##// END OF EJS Templates
manual fixes to docs
Matthias Bussonnier -
Show More
@@ -1,2262 +1,2267 b''
1 """Completion for IPython.
1 """Completion for IPython.
2
2
3 This module started as fork of the rlcompleter module in the Python standard
3 This module started as fork of the rlcompleter module in the Python standard
4 library. The original enhancements made to rlcompleter have been sent
4 library. The original enhancements made to rlcompleter have been sent
5 upstream and were accepted as of Python 2.3,
5 upstream and were accepted as of Python 2.3,
6
6
7 This module now support a wide variety of completion mechanism both available
7 This module now support a wide variety of completion mechanism both available
8 for normal classic Python code, as well as completer for IPython specific
8 for normal classic Python code, as well as completer for IPython specific
9 Syntax like magics.
9 Syntax like magics.
10
10
11 Latex and Unicode completion
11 Latex and Unicode completion
12 ============================
12 ============================
13
13
14 IPython and compatible frontends not only can complete your code, but can help
14 IPython and compatible frontends not only can complete your code, but can help
15 you to input a wide range of characters. In particular we allow you to insert
15 you to input a wide range of characters. In particular we allow you to insert
16 a unicode character using the tab completion mechanism.
16 a unicode character using the tab completion mechanism.
17
17
18 Forward latex/unicode completion
18 Forward latex/unicode completion
19 --------------------------------
19 --------------------------------
20
20
21 Forward completion allows you to easily type a unicode character using its latex
21 Forward completion allows you to easily type a unicode character using its latex
22 name, or unicode long description. To do so type a backslash follow by the
22 name, or unicode long description. To do so type a backslash follow by the
23 relevant name and press tab:
23 relevant name and press tab:
24
24
25
25
26 Using latex completion:
26 Using latex completion:
27
27
28 .. code::
28 .. code::
29
29
30 \\alpha<tab>
30 \\alpha<tab>
31 Ξ±
31 Ξ±
32
32
33 or using unicode completion:
33 or using unicode completion:
34
34
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
42 Only valid Python identifiers will complete. Combining characters (like arrow or
42 Only valid Python identifiers will complete. Combining characters (like arrow or
43 dots) are also available, unlike latex they need to be put after the their
43 dots) are also available, unlike latex they need to be put after the their
44 counterpart that is to say, `F\\\\vec<tab>` is correct, not `\\\\vec<tab>F`.
44 counterpart that is to say, `F\\\\vec<tab>` is correct, not `\\\\vec<tab>F`.
45
45
46 Some browsers are known to display combining characters incorrectly.
46 Some browsers are known to display combining characters incorrectly.
47
47
48 Backward latex completion
48 Backward latex completion
49 -------------------------
49 -------------------------
50
50
51 It is sometime challenging to know how to type a character, if you are using
51 It is sometime challenging to know how to type a character, if you are using
52 IPython, or any compatible frontend you can prepend backslash to the character
52 IPython, or any compatible frontend you can prepend backslash to the character
53 and press `<tab>` to expand it to its latex form.
53 and press `<tab>` to expand it to its latex form.
54
54
55 .. code::
55 .. code::
56
56
57 \\Ξ±<tab>
57 \\Ξ±<tab>
58 \\alpha
58 \\alpha
59
59
60
60
61 Both forward and backward completions can be deactivated by setting the
61 Both forward and backward completions can be deactivated by setting the
62 ``Completer.backslash_combining_completions`` option to ``False``.
62 ``Completer.backslash_combining_completions`` option to ``False``.
63
63
64
64
65 Experimental
65 Experimental
66 ============
66 ============
67
67
68 Starting with IPython 6.0, this module can make use of the Jedi library to
68 Starting with IPython 6.0, this module can make use of the Jedi library to
69 generate completions both using static analysis of the code, and dynamically
69 generate completions both using static analysis of the code, and dynamically
70 inspecting multiple namespaces. Jedi is an autocompletion and static analysis
70 inspecting multiple namespaces. Jedi is an autocompletion and static analysis
71 for Python. The APIs attached to this new mechanism is unstable and will
71 for Python. The APIs attached to this new mechanism is unstable and will
72 raise unless use in an :any:`provisionalcompleter` context manager.
72 raise unless use in an :any:`provisionalcompleter` context manager.
73
73
74 You will find that the following are experimental:
74 You will find that the following are experimental:
75
75
76 - :any:`provisionalcompleter`
76 - :any:`provisionalcompleter`
77 - :any:`IPCompleter.completions`
77 - :any:`IPCompleter.completions`
78 - :any:`Completion`
78 - :any:`Completion`
79 - :any:`rectify_completions`
79 - :any:`rectify_completions`
80
80
81 .. note::
81 .. note::
82
82
83 better name for :any:`rectify_completions` ?
83 better name for :any:`rectify_completions` ?
84
84
85 We welcome any feedback on these new API, and we also encourage you to try this
85 We welcome any feedback on these new API, and we also encourage you to try this
86 module in debug mode (start IPython with ``--Completer.debug=True``) in order
86 module in debug mode (start IPython with ``--Completer.debug=True``) in order
87 to have extra logging information if :any:`jedi` is crashing, or if current
87 to have extra logging information if :any:`jedi` is crashing, or if current
88 IPython completer pending deprecations are returning results not yet handled
88 IPython completer pending deprecations are returning results not yet handled
89 by :any:`jedi`
89 by :any:`jedi`
90
90
91 Using Jedi for tab completion allow snippets like the following to work without
91 Using Jedi for tab completion allow snippets like the following to work without
92 having to execute any code:
92 having to execute any code:
93
93
94 >>> myvar = ['hello', 42]
94 >>> myvar = ['hello', 42]
95 ... myvar[1].bi<tab>
95 ... myvar[1].bi<tab>
96
96
97 Tab completion will be able to infer that ``myvar[1]`` is a real number without
97 Tab completion will be able to infer that ``myvar[1]`` is a real number without
98 executing any code unlike the previously available ``IPCompleter.greedy``
98 executing any code unlike the previously available ``IPCompleter.greedy``
99 option.
99 option.
100
100
101 Be sure to update :any:`jedi` to the latest stable version or to try the
101 Be sure to update :any:`jedi` to the latest stable version or to try the
102 current development version to get better completions.
102 current development version to get better completions.
103 """
103 """
104
104
105
105
106 # Copyright (c) IPython Development Team.
106 # Copyright (c) IPython Development Team.
107 # Distributed under the terms of the Modified BSD License.
107 # Distributed under the terms of the Modified BSD License.
108 #
108 #
109 # Some of this code originated from rlcompleter in the Python standard library
109 # Some of this code originated from rlcompleter in the Python standard library
110 # Copyright (C) 2001 Python Software Foundation, www.python.org
110 # Copyright (C) 2001 Python Software Foundation, www.python.org
111
111
112
112
113 import builtins as builtin_mod
113 import builtins as builtin_mod
114 import glob
114 import glob
115 import inspect
115 import inspect
116 import itertools
116 import itertools
117 import keyword
117 import keyword
118 import os
118 import os
119 import re
119 import re
120 import string
120 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 uuid
125 import warnings
125 import warnings
126 from contextlib import contextmanager
126 from contextlib import contextmanager
127 from importlib import import_module
127 from importlib import import_module
128 from types import SimpleNamespace
128 from types import SimpleNamespace
129 from typing import Iterable, Iterator, List, Tuple, Union, Any, Sequence, Dict, NamedTuple, Pattern, Optional
129 from typing import Iterable, Iterator, List, Tuple, Union, Any, Sequence, Dict, NamedTuple, Pattern, Optional
130
130
131 from IPython.core.error import TryNext
131 from IPython.core.error import TryNext
132 from IPython.core.inputtransformer2 import ESC_MAGIC
132 from IPython.core.inputtransformer2 import ESC_MAGIC
133 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
133 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
134 from IPython.core.oinspect import InspectColors
134 from IPython.core.oinspect import InspectColors
135 from IPython.utils import generics
135 from IPython.utils import generics
136 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
137 from IPython.utils.path import ensure_dir_exists
138 from IPython.utils.process import arg_split
138 from IPython.utils.process import arg_split
139 from traitlets import Bool, Enum, Int, List as ListTrait, Unicode, default, observe
139 from traitlets import Bool, Enum, Int, List as ListTrait, Unicode, default, observe
140 from traitlets.config.configurable import Configurable
140 from traitlets.config.configurable import Configurable
141
141
142 import __main__
142 import __main__
143
143
144 # skip module docstests
144 # skip module docstests
145 skip_doctest = True
145 skip_doctest = True
146
146
147 try:
147 try:
148 import jedi
148 import jedi
149 jedi.settings.case_insensitive_completion = False
149 jedi.settings.case_insensitive_completion = False
150 import jedi.api.helpers
150 import jedi.api.helpers
151 import jedi.api.classes
151 import jedi.api.classes
152 JEDI_INSTALLED = True
152 JEDI_INSTALLED = True
153 except ImportError:
153 except ImportError:
154 JEDI_INSTALLED = False
154 JEDI_INSTALLED = False
155 #-----------------------------------------------------------------------------
155 #-----------------------------------------------------------------------------
156 # Globals
156 # Globals
157 #-----------------------------------------------------------------------------
157 #-----------------------------------------------------------------------------
158
158
159 # ranges where we have most of the valid unicode names. We could be more finer
159 # ranges where we have most of the valid unicode names. We could be more finer
160 # grained but is it worth it for performace While unicode have character in the
160 # grained but is it worth it for performace While unicode have character in the
161 # rage 0, 0x110000, we seem to have name for about 10% of those. (131808 as I
161 # rage 0, 0x110000, we seem to have name for about 10% of those. (131808 as I
162 # write this). With below range we cover them all, with a density of ~67%
162 # write this). With below range we cover them all, with a density of ~67%
163 # biggest next gap we consider only adds up about 1% density and there are 600
163 # biggest next gap we consider only adds up about 1% density and there are 600
164 # gaps that would need hard coding.
164 # gaps that would need hard coding.
165 _UNICODE_RANGES = [(32, 0x3134b), (0xe0001, 0xe01f0)]
165 _UNICODE_RANGES = [(32, 0x3134b), (0xe0001, 0xe01f0)]
166
166
167 # Public API
167 # Public API
168 __all__ = ['Completer','IPCompleter']
168 __all__ = ['Completer','IPCompleter']
169
169
170 if sys.platform == 'win32':
170 if sys.platform == 'win32':
171 PROTECTABLES = ' '
171 PROTECTABLES = ' '
172 else:
172 else:
173 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
173 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
174
174
175 # Protect against returning an enormous number of completions which the frontend
175 # Protect against returning an enormous number of completions which the frontend
176 # may have trouble processing.
176 # may have trouble processing.
177 MATCHES_LIMIT = 500
177 MATCHES_LIMIT = 500
178
178
179 _deprecation_readline_sentinel = object()
179 _deprecation_readline_sentinel = object()
180
180
181
181
182 class ProvisionalCompleterWarning(FutureWarning):
182 class ProvisionalCompleterWarning(FutureWarning):
183 """
183 """
184 Exception raise by an experimental feature in this module.
184 Exception raise by an experimental feature in this module.
185
185
186 Wrap code in :any:`provisionalcompleter` context manager if you
186 Wrap code in :any:`provisionalcompleter` context manager if you
187 are certain you want to use an unstable feature.
187 are certain you want to use an unstable feature.
188 """
188 """
189 pass
189 pass
190
190
191 warnings.filterwarnings('error', category=ProvisionalCompleterWarning)
191 warnings.filterwarnings('error', category=ProvisionalCompleterWarning)
192
192
193 @contextmanager
193 @contextmanager
194 def provisionalcompleter(action='ignore'):
194 def provisionalcompleter(action='ignore'):
195 """
195 """
196
196
197
197
198 This context manager has to be used in any place where unstable completer
198 This context manager has to be used in any place where unstable completer
199 behavior and API may be called.
199 behavior and API may be called.
200
200
201 >>> with provisionalcompleter():
201 >>> with provisionalcompleter():
202 ... completer.do_experimental_things() # works
202 ... completer.do_experimental_things() # works
203
203
204 >>> completer.do_experimental_things() # raises.
204 >>> completer.do_experimental_things() # raises.
205
205
206 .. note:: Unstable
206 .. note:: Unstable
207
207
208 By using this context manager you agree that the API in use may change
208 By using this context manager you agree that the API in use may change
209 without warning, and that you won't complain if they do so.
209 without warning, and that you won't complain if they do so.
210
210
211 You also understand that, if the API is not to your liking, you should report
211 You also understand that, if the API is not to your liking, you should report
212 a bug to explain your use case upstream.
212 a bug to explain your use case upstream.
213
213
214 We'll be happy to get your feedback, feature requests, and improvements on
214 We'll be happy to get your feedback, feature requests, and improvements on
215 any of the unstable APIs!
215 any of the unstable APIs!
216 """
216 """
217 with warnings.catch_warnings():
217 with warnings.catch_warnings():
218 warnings.filterwarnings(action, category=ProvisionalCompleterWarning)
218 warnings.filterwarnings(action, category=ProvisionalCompleterWarning)
219 yield
219 yield
220
220
221
221
222 def has_open_quotes(s):
222 def has_open_quotes(s):
223 """Return whether a string has open quotes.
223 """Return whether a string has open quotes.
224
224
225 This simply counts whether the number of quote characters of either type in
225 This simply counts whether the number of quote characters of either type in
226 the string is odd.
226 the string is odd.
227
227
228 Returns
228 Returns
229 -------
229 -------
230 If there is an open quote, the quote character is returned. Else, return
230 If there is an open quote, the quote character is returned. Else, return
231 False.
231 False.
232 """
232 """
233 # We check " first, then ', so complex cases with nested quotes will get
233 # We check " first, then ', so complex cases with nested quotes will get
234 # the " to take precedence.
234 # the " to take precedence.
235 if s.count('"') % 2:
235 if s.count('"') % 2:
236 return '"'
236 return '"'
237 elif s.count("'") % 2:
237 elif s.count("'") % 2:
238 return "'"
238 return "'"
239 else:
239 else:
240 return False
240 return False
241
241
242
242
243 def protect_filename(s, protectables=PROTECTABLES):
243 def protect_filename(s, protectables=PROTECTABLES):
244 """Escape a string to protect certain characters."""
244 """Escape a string to protect certain characters."""
245 if set(s) & set(protectables):
245 if set(s) & set(protectables):
246 if sys.platform == "win32":
246 if sys.platform == "win32":
247 return '"' + s + '"'
247 return '"' + s + '"'
248 else:
248 else:
249 return "".join(("\\" + c if c in protectables else c) for c in s)
249 return "".join(("\\" + c if c in protectables else c) for c in s)
250 else:
250 else:
251 return s
251 return s
252
252
253
253
254 def expand_user(path:str) -> Tuple[str, bool, str]:
254 def expand_user(path:str) -> Tuple[str, bool, str]:
255 """Expand ``~``-style usernames in strings.
255 """Expand ``~``-style usernames in strings.
256
256
257 This is similar to :func:`os.path.expanduser`, but it computes and returns
257 This is similar to :func:`os.path.expanduser`, but it computes and returns
258 extra information that will be useful if the input was being used in
258 extra information that will be useful if the input was being used in
259 computing completions, and you wish to return the completions with the
259 computing completions, and you wish to return the completions with the
260 original '~' instead of its expanded value.
260 original '~' instead of its expanded value.
261
261
262 Parameters
262 Parameters
263 ----------
263 ----------
264 path : str
264 path : str
265 String to be expanded. If no ~ is present, the output is the same as the
265 String to be expanded. If no ~ is present, the output is the same as the
266 input.
266 input.
267
267
268 Returns
268 Returns
269 -------
269 -------
270 newpath : str
270 newpath : str
271 Result of ~ expansion in the input path.
271 Result of ~ expansion in the input path.
272 tilde_expand : bool
272 tilde_expand : bool
273 Whether any expansion was performed or not.
273 Whether any expansion was performed or not.
274 tilde_val : str
274 tilde_val : str
275 The value that ~ was replaced with.
275 The value that ~ was replaced with.
276 """
276 """
277 # Default values
277 # Default values
278 tilde_expand = False
278 tilde_expand = False
279 tilde_val = ''
279 tilde_val = ''
280 newpath = path
280 newpath = path
281
281
282 if path.startswith('~'):
282 if path.startswith('~'):
283 tilde_expand = True
283 tilde_expand = True
284 rest = len(path)-1
284 rest = len(path)-1
285 newpath = os.path.expanduser(path)
285 newpath = os.path.expanduser(path)
286 if rest:
286 if rest:
287 tilde_val = newpath[:-rest]
287 tilde_val = newpath[:-rest]
288 else:
288 else:
289 tilde_val = newpath
289 tilde_val = newpath
290
290
291 return newpath, tilde_expand, tilde_val
291 return newpath, tilde_expand, tilde_val
292
292
293
293
294 def compress_user(path:str, tilde_expand:bool, tilde_val:str) -> str:
294 def compress_user(path:str, tilde_expand:bool, tilde_val:str) -> str:
295 """Does the opposite of expand_user, with its outputs.
295 """Does the opposite of expand_user, with its outputs.
296 """
296 """
297 if tilde_expand:
297 if tilde_expand:
298 return path.replace(tilde_val, '~')
298 return path.replace(tilde_val, '~')
299 else:
299 else:
300 return path
300 return path
301
301
302
302
303 def completions_sorting_key(word):
303 def completions_sorting_key(word):
304 """key for sorting completions
304 """key for sorting completions
305
305
306 This does several things:
306 This does several things:
307
307
308 - Demote any completions starting with underscores to the end
308 - Demote any completions starting with underscores to the end
309 - Insert any %magic and %%cellmagic completions in the alphabetical order
309 - Insert any %magic and %%cellmagic completions in the alphabetical order
310 by their name
310 by their name
311 """
311 """
312 prio1, prio2 = 0, 0
312 prio1, prio2 = 0, 0
313
313
314 if word.startswith('__'):
314 if word.startswith('__'):
315 prio1 = 2
315 prio1 = 2
316 elif word.startswith('_'):
316 elif word.startswith('_'):
317 prio1 = 1
317 prio1 = 1
318
318
319 if word.endswith('='):
319 if word.endswith('='):
320 prio1 = -1
320 prio1 = -1
321
321
322 if word.startswith('%%'):
322 if word.startswith('%%'):
323 # If there's another % in there, this is something else, so leave it alone
323 # If there's another % in there, this is something else, so leave it alone
324 if not "%" in word[2:]:
324 if not "%" in word[2:]:
325 word = word[2:]
325 word = word[2:]
326 prio2 = 2
326 prio2 = 2
327 elif word.startswith('%'):
327 elif word.startswith('%'):
328 if not "%" in word[1:]:
328 if not "%" in word[1:]:
329 word = word[1:]
329 word = word[1:]
330 prio2 = 1
330 prio2 = 1
331
331
332 return prio1, word, prio2
332 return prio1, word, prio2
333
333
334
334
335 class _FakeJediCompletion:
335 class _FakeJediCompletion:
336 """
336 """
337 This is a workaround to communicate to the UI that Jedi has crashed and to
337 This is a workaround to communicate to the UI that Jedi has crashed and to
338 report a bug. Will be used only id :any:`IPCompleter.debug` is set to true.
338 report a bug. Will be used only id :any:`IPCompleter.debug` is set to true.
339
339
340 Added in IPython 6.0 so should likely be removed for 7.0
340 Added in IPython 6.0 so should likely be removed for 7.0
341
341
342 """
342 """
343
343
344 def __init__(self, name):
344 def __init__(self, name):
345
345
346 self.name = name
346 self.name = name
347 self.complete = name
347 self.complete = name
348 self.type = 'crashed'
348 self.type = 'crashed'
349 self.name_with_symbols = name
349 self.name_with_symbols = name
350 self.signature = ''
350 self.signature = ''
351 self._origin = 'fake'
351 self._origin = 'fake'
352
352
353 def __repr__(self):
353 def __repr__(self):
354 return '<Fake completion object jedi has crashed>'
354 return '<Fake completion object jedi has crashed>'
355
355
356
356
357 class Completion:
357 class Completion:
358 """
358 """
359 Completion object used and return by IPython completers.
359 Completion object used and return by IPython completers.
360
360
361 .. warning:: Unstable
361 .. warning:: Unstable
362
362
363 This function is unstable, API may change without warning.
363 This function is unstable, API may change without warning.
364 It will also raise unless use in proper context manager.
364 It will also raise unless use in proper context manager.
365
365
366 This act as a middle ground :any:`Completion` object between the
366 This act as a middle ground :any:`Completion` object between the
367 :any:`jedi.api.classes.Completion` object and the Prompt Toolkit completion
367 :any:`jedi.api.classes.Completion` object and the Prompt Toolkit completion
368 object. While Jedi need a lot of information about evaluator and how the
368 object. While Jedi need a lot of information about evaluator and how the
369 code should be ran/inspected, PromptToolkit (and other frontend) mostly
369 code should be ran/inspected, PromptToolkit (and other frontend) mostly
370 need user facing information.
370 need user facing information.
371
371
372 - Which range should be replaced replaced by what.
372 - Which range should be replaced replaced by what.
373 - Some metadata (like completion type), or meta information to displayed to
373 - Some metadata (like completion type), or meta information to displayed to
374 the use user.
374 the use user.
375
375
376 For debugging purpose we can also store the origin of the completion (``jedi``,
376 For debugging purpose we can also store the origin of the completion (``jedi``,
377 ``IPython.python_matches``, ``IPython.magics_matches``...).
377 ``IPython.python_matches``, ``IPython.magics_matches``...).
378 """
378 """
379
379
380 __slots__ = ['start', 'end', 'text', 'type', 'signature', '_origin']
380 __slots__ = ['start', 'end', 'text', 'type', 'signature', '_origin']
381
381
382 def __init__(self, start: int, end: int, text: str, *, type: str=None, _origin='', signature='') -> None:
382 def __init__(self, start: int, end: int, text: str, *, type: str=None, _origin='', signature='') -> None:
383 warnings.warn("``Completion`` is a provisional API (as of IPython 6.0). "
383 warnings.warn("``Completion`` is a provisional API (as of IPython 6.0). "
384 "It may change without warnings. "
384 "It may change without warnings. "
385 "Use in corresponding context manager.",
385 "Use in corresponding context manager.",
386 category=ProvisionalCompleterWarning, stacklevel=2)
386 category=ProvisionalCompleterWarning, stacklevel=2)
387
387
388 self.start = start
388 self.start = start
389 self.end = end
389 self.end = end
390 self.text = text
390 self.text = text
391 self.type = type
391 self.type = type
392 self.signature = signature
392 self.signature = signature
393 self._origin = _origin
393 self._origin = _origin
394
394
395 def __repr__(self):
395 def __repr__(self):
396 return '<Completion start=%s end=%s text=%r type=%r, signature=%r,>' % \
396 return '<Completion start=%s end=%s text=%r type=%r, signature=%r,>' % \
397 (self.start, self.end, self.text, self.type or '?', self.signature or '?')
397 (self.start, self.end, self.text, self.type or '?', self.signature or '?')
398
398
399 def __eq__(self, other)->Bool:
399 def __eq__(self, other)->Bool:
400 """
400 """
401 Equality and hash do not hash the type (as some completer may not be
401 Equality and hash do not hash the type (as some completer may not be
402 able to infer the type), but are use to (partially) de-duplicate
402 able to infer the type), but are use to (partially) de-duplicate
403 completion.
403 completion.
404
404
405 Completely de-duplicating completion is a bit tricker that just
405 Completely de-duplicating completion is a bit tricker that just
406 comparing as it depends on surrounding text, which Completions are not
406 comparing as it depends on surrounding text, which Completions are not
407 aware of.
407 aware of.
408 """
408 """
409 return self.start == other.start and \
409 return self.start == other.start and \
410 self.end == other.end and \
410 self.end == other.end and \
411 self.text == other.text
411 self.text == other.text
412
412
413 def __hash__(self):
413 def __hash__(self):
414 return hash((self.start, self.end, self.text))
414 return hash((self.start, self.end, self.text))
415
415
416
416
417 _IC = Iterable[Completion]
417 _IC = Iterable[Completion]
418
418
419
419
420 def _deduplicate_completions(text: str, completions: _IC)-> _IC:
420 def _deduplicate_completions(text: str, completions: _IC)-> _IC:
421 """
421 """
422 Deduplicate a set of completions.
422 Deduplicate a set of completions.
423
423
424 .. warning:: Unstable
424 .. warning:: Unstable
425
425
426 This function is unstable, API may change without warning.
426 This function is unstable, API may change without warning.
427
427
428 Parameters
428 Parameters
429 ----------
429 ----------
430 text: str
430 text: str
431 text that should be completed.
431 text that should be completed.
432 completions: Iterator[Completion]
432 completions: Iterator[Completion]
433 iterator over the completions to deduplicate
433 iterator over the completions to deduplicate
434
434
435 Yields
435 Yields
436 ------
436 ------
437 `Completions` objects
437 `Completions` objects
438
438
439
439
440 Completions coming from multiple sources, may be different but end up having
440 Completions coming from multiple sources, may be different but end up having
441 the same effect when applied to ``text``. If this is the case, this will
441 the same effect when applied to ``text``. If this is the case, this will
442 consider completions as equal and only emit the first encountered.
442 consider completions as equal and only emit the first encountered.
443
443
444 Not folded in `completions()` yet for debugging purpose, and to detect when
444 Not folded in `completions()` yet for debugging purpose, and to detect when
445 the IPython completer does return things that Jedi does not, but should be
445 the IPython completer does return things that Jedi does not, but should be
446 at some point.
446 at some point.
447 """
447 """
448 completions = list(completions)
448 completions = list(completions)
449 if not completions:
449 if not completions:
450 return
450 return
451
451
452 new_start = min(c.start for c in completions)
452 new_start = min(c.start for c in completions)
453 new_end = max(c.end for c in completions)
453 new_end = max(c.end for c in completions)
454
454
455 seen = set()
455 seen = set()
456 for c in completions:
456 for c in completions:
457 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
457 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
458 if new_text not in seen:
458 if new_text not in seen:
459 yield c
459 yield c
460 seen.add(new_text)
460 seen.add(new_text)
461
461
462
462
463 def rectify_completions(text: str, completions: _IC, *, _debug=False)->_IC:
463 def rectify_completions(text: str, completions: _IC, *, _debug=False)->_IC:
464 """
464 """
465 Rectify a set of completions to all have the same ``start`` and ``end``
465 Rectify a set of completions to all have the same ``start`` and ``end``
466
466
467 .. warning:: Unstable
467 .. warning:: Unstable
468
468
469 This function is unstable, API may change without warning.
469 This function is unstable, API may change without warning.
470 It will also raise unless use in proper context manager.
470 It will also raise unless use in proper context manager.
471
471
472 Parameters
472 Parameters
473 ----------
473 ----------
474 text: str
474 text: str
475 text that should be completed.
475 text that should be completed.
476 completions: Iterator[Completion]
476 completions: Iterator[Completion]
477 iterator over the completions to rectify
477 iterator over the completions to rectify
478
478
479
479 Notes
480 -----
480 :any:`jedi.api.classes.Completion` s returned by Jedi may not have the same start and end, though
481 :any:`jedi.api.classes.Completion` s returned by Jedi may not have the same start and end, though
481 the Jupyter Protocol requires them to behave like so. This will readjust
482 the Jupyter Protocol requires them to behave like so. This will readjust
482 the completion to have the same ``start`` and ``end`` by padding both
483 the completion to have the same ``start`` and ``end`` by padding both
483 extremities with surrounding text.
484 extremities with surrounding text.
484
485
485 During stabilisation should support a ``_debug`` option to log which
486 During stabilisation should support a ``_debug`` option to log which
486 completion are return by the IPython completer and not found in Jedi in
487 completion are return by the IPython completer and not found in Jedi in
487 order to make upstream bug report.
488 order to make upstream bug report.
488 """
489 """
489 warnings.warn("`rectify_completions` is a provisional API (as of IPython 6.0). "
490 warnings.warn("`rectify_completions` is a provisional API (as of IPython 6.0). "
490 "It may change without warnings. "
491 "It may change without warnings. "
491 "Use in corresponding context manager.",
492 "Use in corresponding context manager.",
492 category=ProvisionalCompleterWarning, stacklevel=2)
493 category=ProvisionalCompleterWarning, stacklevel=2)
493
494
494 completions = list(completions)
495 completions = list(completions)
495 if not completions:
496 if not completions:
496 return
497 return
497 starts = (c.start for c in completions)
498 starts = (c.start for c in completions)
498 ends = (c.end for c in completions)
499 ends = (c.end for c in completions)
499
500
500 new_start = min(starts)
501 new_start = min(starts)
501 new_end = max(ends)
502 new_end = max(ends)
502
503
503 seen_jedi = set()
504 seen_jedi = set()
504 seen_python_matches = set()
505 seen_python_matches = set()
505 for c in completions:
506 for c in completions:
506 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
507 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
507 if c._origin == 'jedi':
508 if c._origin == 'jedi':
508 seen_jedi.add(new_text)
509 seen_jedi.add(new_text)
509 elif c._origin == 'IPCompleter.python_matches':
510 elif c._origin == 'IPCompleter.python_matches':
510 seen_python_matches.add(new_text)
511 seen_python_matches.add(new_text)
511 yield Completion(new_start, new_end, new_text, type=c.type, _origin=c._origin, signature=c.signature)
512 yield Completion(new_start, new_end, new_text, type=c.type, _origin=c._origin, signature=c.signature)
512 diff = seen_python_matches.difference(seen_jedi)
513 diff = seen_python_matches.difference(seen_jedi)
513 if diff and _debug:
514 if diff and _debug:
514 print('IPython.python matches have extras:', diff)
515 print('IPython.python matches have extras:', diff)
515
516
516
517
517 if sys.platform == 'win32':
518 if sys.platform == 'win32':
518 DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?'
519 DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?'
519 else:
520 else:
520 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
521 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
521
522
522 GREEDY_DELIMS = ' =\r\n'
523 GREEDY_DELIMS = ' =\r\n'
523
524
524
525
525 class CompletionSplitter(object):
526 class CompletionSplitter(object):
526 """An object to split an input line in a manner similar to readline.
527 """An object to split an input line in a manner similar to readline.
527
528
528 By having our own implementation, we can expose readline-like completion in
529 By having our own implementation, we can expose readline-like completion in
529 a uniform manner to all frontends. This object only needs to be given the
530 a uniform manner to all frontends. This object only needs to be given the
530 line of text to be split and the cursor position on said line, and it
531 line of text to be split and the cursor position on said line, and it
531 returns the 'word' to be completed on at the cursor after splitting the
532 returns the 'word' to be completed on at the cursor after splitting the
532 entire line.
533 entire line.
533
534
534 What characters are used as splitting delimiters can be controlled by
535 What characters are used as splitting delimiters can be controlled by
535 setting the ``delims`` attribute (this is a property that internally
536 setting the ``delims`` attribute (this is a property that internally
536 automatically builds the necessary regular expression)"""
537 automatically builds the necessary regular expression)"""
537
538
538 # Private interface
539 # Private interface
539
540
540 # A string of delimiter characters. The default value makes sense for
541 # A string of delimiter characters. The default value makes sense for
541 # IPython's most typical usage patterns.
542 # IPython's most typical usage patterns.
542 _delims = DELIMS
543 _delims = DELIMS
543
544
544 # The expression (a normal string) to be compiled into a regular expression
545 # The expression (a normal string) to be compiled into a regular expression
545 # for actual splitting. We store it as an attribute mostly for ease of
546 # for actual splitting. We store it as an attribute mostly for ease of
546 # debugging, since this type of code can be so tricky to debug.
547 # debugging, since this type of code can be so tricky to debug.
547 _delim_expr = None
548 _delim_expr = None
548
549
549 # The regular expression that does the actual splitting
550 # The regular expression that does the actual splitting
550 _delim_re = None
551 _delim_re = None
551
552
552 def __init__(self, delims=None):
553 def __init__(self, delims=None):
553 delims = CompletionSplitter._delims if delims is None else delims
554 delims = CompletionSplitter._delims if delims is None else delims
554 self.delims = delims
555 self.delims = delims
555
556
556 @property
557 @property
557 def delims(self):
558 def delims(self):
558 """Return the string of delimiter characters."""
559 """Return the string of delimiter characters."""
559 return self._delims
560 return self._delims
560
561
561 @delims.setter
562 @delims.setter
562 def delims(self, delims):
563 def delims(self, delims):
563 """Set the delimiters for line splitting."""
564 """Set the delimiters for line splitting."""
564 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
565 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
565 self._delim_re = re.compile(expr)
566 self._delim_re = re.compile(expr)
566 self._delims = delims
567 self._delims = delims
567 self._delim_expr = expr
568 self._delim_expr = expr
568
569
569 def split_line(self, line, cursor_pos=None):
570 def split_line(self, line, cursor_pos=None):
570 """Split a line of text with a cursor at the given position.
571 """Split a line of text with a cursor at the given position.
571 """
572 """
572 l = line if cursor_pos is None else line[:cursor_pos]
573 l = line if cursor_pos is None else line[:cursor_pos]
573 return self._delim_re.split(l)[-1]
574 return self._delim_re.split(l)[-1]
574
575
575
576
576
577
577 class Completer(Configurable):
578 class Completer(Configurable):
578
579
579 greedy = Bool(False,
580 greedy = Bool(False,
580 help="""Activate greedy completion
581 help="""Activate greedy completion
581 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
582 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
582
583
583 This will enable completion on elements of lists, results of function calls, etc.,
584 This will enable completion on elements of lists, results of function calls, etc.,
584 but can be unsafe because the code is actually evaluated on TAB.
585 but can be unsafe because the code is actually evaluated on TAB.
585 """
586 """
586 ).tag(config=True)
587 ).tag(config=True)
587
588
588 use_jedi = Bool(default_value=JEDI_INSTALLED,
589 use_jedi = Bool(default_value=JEDI_INSTALLED,
589 help="Experimental: Use Jedi to generate autocompletions. "
590 help="Experimental: Use Jedi to generate autocompletions. "
590 "Default to True if jedi is installed.").tag(config=True)
591 "Default to True if jedi is installed.").tag(config=True)
591
592
592 jedi_compute_type_timeout = Int(default_value=400,
593 jedi_compute_type_timeout = Int(default_value=400,
593 help="""Experimental: restrict time (in milliseconds) during which Jedi can compute types.
594 help="""Experimental: restrict time (in milliseconds) during which Jedi can compute types.
594 Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt
595 Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt
595 performance by preventing jedi to build its cache.
596 performance by preventing jedi to build its cache.
596 """).tag(config=True)
597 """).tag(config=True)
597
598
598 debug = Bool(default_value=False,
599 debug = Bool(default_value=False,
599 help='Enable debug for the Completer. Mostly print extra '
600 help='Enable debug for the Completer. Mostly print extra '
600 'information for experimental jedi integration.')\
601 'information for experimental jedi integration.')\
601 .tag(config=True)
602 .tag(config=True)
602
603
603 backslash_combining_completions = Bool(True,
604 backslash_combining_completions = Bool(True,
604 help="Enable unicode completions, e.g. \\alpha<tab> . "
605 help="Enable unicode completions, e.g. \\alpha<tab> . "
605 "Includes completion of latex commands, unicode names, and expanding "
606 "Includes completion of latex commands, unicode names, and expanding "
606 "unicode characters back to latex commands.").tag(config=True)
607 "unicode characters back to latex commands.").tag(config=True)
607
608
608
609
609
610
610 def __init__(self, namespace=None, global_namespace=None, **kwargs):
611 def __init__(self, namespace=None, global_namespace=None, **kwargs):
611 """Create a new completer for the command line.
612 """Create a new completer for the command line.
612
613
613 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
614 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
614
615
615 If unspecified, the default namespace where completions are performed
616 If unspecified, the default namespace where completions are performed
616 is __main__ (technically, __main__.__dict__). Namespaces should be
617 is __main__ (technically, __main__.__dict__). Namespaces should be
617 given as dictionaries.
618 given as dictionaries.
618
619
619 An optional second namespace can be given. This allows the completer
620 An optional second namespace can be given. This allows the completer
620 to handle cases where both the local and global scopes need to be
621 to handle cases where both the local and global scopes need to be
621 distinguished.
622 distinguished.
622 """
623 """
623
624
624 # Don't bind to namespace quite yet, but flag whether the user wants a
625 # Don't bind to namespace quite yet, but flag whether the user wants a
625 # specific namespace or to use __main__.__dict__. This will allow us
626 # specific namespace or to use __main__.__dict__. This will allow us
626 # to bind to __main__.__dict__ at completion time, not now.
627 # to bind to __main__.__dict__ at completion time, not now.
627 if namespace is None:
628 if namespace is None:
628 self.use_main_ns = True
629 self.use_main_ns = True
629 else:
630 else:
630 self.use_main_ns = False
631 self.use_main_ns = False
631 self.namespace = namespace
632 self.namespace = namespace
632
633
633 # The global namespace, if given, can be bound directly
634 # The global namespace, if given, can be bound directly
634 if global_namespace is None:
635 if global_namespace is None:
635 self.global_namespace = {}
636 self.global_namespace = {}
636 else:
637 else:
637 self.global_namespace = global_namespace
638 self.global_namespace = global_namespace
638
639
639 self.custom_matchers = []
640 self.custom_matchers = []
640
641
641 super(Completer, self).__init__(**kwargs)
642 super(Completer, self).__init__(**kwargs)
642
643
643 def complete(self, text, state):
644 def complete(self, text, state):
644 """Return the next possible completion for 'text'.
645 """Return the next possible completion for 'text'.
645
646
646 This is called successively with state == 0, 1, 2, ... until it
647 This is called successively with state == 0, 1, 2, ... until it
647 returns None. The completion should begin with 'text'.
648 returns None. The completion should begin with 'text'.
648
649
649 """
650 """
650 if self.use_main_ns:
651 if self.use_main_ns:
651 self.namespace = __main__.__dict__
652 self.namespace = __main__.__dict__
652
653
653 if state == 0:
654 if state == 0:
654 if "." in text:
655 if "." in text:
655 self.matches = self.attr_matches(text)
656 self.matches = self.attr_matches(text)
656 else:
657 else:
657 self.matches = self.global_matches(text)
658 self.matches = self.global_matches(text)
658 try:
659 try:
659 return self.matches[state]
660 return self.matches[state]
660 except IndexError:
661 except IndexError:
661 return None
662 return None
662
663
663 def global_matches(self, text):
664 def global_matches(self, text):
664 """Compute matches when text is a simple name.
665 """Compute matches when text is a simple name.
665
666
666 Return a list of all keywords, built-in functions and names currently
667 Return a list of all keywords, built-in functions and names currently
667 defined in self.namespace or self.global_namespace that match.
668 defined in self.namespace or self.global_namespace that match.
668
669
669 """
670 """
670 matches = []
671 matches = []
671 match_append = matches.append
672 match_append = matches.append
672 n = len(text)
673 n = len(text)
673 for lst in [keyword.kwlist,
674 for lst in [keyword.kwlist,
674 builtin_mod.__dict__.keys(),
675 builtin_mod.__dict__.keys(),
675 self.namespace.keys(),
676 self.namespace.keys(),
676 self.global_namespace.keys()]:
677 self.global_namespace.keys()]:
677 for word in lst:
678 for word in lst:
678 if word[:n] == text and word != "__builtins__":
679 if word[:n] == text and word != "__builtins__":
679 match_append(word)
680 match_append(word)
680
681
681 snake_case_re = re.compile(r"[^_]+(_[^_]+)+?\Z")
682 snake_case_re = re.compile(r"[^_]+(_[^_]+)+?\Z")
682 for lst in [self.namespace.keys(),
683 for lst in [self.namespace.keys(),
683 self.global_namespace.keys()]:
684 self.global_namespace.keys()]:
684 shortened = {"_".join([sub[0] for sub in word.split('_')]) : word
685 shortened = {"_".join([sub[0] for sub in word.split('_')]) : word
685 for word in lst if snake_case_re.match(word)}
686 for word in lst if snake_case_re.match(word)}
686 for word in shortened.keys():
687 for word in shortened.keys():
687 if word[:n] == text and word != "__builtins__":
688 if word[:n] == text and word != "__builtins__":
688 match_append(shortened[word])
689 match_append(shortened[word])
689 return matches
690 return matches
690
691
691 def attr_matches(self, text):
692 def attr_matches(self, text):
692 """Compute matches when text contains a dot.
693 """Compute matches when text contains a dot.
693
694
694 Assuming the text is of the form NAME.NAME....[NAME], and is
695 Assuming the text is of the form NAME.NAME....[NAME], and is
695 evaluatable in self.namespace or self.global_namespace, it will be
696 evaluatable in self.namespace or self.global_namespace, it will be
696 evaluated and its attributes (as revealed by dir()) are used as
697 evaluated and its attributes (as revealed by dir()) are used as
697 possible completions. (For class instances, class members are
698 possible completions. (For class instances, class members are
698 also considered.)
699 also considered.)
699
700
700 WARNING: this can still invoke arbitrary C code, if an object
701 WARNING: this can still invoke arbitrary C code, if an object
701 with a __getattr__ hook is evaluated.
702 with a __getattr__ hook is evaluated.
702
703
703 """
704 """
704
705
705 # Another option, seems to work great. Catches things like ''.<tab>
706 # Another option, seems to work great. Catches things like ''.<tab>
706 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
707 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
707
708
708 if m:
709 if m:
709 expr, attr = m.group(1, 3)
710 expr, attr = m.group(1, 3)
710 elif self.greedy:
711 elif self.greedy:
711 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
712 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
712 if not m2:
713 if not m2:
713 return []
714 return []
714 expr, attr = m2.group(1,2)
715 expr, attr = m2.group(1,2)
715 else:
716 else:
716 return []
717 return []
717
718
718 try:
719 try:
719 obj = eval(expr, self.namespace)
720 obj = eval(expr, self.namespace)
720 except:
721 except:
721 try:
722 try:
722 obj = eval(expr, self.global_namespace)
723 obj = eval(expr, self.global_namespace)
723 except:
724 except:
724 return []
725 return []
725
726
726 if self.limit_to__all__ and hasattr(obj, '__all__'):
727 if self.limit_to__all__ and hasattr(obj, '__all__'):
727 words = get__all__entries(obj)
728 words = get__all__entries(obj)
728 else:
729 else:
729 words = dir2(obj)
730 words = dir2(obj)
730
731
731 try:
732 try:
732 words = generics.complete_object(obj, words)
733 words = generics.complete_object(obj, words)
733 except TryNext:
734 except TryNext:
734 pass
735 pass
735 except AssertionError:
736 except AssertionError:
736 raise
737 raise
737 except Exception:
738 except Exception:
738 # Silence errors from completion function
739 # Silence errors from completion function
739 #raise # dbg
740 #raise # dbg
740 pass
741 pass
741 # Build match list to return
742 # Build match list to return
742 n = len(attr)
743 n = len(attr)
743 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
744 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
744
745
745
746
746 def get__all__entries(obj):
747 def get__all__entries(obj):
747 """returns the strings in the __all__ attribute"""
748 """returns the strings in the __all__ attribute"""
748 try:
749 try:
749 words = getattr(obj, '__all__')
750 words = getattr(obj, '__all__')
750 except:
751 except:
751 return []
752 return []
752
753
753 return [w for w in words if isinstance(w, str)]
754 return [w for w in words if isinstance(w, str)]
754
755
755
756
756 def match_dict_keys(keys: List[Union[str, bytes, Tuple[Union[str, bytes]]]], prefix: str, delims: str,
757 def match_dict_keys(keys: List[Union[str, bytes, Tuple[Union[str, bytes]]]], prefix: str, delims: str,
757 extra_prefix: Optional[Tuple[str, bytes]]=None) -> Tuple[str, int, List[str]]:
758 extra_prefix: Optional[Tuple[str, bytes]]=None) -> Tuple[str, int, List[str]]:
758 """Used by dict_key_matches, matching the prefix to a list of keys
759 """Used by dict_key_matches, matching the prefix to a list of keys
759
760
760 Parameters
761 Parameters
761 ==========
762 ==========
762 keys:
763 keys:
763 list of keys in dictionary currently being completed.
764 list of keys in dictionary currently being completed.
764 prefix:
765 prefix:
765 Part of the text already typed by the user. E.g. `mydict[b'fo`
766 Part of the text already typed by the user. E.g. `mydict[b'fo`
766 delims:
767 delims:
767 String of delimiters to consider when finding the current key.
768 String of delimiters to consider when finding the current key.
768 extra_prefix: optional
769 extra_prefix: optional
769 Part of the text already typed in multi-key index cases. E.g. for
770 Part of the text already typed in multi-key index cases. E.g. for
770 `mydict['foo', "bar", 'b`, this would be `('foo', 'bar')`.
771 `mydict['foo', "bar", 'b`, this would be `('foo', 'bar')`.
771
772
772 Returns
773 Returns
773 =======
774 =======
774
775
775 A tuple of three elements: ``quote``, ``token_start``, ``matched``, with
776 A tuple of three elements: ``quote``, ``token_start``, ``matched``, with
776 ``quote`` being the quote that need to be used to close current string.
777 ``quote`` being the quote that need to be used to close current string.
777 ``token_start`` the position where the replacement should start occurring,
778 ``token_start`` the position where the replacement should start occurring,
778 ``matches`` a list of replacement/completion
779 ``matches`` a list of replacement/completion
779
780
780 """
781 """
781 prefix_tuple = extra_prefix if extra_prefix else ()
782 prefix_tuple = extra_prefix if extra_prefix else ()
782 Nprefix = len(prefix_tuple)
783 Nprefix = len(prefix_tuple)
783 def filter_prefix_tuple(key):
784 def filter_prefix_tuple(key):
784 # Reject too short keys
785 # Reject too short keys
785 if len(key) <= Nprefix:
786 if len(key) <= Nprefix:
786 return False
787 return False
787 # Reject keys with non str/bytes in it
788 # Reject keys with non str/bytes in it
788 for k in key:
789 for k in key:
789 if not isinstance(k, (str, bytes)):
790 if not isinstance(k, (str, bytes)):
790 return False
791 return False
791 # Reject keys that do not match the prefix
792 # Reject keys that do not match the prefix
792 for k, pt in zip(key, prefix_tuple):
793 for k, pt in zip(key, prefix_tuple):
793 if k != pt:
794 if k != pt:
794 return False
795 return False
795 # All checks passed!
796 # All checks passed!
796 return True
797 return True
797
798
798 filtered_keys:List[Union[str,bytes]] = []
799 filtered_keys:List[Union[str,bytes]] = []
799 def _add_to_filtered_keys(key):
800 def _add_to_filtered_keys(key):
800 if isinstance(key, (str, bytes)):
801 if isinstance(key, (str, bytes)):
801 filtered_keys.append(key)
802 filtered_keys.append(key)
802
803
803 for k in keys:
804 for k in keys:
804 if isinstance(k, tuple):
805 if isinstance(k, tuple):
805 if filter_prefix_tuple(k):
806 if filter_prefix_tuple(k):
806 _add_to_filtered_keys(k[Nprefix])
807 _add_to_filtered_keys(k[Nprefix])
807 else:
808 else:
808 _add_to_filtered_keys(k)
809 _add_to_filtered_keys(k)
809
810
810 if not prefix:
811 if not prefix:
811 return '', 0, [repr(k) for k in filtered_keys]
812 return '', 0, [repr(k) for k in filtered_keys]
812 quote_match = re.search('["\']', prefix)
813 quote_match = re.search('["\']', prefix)
813 assert quote_match is not None # silence mypy
814 assert quote_match is not None # silence mypy
814 quote = quote_match.group()
815 quote = quote_match.group()
815 try:
816 try:
816 prefix_str = eval(prefix + quote, {})
817 prefix_str = eval(prefix + quote, {})
817 except Exception:
818 except Exception:
818 return '', 0, []
819 return '', 0, []
819
820
820 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
821 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
821 token_match = re.search(pattern, prefix, re.UNICODE)
822 token_match = re.search(pattern, prefix, re.UNICODE)
822 assert token_match is not None # silence mypy
823 assert token_match is not None # silence mypy
823 token_start = token_match.start()
824 token_start = token_match.start()
824 token_prefix = token_match.group()
825 token_prefix = token_match.group()
825
826
826 matched:List[str] = []
827 matched:List[str] = []
827 for key in filtered_keys:
828 for key in filtered_keys:
828 try:
829 try:
829 if not key.startswith(prefix_str):
830 if not key.startswith(prefix_str):
830 continue
831 continue
831 except (AttributeError, TypeError, UnicodeError):
832 except (AttributeError, TypeError, UnicodeError):
832 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
833 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
833 continue
834 continue
834
835
835 # reformat remainder of key to begin with prefix
836 # reformat remainder of key to begin with prefix
836 rem = key[len(prefix_str):]
837 rem = key[len(prefix_str):]
837 # force repr wrapped in '
838 # force repr wrapped in '
838 rem_repr = repr(rem + '"') if isinstance(rem, str) else repr(rem + b'"')
839 rem_repr = repr(rem + '"') if isinstance(rem, str) else repr(rem + b'"')
839 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
840 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
840 if quote == '"':
841 if quote == '"':
841 # The entered prefix is quoted with ",
842 # The entered prefix is quoted with ",
842 # but the match is quoted with '.
843 # but the match is quoted with '.
843 # A contained " hence needs escaping for comparison:
844 # A contained " hence needs escaping for comparison:
844 rem_repr = rem_repr.replace('"', '\\"')
845 rem_repr = rem_repr.replace('"', '\\"')
845
846
846 # then reinsert prefix from start of token
847 # then reinsert prefix from start of token
847 matched.append('%s%s' % (token_prefix, rem_repr))
848 matched.append('%s%s' % (token_prefix, rem_repr))
848 return quote, token_start, matched
849 return quote, token_start, matched
849
850
850
851
851 def cursor_to_position(text:str, line:int, column:int)->int:
852 def cursor_to_position(text:str, line:int, column:int)->int:
852 """
853 """
853
854
854 Convert the (line,column) position of the cursor in text to an offset in a
855 Convert the (line,column) position of the cursor in text to an offset in a
855 string.
856 string.
856
857
857 Parameters
858 Parameters
858 ----------
859 ----------
859
860
860 text : str
861 text : str
861 The text in which to calculate the cursor offset
862 The text in which to calculate the cursor offset
862 line : int
863 line : int
863 Line of the cursor; 0-indexed
864 Line of the cursor; 0-indexed
864 column : int
865 column : int
865 Column of the cursor 0-indexed
866 Column of the cursor 0-indexed
866
867
867 Return
868 Return
868 ------
869 ------
869 Position of the cursor in ``text``, 0-indexed.
870 Position of the cursor in ``text``, 0-indexed.
870
871
871 See Also
872 See Also
872 --------
873 --------
873 position_to_cursor: reciprocal of this function
874 position_to_cursor: reciprocal of this function
874
875
875 """
876 """
876 lines = text.split('\n')
877 lines = text.split('\n')
877 assert line <= len(lines), '{} <= {}'.format(str(line), str(len(lines)))
878 assert line <= len(lines), '{} <= {}'.format(str(line), str(len(lines)))
878
879
879 return sum(len(l) + 1 for l in lines[:line]) + column
880 return sum(len(l) + 1 for l in lines[:line]) + column
880
881
881 def position_to_cursor(text:str, offset:int)->Tuple[int, int]:
882 def position_to_cursor(text:str, offset:int)->Tuple[int, int]:
882 """
883 """
883 Convert the position of the cursor in text (0 indexed) to a line
884 Convert the position of the cursor in text (0 indexed) to a line
884 number(0-indexed) and a column number (0-indexed) pair
885 number(0-indexed) and a column number (0-indexed) pair
885
886
886 Position should be a valid position in ``text``.
887 Position should be a valid position in ``text``.
887
888
888 Parameters
889 Parameters
889 ----------
890 ----------
890
891
891 text : str
892 text : str
892 The text in which to calculate the cursor offset
893 The text in which to calculate the cursor offset
893 offset : int
894 offset : int
894 Position of the cursor in ``text``, 0-indexed.
895 Position of the cursor in ``text``, 0-indexed.
895
896
896 Return
897 Return
897 ------
898 ------
898 (line, column) : (int, int)
899 (line, column) : (int, int)
899 Line of the cursor; 0-indexed, column of the cursor 0-indexed
900 Line of the cursor; 0-indexed, column of the cursor 0-indexed
900
901
901
902
902 See Also
903 See Also
903 --------
904 --------
904 cursor_to_position : reciprocal of this function
905 cursor_to_position : reciprocal of this function
905
906
906
907
907 """
908 """
908
909
909 assert 0 <= offset <= len(text) , "0 <= %s <= %s" % (offset , len(text))
910 assert 0 <= offset <= len(text) , "0 <= %s <= %s" % (offset , len(text))
910
911
911 before = text[:offset]
912 before = text[:offset]
912 blines = before.split('\n') # ! splitnes trim trailing \n
913 blines = before.split('\n') # ! splitnes trim trailing \n
913 line = before.count('\n')
914 line = before.count('\n')
914 col = len(blines[-1])
915 col = len(blines[-1])
915 return line, col
916 return line, col
916
917
917
918
918 def _safe_isinstance(obj, module, class_name):
919 def _safe_isinstance(obj, module, class_name):
919 """Checks if obj is an instance of module.class_name if loaded
920 """Checks if obj is an instance of module.class_name if loaded
920 """
921 """
921 return (module in sys.modules and
922 return (module in sys.modules and
922 isinstance(obj, getattr(import_module(module), class_name)))
923 isinstance(obj, getattr(import_module(module), class_name)))
923
924
924 def back_unicode_name_matches(text:str) -> Tuple[str, Sequence[str]]:
925 def back_unicode_name_matches(text:str) -> Tuple[str, Sequence[str]]:
925 """Match Unicode characters back to Unicode name
926 """Match Unicode characters back to Unicode name
926
927
927 This does ``β˜ƒ`` -> ``\\snowman``
928 This does ``β˜ƒ`` -> ``\\snowman``
928
929
929 Note that snowman is not a valid python3 combining character but will be expanded.
930 Note that snowman is not a valid python3 combining character but will be expanded.
930 Though it will not recombine back to the snowman character by the completion machinery.
931 Though it will not recombine back to the snowman character by the completion machinery.
931
932
932 This will not either back-complete standard sequences like \\n, \\b ...
933 This will not either back-complete standard sequences like \\n, \\b ...
933
934
934 Returns
935 Returns
935 =======
936 =======
936
937
937 Return a tuple with two elements:
938 Return a tuple with two elements:
938
939
939 - The Unicode character that was matched (preceded with a backslash), or
940 - The Unicode character that was matched (preceded with a backslash), or
940 empty string,
941 empty string,
941 - a sequence (of 1), name for the match Unicode character, preceded by
942 - a sequence (of 1), name for the match Unicode character, preceded by
942 backslash, or empty if no match.
943 backslash, or empty if no match.
943
944
944 """
945 """
945 if len(text)<2:
946 if len(text)<2:
946 return '', ()
947 return '', ()
947 maybe_slash = text[-2]
948 maybe_slash = text[-2]
948 if maybe_slash != '\\':
949 if maybe_slash != '\\':
949 return '', ()
950 return '', ()
950
951
951 char = text[-1]
952 char = text[-1]
952 # no expand on quote for completion in strings.
953 # no expand on quote for completion in strings.
953 # nor backcomplete standard ascii keys
954 # nor backcomplete standard ascii keys
954 if char in string.ascii_letters or char in ('"',"'"):
955 if char in string.ascii_letters or char in ('"',"'"):
955 return '', ()
956 return '', ()
956 try :
957 try :
957 unic = unicodedata.name(char)
958 unic = unicodedata.name(char)
958 return '\\'+char,('\\'+unic,)
959 return '\\'+char,('\\'+unic,)
959 except KeyError:
960 except KeyError:
960 pass
961 pass
961 return '', ()
962 return '', ()
962
963
963 def back_latex_name_matches(text:str) -> Tuple[str, Sequence[str]] :
964 def back_latex_name_matches(text:str) -> Tuple[str, Sequence[str]] :
964 """Match latex characters back to unicode name
965 """Match latex characters back to unicode name
965
966
966 This does ``\\β„΅`` -> ``\\aleph``
967 This does ``\\β„΅`` -> ``\\aleph``
967
968
968 """
969 """
969 if len(text)<2:
970 if len(text)<2:
970 return '', ()
971 return '', ()
971 maybe_slash = text[-2]
972 maybe_slash = text[-2]
972 if maybe_slash != '\\':
973 if maybe_slash != '\\':
973 return '', ()
974 return '', ()
974
975
975
976
976 char = text[-1]
977 char = text[-1]
977 # no expand on quote for completion in strings.
978 # no expand on quote for completion in strings.
978 # nor backcomplete standard ascii keys
979 # nor backcomplete standard ascii keys
979 if char in string.ascii_letters or char in ('"',"'"):
980 if char in string.ascii_letters or char in ('"',"'"):
980 return '', ()
981 return '', ()
981 try :
982 try :
982 latex = reverse_latex_symbol[char]
983 latex = reverse_latex_symbol[char]
983 # '\\' replace the \ as well
984 # '\\' replace the \ as well
984 return '\\'+char,[latex]
985 return '\\'+char,[latex]
985 except KeyError:
986 except KeyError:
986 pass
987 pass
987 return '', ()
988 return '', ()
988
989
989
990
990 def _formatparamchildren(parameter) -> str:
991 def _formatparamchildren(parameter) -> str:
991 """
992 """
992 Get parameter name and value from Jedi Private API
993 Get parameter name and value from Jedi Private API
993
994
994 Jedi does not expose a simple way to get `param=value` from its API.
995 Jedi does not expose a simple way to get `param=value` from its API.
995
996
996 Parameter
997 Parameter
997 =========
998 =========
998
999
999 parameter:
1000 parameter:
1000 Jedi's function `Param`
1001 Jedi's function `Param`
1001
1002
1002 Returns
1003 Returns
1003 =======
1004 =======
1004
1005
1005 A string like 'a', 'b=1', '*args', '**kwargs'
1006 A string like 'a', 'b=1', '*args', '**kwargs'
1006
1007
1007
1008
1008 """
1009 """
1009 description = parameter.description
1010 description = parameter.description
1010 if not description.startswith('param '):
1011 if not description.startswith('param '):
1011 raise ValueError('Jedi function parameter description have change format.'
1012 raise ValueError('Jedi function parameter description have change format.'
1012 'Expected "param ...", found %r".' % description)
1013 'Expected "param ...", found %r".' % description)
1013 return description[6:]
1014 return description[6:]
1014
1015
1015 def _make_signature(completion)-> str:
1016 def _make_signature(completion)-> str:
1016 """
1017 """
1017 Make the signature from a jedi completion
1018 Make the signature from a jedi completion
1018
1019
1019 Parameter
1020 Parameter
1020 =========
1021 =========
1021
1022
1022 completion: jedi.Completion
1023 completion: jedi.Completion
1023 object does not complete a function type
1024 object does not complete a function type
1024
1025
1025 Returns
1026 Returns
1026 =======
1027 =======
1027
1028
1028 a string consisting of the function signature, with the parenthesis but
1029 a string consisting of the function signature, with the parenthesis but
1029 without the function name. example:
1030 without the function name. example:
1030 `(a, *args, b=1, **kwargs)`
1031 `(a, *args, b=1, **kwargs)`
1031
1032
1032 """
1033 """
1033
1034
1034 # it looks like this might work on jedi 0.17
1035 # it looks like this might work on jedi 0.17
1035 if hasattr(completion, 'get_signatures'):
1036 if hasattr(completion, 'get_signatures'):
1036 signatures = completion.get_signatures()
1037 signatures = completion.get_signatures()
1037 if not signatures:
1038 if not signatures:
1038 return '(?)'
1039 return '(?)'
1039
1040
1040 c0 = completion.get_signatures()[0]
1041 c0 = completion.get_signatures()[0]
1041 return '('+c0.to_string().split('(', maxsplit=1)[1]
1042 return '('+c0.to_string().split('(', maxsplit=1)[1]
1042
1043
1043 return '(%s)'% ', '.join([f for f in (_formatparamchildren(p) for signature in completion.get_signatures()
1044 return '(%s)'% ', '.join([f for f in (_formatparamchildren(p) for signature in completion.get_signatures()
1044 for p in signature.defined_names()) if f])
1045 for p in signature.defined_names()) if f])
1045
1046
1046
1047
1047 class _CompleteResult(NamedTuple):
1048 class _CompleteResult(NamedTuple):
1048 matched_text : str
1049 matched_text : str
1049 matches: Sequence[str]
1050 matches: Sequence[str]
1050 matches_origin: Sequence[str]
1051 matches_origin: Sequence[str]
1051 jedi_matches: Any
1052 jedi_matches: Any
1052
1053
1053
1054
1054 class IPCompleter(Completer):
1055 class IPCompleter(Completer):
1055 """Extension of the completer class with IPython-specific features"""
1056 """Extension of the completer class with IPython-specific features"""
1056
1057
1057 __dict_key_regexps: Optional[Dict[bool,Pattern]] = None
1058 __dict_key_regexps: Optional[Dict[bool,Pattern]] = None
1058
1059
1059 @observe('greedy')
1060 @observe('greedy')
1060 def _greedy_changed(self, change):
1061 def _greedy_changed(self, change):
1061 """update the splitter and readline delims when greedy is changed"""
1062 """update the splitter and readline delims when greedy is changed"""
1062 if change['new']:
1063 if change['new']:
1063 self.splitter.delims = GREEDY_DELIMS
1064 self.splitter.delims = GREEDY_DELIMS
1064 else:
1065 else:
1065 self.splitter.delims = DELIMS
1066 self.splitter.delims = DELIMS
1066
1067
1067 dict_keys_only = Bool(False,
1068 dict_keys_only = Bool(False,
1068 help="""Whether to show dict key matches only""")
1069 help="""Whether to show dict key matches only""")
1069
1070
1070 merge_completions = Bool(True,
1071 merge_completions = Bool(True,
1071 help="""Whether to merge completion results into a single list
1072 help="""Whether to merge completion results into a single list
1072
1073
1073 If False, only the completion results from the first non-empty
1074 If False, only the completion results from the first non-empty
1074 completer will be returned.
1075 completer will be returned.
1075 """
1076 """
1076 ).tag(config=True)
1077 ).tag(config=True)
1077 omit__names = Enum((0,1,2), default_value=2,
1078 omit__names = Enum((0,1,2), default_value=2,
1078 help="""Instruct the completer to omit private method names
1079 help="""Instruct the completer to omit private method names
1079
1080
1080 Specifically, when completing on ``object.<tab>``.
1081 Specifically, when completing on ``object.<tab>``.
1081
1082
1082 When 2 [default]: all names that start with '_' will be excluded.
1083 When 2 [default]: all names that start with '_' will be excluded.
1083
1084
1084 When 1: all 'magic' names (``__foo__``) will be excluded.
1085 When 1: all 'magic' names (``__foo__``) will be excluded.
1085
1086
1086 When 0: nothing will be excluded.
1087 When 0: nothing will be excluded.
1087 """
1088 """
1088 ).tag(config=True)
1089 ).tag(config=True)
1089 limit_to__all__ = Bool(False,
1090 limit_to__all__ = Bool(False,
1090 help="""
1091 help="""
1091 DEPRECATED as of version 5.0.
1092 DEPRECATED as of version 5.0.
1092
1093
1093 Instruct the completer to use __all__ for the completion
1094 Instruct the completer to use __all__ for the completion
1094
1095
1095 Specifically, when completing on ``object.<tab>``.
1096 Specifically, when completing on ``object.<tab>``.
1096
1097
1097 When True: only those names in obj.__all__ will be included.
1098 When True: only those names in obj.__all__ will be included.
1098
1099
1099 When False [default]: the __all__ attribute is ignored
1100 When False [default]: the __all__ attribute is ignored
1100 """,
1101 """,
1101 ).tag(config=True)
1102 ).tag(config=True)
1102
1103
1103 profile_completions = Bool(
1104 profile_completions = Bool(
1104 default_value=False,
1105 default_value=False,
1105 help="If True, emit profiling data for completion subsystem using cProfile."
1106 help="If True, emit profiling data for completion subsystem using cProfile."
1106 ).tag(config=True)
1107 ).tag(config=True)
1107
1108
1108 profiler_output_dir = Unicode(
1109 profiler_output_dir = Unicode(
1109 default_value=".completion_profiles",
1110 default_value=".completion_profiles",
1110 help="Template for path at which to output profile data for completions."
1111 help="Template for path at which to output profile data for completions."
1111 ).tag(config=True)
1112 ).tag(config=True)
1112
1113
1113 @observe('limit_to__all__')
1114 @observe('limit_to__all__')
1114 def _limit_to_all_changed(self, change):
1115 def _limit_to_all_changed(self, change):
1115 warnings.warn('`IPython.core.IPCompleter.limit_to__all__` configuration '
1116 warnings.warn('`IPython.core.IPCompleter.limit_to__all__` configuration '
1116 'value has been deprecated since IPython 5.0, will be made to have '
1117 'value has been deprecated since IPython 5.0, will be made to have '
1117 'no effects and then removed in future version of IPython.',
1118 'no effects and then removed in future version of IPython.',
1118 UserWarning)
1119 UserWarning)
1119
1120
1120 def __init__(self, shell=None, namespace=None, global_namespace=None,
1121 def __init__(self, shell=None, namespace=None, global_namespace=None,
1121 use_readline=_deprecation_readline_sentinel, config=None, **kwargs):
1122 use_readline=_deprecation_readline_sentinel, config=None, **kwargs):
1122 """IPCompleter() -> completer
1123 """IPCompleter() -> completer
1123
1124
1124 Return a completer object.
1125 Return a completer object.
1125
1126
1126 Parameters
1127 Parameters
1127 ----------
1128 ----------
1128
1129
1129 shell
1130 shell
1130 a pointer to the ipython shell itself. This is needed
1131 a pointer to the ipython shell itself. This is needed
1131 because this completer knows about magic functions, and those can
1132 because this completer knows about magic functions, and those can
1132 only be accessed via the ipython instance.
1133 only be accessed via the ipython instance.
1133
1134
1134 namespace : dict, optional
1135 namespace : dict, optional
1135 an optional dict where completions are performed.
1136 an optional dict where completions are performed.
1136
1137
1137 global_namespace : dict, optional
1138 global_namespace : dict, optional
1138 secondary optional dict for completions, to
1139 secondary optional dict for completions, to
1139 handle cases (such as IPython embedded inside functions) where
1140 handle cases (such as IPython embedded inside functions) where
1140 both Python scopes are visible.
1141 both Python scopes are visible.
1141
1142
1142 use_readline : bool, optional
1143 use_readline : bool, optional
1143 DEPRECATED, ignored since IPython 6.0, will have no effects
1144 DEPRECATED, ignored since IPython 6.0, will have no effects
1144 """
1145 """
1145
1146
1146 self.magic_escape = ESC_MAGIC
1147 self.magic_escape = ESC_MAGIC
1147 self.splitter = CompletionSplitter()
1148 self.splitter = CompletionSplitter()
1148
1149
1149 if use_readline is not _deprecation_readline_sentinel:
1150 if use_readline is not _deprecation_readline_sentinel:
1150 warnings.warn('The `use_readline` parameter is deprecated and ignored since IPython 6.0.',
1151 warnings.warn('The `use_readline` parameter is deprecated and ignored since IPython 6.0.',
1151 DeprecationWarning, stacklevel=2)
1152 DeprecationWarning, stacklevel=2)
1152
1153
1153 # _greedy_changed() depends on splitter and readline being defined:
1154 # _greedy_changed() depends on splitter and readline being defined:
1154 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
1155 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
1155 config=config, **kwargs)
1156 config=config, **kwargs)
1156
1157
1157 # List where completion matches will be stored
1158 # List where completion matches will be stored
1158 self.matches = []
1159 self.matches = []
1159 self.shell = shell
1160 self.shell = shell
1160 # Regexp to split filenames with spaces in them
1161 # Regexp to split filenames with spaces in them
1161 self.space_name_re = re.compile(r'([^\\] )')
1162 self.space_name_re = re.compile(r'([^\\] )')
1162 # Hold a local ref. to glob.glob for speed
1163 # Hold a local ref. to glob.glob for speed
1163 self.glob = glob.glob
1164 self.glob = glob.glob
1164
1165
1165 # Determine if we are running on 'dumb' terminals, like (X)Emacs
1166 # Determine if we are running on 'dumb' terminals, like (X)Emacs
1166 # buffers, to avoid completion problems.
1167 # buffers, to avoid completion problems.
1167 term = os.environ.get('TERM','xterm')
1168 term = os.environ.get('TERM','xterm')
1168 self.dumb_terminal = term in ['dumb','emacs']
1169 self.dumb_terminal = term in ['dumb','emacs']
1169
1170
1170 # Special handling of backslashes needed in win32 platforms
1171 # Special handling of backslashes needed in win32 platforms
1171 if sys.platform == "win32":
1172 if sys.platform == "win32":
1172 self.clean_glob = self._clean_glob_win32
1173 self.clean_glob = self._clean_glob_win32
1173 else:
1174 else:
1174 self.clean_glob = self._clean_glob
1175 self.clean_glob = self._clean_glob
1175
1176
1176 #regexp to parse docstring for function signature
1177 #regexp to parse docstring for function signature
1177 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1178 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1178 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1179 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1179 #use this if positional argument name is also needed
1180 #use this if positional argument name is also needed
1180 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
1181 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
1181
1182
1182 self.magic_arg_matchers = [
1183 self.magic_arg_matchers = [
1183 self.magic_config_matches,
1184 self.magic_config_matches,
1184 self.magic_color_matches,
1185 self.magic_color_matches,
1185 ]
1186 ]
1186
1187
1187 # This is set externally by InteractiveShell
1188 # This is set externally by InteractiveShell
1188 self.custom_completers = None
1189 self.custom_completers = None
1189
1190
1190 # This is a list of names of unicode characters that can be completed
1191 # This is a list of names of unicode characters that can be completed
1191 # into their corresponding unicode value. The list is large, so we
1192 # into their corresponding unicode value. The list is large, so we
1192 # laziliy initialize it on first use. Consuming code should access this
1193 # laziliy initialize it on first use. Consuming code should access this
1193 # attribute through the `@unicode_names` property.
1194 # attribute through the `@unicode_names` property.
1194 self._unicode_names = None
1195 self._unicode_names = None
1195
1196
1196 @property
1197 @property
1197 def matchers(self) -> List[Any]:
1198 def matchers(self) -> List[Any]:
1198 """All active matcher routines for completion"""
1199 """All active matcher routines for completion"""
1199 if self.dict_keys_only:
1200 if self.dict_keys_only:
1200 return [self.dict_key_matches]
1201 return [self.dict_key_matches]
1201
1202
1202 if self.use_jedi:
1203 if self.use_jedi:
1203 return [
1204 return [
1204 *self.custom_matchers,
1205 *self.custom_matchers,
1205 self.file_matches,
1206 self.file_matches,
1206 self.magic_matches,
1207 self.magic_matches,
1207 self.dict_key_matches,
1208 self.dict_key_matches,
1208 ]
1209 ]
1209 else:
1210 else:
1210 return [
1211 return [
1211 *self.custom_matchers,
1212 *self.custom_matchers,
1212 self.python_matches,
1213 self.python_matches,
1213 self.file_matches,
1214 self.file_matches,
1214 self.magic_matches,
1215 self.magic_matches,
1215 self.python_func_kw_matches,
1216 self.python_func_kw_matches,
1216 self.dict_key_matches,
1217 self.dict_key_matches,
1217 ]
1218 ]
1218
1219
1219 def all_completions(self, text:str) -> List[str]:
1220 def all_completions(self, text:str) -> List[str]:
1220 """
1221 """
1221 Wrapper around the completion methods for the benefit of emacs.
1222 Wrapper around the completion methods for the benefit of emacs.
1222 """
1223 """
1223 prefix = text.rpartition('.')[0]
1224 prefix = text.rpartition('.')[0]
1224 with provisionalcompleter():
1225 with provisionalcompleter():
1225 return ['.'.join([prefix, c.text]) if prefix and self.use_jedi else c.text
1226 return ['.'.join([prefix, c.text]) if prefix and self.use_jedi else c.text
1226 for c in self.completions(text, len(text))]
1227 for c in self.completions(text, len(text))]
1227
1228
1228 return self.complete(text)[1]
1229 return self.complete(text)[1]
1229
1230
1230 def _clean_glob(self, text:str):
1231 def _clean_glob(self, text:str):
1231 return self.glob("%s*" % text)
1232 return self.glob("%s*" % text)
1232
1233
1233 def _clean_glob_win32(self, text:str):
1234 def _clean_glob_win32(self, text:str):
1234 return [f.replace("\\","/")
1235 return [f.replace("\\","/")
1235 for f in self.glob("%s*" % text)]
1236 for f in self.glob("%s*" % text)]
1236
1237
1237 def file_matches(self, text:str)->List[str]:
1238 def file_matches(self, text:str)->List[str]:
1238 """Match filenames, expanding ~USER type strings.
1239 """Match filenames, expanding ~USER type strings.
1239
1240
1240 Most of the seemingly convoluted logic in this completer is an
1241 Most of the seemingly convoluted logic in this completer is an
1241 attempt to handle filenames with spaces in them. And yet it's not
1242 attempt to handle filenames with spaces in them. And yet it's not
1242 quite perfect, because Python's readline doesn't expose all of the
1243 quite perfect, because Python's readline doesn't expose all of the
1243 GNU readline details needed for this to be done correctly.
1244 GNU readline details needed for this to be done correctly.
1244
1245
1245 For a filename with a space in it, the printed completions will be
1246 For a filename with a space in it, the printed completions will be
1246 only the parts after what's already been typed (instead of the
1247 only the parts after what's already been typed (instead of the
1247 full completions, as is normally done). I don't think with the
1248 full completions, as is normally done). I don't think with the
1248 current (as of Python 2.3) Python readline it's possible to do
1249 current (as of Python 2.3) Python readline it's possible to do
1249 better."""
1250 better."""
1250
1251
1251 # chars that require escaping with backslash - i.e. chars
1252 # chars that require escaping with backslash - i.e. chars
1252 # that readline treats incorrectly as delimiters, but we
1253 # that readline treats incorrectly as delimiters, but we
1253 # don't want to treat as delimiters in filename matching
1254 # don't want to treat as delimiters in filename matching
1254 # when escaped with backslash
1255 # when escaped with backslash
1255 if text.startswith('!'):
1256 if text.startswith('!'):
1256 text = text[1:]
1257 text = text[1:]
1257 text_prefix = u'!'
1258 text_prefix = u'!'
1258 else:
1259 else:
1259 text_prefix = u''
1260 text_prefix = u''
1260
1261
1261 text_until_cursor = self.text_until_cursor
1262 text_until_cursor = self.text_until_cursor
1262 # track strings with open quotes
1263 # track strings with open quotes
1263 open_quotes = has_open_quotes(text_until_cursor)
1264 open_quotes = has_open_quotes(text_until_cursor)
1264
1265
1265 if '(' in text_until_cursor or '[' in text_until_cursor:
1266 if '(' in text_until_cursor or '[' in text_until_cursor:
1266 lsplit = text
1267 lsplit = text
1267 else:
1268 else:
1268 try:
1269 try:
1269 # arg_split ~ shlex.split, but with unicode bugs fixed by us
1270 # arg_split ~ shlex.split, but with unicode bugs fixed by us
1270 lsplit = arg_split(text_until_cursor)[-1]
1271 lsplit = arg_split(text_until_cursor)[-1]
1271 except ValueError:
1272 except ValueError:
1272 # typically an unmatched ", or backslash without escaped char.
1273 # typically an unmatched ", or backslash without escaped char.
1273 if open_quotes:
1274 if open_quotes:
1274 lsplit = text_until_cursor.split(open_quotes)[-1]
1275 lsplit = text_until_cursor.split(open_quotes)[-1]
1275 else:
1276 else:
1276 return []
1277 return []
1277 except IndexError:
1278 except IndexError:
1278 # tab pressed on empty line
1279 # tab pressed on empty line
1279 lsplit = ""
1280 lsplit = ""
1280
1281
1281 if not open_quotes and lsplit != protect_filename(lsplit):
1282 if not open_quotes and lsplit != protect_filename(lsplit):
1282 # if protectables are found, do matching on the whole escaped name
1283 # if protectables are found, do matching on the whole escaped name
1283 has_protectables = True
1284 has_protectables = True
1284 text0,text = text,lsplit
1285 text0,text = text,lsplit
1285 else:
1286 else:
1286 has_protectables = False
1287 has_protectables = False
1287 text = os.path.expanduser(text)
1288 text = os.path.expanduser(text)
1288
1289
1289 if text == "":
1290 if text == "":
1290 return [text_prefix + protect_filename(f) for f in self.glob("*")]
1291 return [text_prefix + protect_filename(f) for f in self.glob("*")]
1291
1292
1292 # Compute the matches from the filesystem
1293 # Compute the matches from the filesystem
1293 if sys.platform == 'win32':
1294 if sys.platform == 'win32':
1294 m0 = self.clean_glob(text)
1295 m0 = self.clean_glob(text)
1295 else:
1296 else:
1296 m0 = self.clean_glob(text.replace('\\', ''))
1297 m0 = self.clean_glob(text.replace('\\', ''))
1297
1298
1298 if has_protectables:
1299 if has_protectables:
1299 # If we had protectables, we need to revert our changes to the
1300 # If we had protectables, we need to revert our changes to the
1300 # beginning of filename so that we don't double-write the part
1301 # beginning of filename so that we don't double-write the part
1301 # of the filename we have so far
1302 # of the filename we have so far
1302 len_lsplit = len(lsplit)
1303 len_lsplit = len(lsplit)
1303 matches = [text_prefix + text0 +
1304 matches = [text_prefix + text0 +
1304 protect_filename(f[len_lsplit:]) for f in m0]
1305 protect_filename(f[len_lsplit:]) for f in m0]
1305 else:
1306 else:
1306 if open_quotes:
1307 if open_quotes:
1307 # if we have a string with an open quote, we don't need to
1308 # if we have a string with an open quote, we don't need to
1308 # protect the names beyond the quote (and we _shouldn't_, as
1309 # protect the names beyond the quote (and we _shouldn't_, as
1309 # it would cause bugs when the filesystem call is made).
1310 # it would cause bugs when the filesystem call is made).
1310 matches = m0 if sys.platform == "win32" else\
1311 matches = m0 if sys.platform == "win32" else\
1311 [protect_filename(f, open_quotes) for f in m0]
1312 [protect_filename(f, open_quotes) for f in m0]
1312 else:
1313 else:
1313 matches = [text_prefix +
1314 matches = [text_prefix +
1314 protect_filename(f) for f in m0]
1315 protect_filename(f) for f in m0]
1315
1316
1316 # Mark directories in input list by appending '/' to their names.
1317 # Mark directories in input list by appending '/' to their names.
1317 return [x+'/' if os.path.isdir(x) else x for x in matches]
1318 return [x+'/' if os.path.isdir(x) else x for x in matches]
1318
1319
1319 def magic_matches(self, text:str):
1320 def magic_matches(self, text:str):
1320 """Match magics"""
1321 """Match magics"""
1321 # Get all shell magics now rather than statically, so magics loaded at
1322 # Get all shell magics now rather than statically, so magics loaded at
1322 # runtime show up too.
1323 # runtime show up too.
1323 lsm = self.shell.magics_manager.lsmagic()
1324 lsm = self.shell.magics_manager.lsmagic()
1324 line_magics = lsm['line']
1325 line_magics = lsm['line']
1325 cell_magics = lsm['cell']
1326 cell_magics = lsm['cell']
1326 pre = self.magic_escape
1327 pre = self.magic_escape
1327 pre2 = pre+pre
1328 pre2 = pre+pre
1328
1329
1329 explicit_magic = text.startswith(pre)
1330 explicit_magic = text.startswith(pre)
1330
1331
1331 # Completion logic:
1332 # Completion logic:
1332 # - user gives %%: only do cell magics
1333 # - user gives %%: only do cell magics
1333 # - user gives %: do both line and cell magics
1334 # - user gives %: do both line and cell magics
1334 # - no prefix: do both
1335 # - no prefix: do both
1335 # In other words, line magics are skipped if the user gives %% explicitly
1336 # In other words, line magics are skipped if the user gives %% explicitly
1336 #
1337 #
1337 # We also exclude magics that match any currently visible names:
1338 # We also exclude magics that match any currently visible names:
1338 # https://github.com/ipython/ipython/issues/4877, unless the user has
1339 # https://github.com/ipython/ipython/issues/4877, unless the user has
1339 # typed a %:
1340 # typed a %:
1340 # https://github.com/ipython/ipython/issues/10754
1341 # https://github.com/ipython/ipython/issues/10754
1341 bare_text = text.lstrip(pre)
1342 bare_text = text.lstrip(pre)
1342 global_matches = self.global_matches(bare_text)
1343 global_matches = self.global_matches(bare_text)
1343 if not explicit_magic:
1344 if not explicit_magic:
1344 def matches(magic):
1345 def matches(magic):
1345 """
1346 """
1346 Filter magics, in particular remove magics that match
1347 Filter magics, in particular remove magics that match
1347 a name present in global namespace.
1348 a name present in global namespace.
1348 """
1349 """
1349 return ( magic.startswith(bare_text) and
1350 return ( magic.startswith(bare_text) and
1350 magic not in global_matches )
1351 magic not in global_matches )
1351 else:
1352 else:
1352 def matches(magic):
1353 def matches(magic):
1353 return magic.startswith(bare_text)
1354 return magic.startswith(bare_text)
1354
1355
1355 comp = [ pre2+m for m in cell_magics if matches(m)]
1356 comp = [ pre2+m for m in cell_magics if matches(m)]
1356 if not text.startswith(pre2):
1357 if not text.startswith(pre2):
1357 comp += [ pre+m for m in line_magics if matches(m)]
1358 comp += [ pre+m for m in line_magics if matches(m)]
1358
1359
1359 return comp
1360 return comp
1360
1361
1361 def magic_config_matches(self, text:str) -> List[str]:
1362 def magic_config_matches(self, text:str) -> List[str]:
1362 """ Match class names and attributes for %config magic """
1363 """ Match class names and attributes for %config magic """
1363 texts = text.strip().split()
1364 texts = text.strip().split()
1364
1365
1365 if len(texts) > 0 and (texts[0] == 'config' or texts[0] == '%config'):
1366 if len(texts) > 0 and (texts[0] == 'config' or texts[0] == '%config'):
1366 # get all configuration classes
1367 # get all configuration classes
1367 classes = sorted(set([ c for c in self.shell.configurables
1368 classes = sorted(set([ c for c in self.shell.configurables
1368 if c.__class__.class_traits(config=True)
1369 if c.__class__.class_traits(config=True)
1369 ]), key=lambda x: x.__class__.__name__)
1370 ]), key=lambda x: x.__class__.__name__)
1370 classnames = [ c.__class__.__name__ for c in classes ]
1371 classnames = [ c.__class__.__name__ for c in classes ]
1371
1372
1372 # return all classnames if config or %config is given
1373 # return all classnames if config or %config is given
1373 if len(texts) == 1:
1374 if len(texts) == 1:
1374 return classnames
1375 return classnames
1375
1376
1376 # match classname
1377 # match classname
1377 classname_texts = texts[1].split('.')
1378 classname_texts = texts[1].split('.')
1378 classname = classname_texts[0]
1379 classname = classname_texts[0]
1379 classname_matches = [ c for c in classnames
1380 classname_matches = [ c for c in classnames
1380 if c.startswith(classname) ]
1381 if c.startswith(classname) ]
1381
1382
1382 # return matched classes or the matched class with attributes
1383 # return matched classes or the matched class with attributes
1383 if texts[1].find('.') < 0:
1384 if texts[1].find('.') < 0:
1384 return classname_matches
1385 return classname_matches
1385 elif len(classname_matches) == 1 and \
1386 elif len(classname_matches) == 1 and \
1386 classname_matches[0] == classname:
1387 classname_matches[0] == classname:
1387 cls = classes[classnames.index(classname)].__class__
1388 cls = classes[classnames.index(classname)].__class__
1388 help = cls.class_get_help()
1389 help = cls.class_get_help()
1389 # strip leading '--' from cl-args:
1390 # strip leading '--' from cl-args:
1390 help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
1391 help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
1391 return [ attr.split('=')[0]
1392 return [ attr.split('=')[0]
1392 for attr in help.strip().splitlines()
1393 for attr in help.strip().splitlines()
1393 if attr.startswith(texts[1]) ]
1394 if attr.startswith(texts[1]) ]
1394 return []
1395 return []
1395
1396
1396 def magic_color_matches(self, text:str) -> List[str] :
1397 def magic_color_matches(self, text:str) -> List[str] :
1397 """ Match color schemes for %colors magic"""
1398 """ Match color schemes for %colors magic"""
1398 texts = text.split()
1399 texts = text.split()
1399 if text.endswith(' '):
1400 if text.endswith(' '):
1400 # .split() strips off the trailing whitespace. Add '' back
1401 # .split() strips off the trailing whitespace. Add '' back
1401 # so that: '%colors ' -> ['%colors', '']
1402 # so that: '%colors ' -> ['%colors', '']
1402 texts.append('')
1403 texts.append('')
1403
1404
1404 if len(texts) == 2 and (texts[0] == 'colors' or texts[0] == '%colors'):
1405 if len(texts) == 2 and (texts[0] == 'colors' or texts[0] == '%colors'):
1405 prefix = texts[1]
1406 prefix = texts[1]
1406 return [ color for color in InspectColors.keys()
1407 return [ color for color in InspectColors.keys()
1407 if color.startswith(prefix) ]
1408 if color.startswith(prefix) ]
1408 return []
1409 return []
1409
1410
1410 def _jedi_matches(self, cursor_column:int, cursor_line:int, text:str) -> Iterable[Any]:
1411 def _jedi_matches(self, cursor_column:int, cursor_line:int, text:str) -> Iterable[Any]:
1411 """
1412 """
1412
1413
1413 Return a list of :any:`jedi.api.Completions` object from a ``text`` and
1414 Return a list of :any:`jedi.api.Completions` object from a ``text`` and
1414 cursor position.
1415 cursor position.
1415
1416
1416 Parameters
1417 Parameters
1417 ----------
1418 ----------
1418 cursor_column : int
1419 cursor_column : int
1419 column position of the cursor in ``text``, 0-indexed.
1420 column position of the cursor in ``text``, 0-indexed.
1420 cursor_line : int
1421 cursor_line : int
1421 line position of the cursor in ``text``, 0-indexed
1422 line position of the cursor in ``text``, 0-indexed
1422 text : str
1423 text : str
1423 text to complete
1424 text to complete
1424
1425
1425 Debugging
1426 Notes
1426 ---------
1427 -----
1427
1428
1428 If ``IPCompleter.debug`` is ``True`` may return a :any:`_FakeJediCompletion`
1429 If ``IPCompleter.debug`` is ``True`` may return a :any:`_FakeJediCompletion`
1429 object containing a string with the Jedi debug information attached.
1430 object containing a string with the Jedi debug information attached.
1430 """
1431 """
1431 namespaces = [self.namespace]
1432 namespaces = [self.namespace]
1432 if self.global_namespace is not None:
1433 if self.global_namespace is not None:
1433 namespaces.append(self.global_namespace)
1434 namespaces.append(self.global_namespace)
1434
1435
1435 completion_filter = lambda x:x
1436 completion_filter = lambda x:x
1436 offset = cursor_to_position(text, cursor_line, cursor_column)
1437 offset = cursor_to_position(text, cursor_line, cursor_column)
1437 # filter output if we are completing for object members
1438 # filter output if we are completing for object members
1438 if offset:
1439 if offset:
1439 pre = text[offset-1]
1440 pre = text[offset-1]
1440 if pre == '.':
1441 if pre == '.':
1441 if self.omit__names == 2:
1442 if self.omit__names == 2:
1442 completion_filter = lambda c:not c.name.startswith('_')
1443 completion_filter = lambda c:not c.name.startswith('_')
1443 elif self.omit__names == 1:
1444 elif self.omit__names == 1:
1444 completion_filter = lambda c:not (c.name.startswith('__') and c.name.endswith('__'))
1445 completion_filter = lambda c:not (c.name.startswith('__') and c.name.endswith('__'))
1445 elif self.omit__names == 0:
1446 elif self.omit__names == 0:
1446 completion_filter = lambda x:x
1447 completion_filter = lambda x:x
1447 else:
1448 else:
1448 raise ValueError("Don't understand self.omit__names == {}".format(self.omit__names))
1449 raise ValueError("Don't understand self.omit__names == {}".format(self.omit__names))
1449
1450
1450 interpreter = jedi.Interpreter(text[:offset], namespaces)
1451 interpreter = jedi.Interpreter(text[:offset], namespaces)
1451 try_jedi = True
1452 try_jedi = True
1452
1453
1453 try:
1454 try:
1454 # find the first token in the current tree -- if it is a ' or " then we are in a string
1455 # find the first token in the current tree -- if it is a ' or " then we are in a string
1455 completing_string = False
1456 completing_string = False
1456 try:
1457 try:
1457 first_child = next(c for c in interpreter._get_module().tree_node.children if hasattr(c, 'value'))
1458 first_child = next(c for c in interpreter._get_module().tree_node.children if hasattr(c, 'value'))
1458 except StopIteration:
1459 except StopIteration:
1459 pass
1460 pass
1460 else:
1461 else:
1461 # note the value may be ', ", or it may also be ''' or """, or
1462 # note the value may be ', ", or it may also be ''' or """, or
1462 # in some cases, """what/you/typed..., but all of these are
1463 # in some cases, """what/you/typed..., but all of these are
1463 # strings.
1464 # strings.
1464 completing_string = len(first_child.value) > 0 and first_child.value[0] in {"'", '"'}
1465 completing_string = len(first_child.value) > 0 and first_child.value[0] in {"'", '"'}
1465
1466
1466 # if we are in a string jedi is likely not the right candidate for
1467 # if we are in a string jedi is likely not the right candidate for
1467 # now. Skip it.
1468 # now. Skip it.
1468 try_jedi = not completing_string
1469 try_jedi = not completing_string
1469 except Exception as e:
1470 except Exception as e:
1470 # many of things can go wrong, we are using private API just don't crash.
1471 # many of things can go wrong, we are using private API just don't crash.
1471 if self.debug:
1472 if self.debug:
1472 print("Error detecting if completing a non-finished string :", e, '|')
1473 print("Error detecting if completing a non-finished string :", e, '|')
1473
1474
1474 if not try_jedi:
1475 if not try_jedi:
1475 return []
1476 return []
1476 try:
1477 try:
1477 return filter(completion_filter, interpreter.complete(column=cursor_column, line=cursor_line + 1))
1478 return filter(completion_filter, interpreter.complete(column=cursor_column, line=cursor_line + 1))
1478 except Exception as e:
1479 except Exception as e:
1479 if self.debug:
1480 if self.debug:
1480 return [_FakeJediCompletion('Oops Jedi has crashed, please report a bug with the following:\n"""\n%s\ns"""' % (e))]
1481 return [_FakeJediCompletion('Oops Jedi has crashed, please report a bug with the following:\n"""\n%s\ns"""' % (e))]
1481 else:
1482 else:
1482 return []
1483 return []
1483
1484
1484 def python_matches(self, text:str)->List[str]:
1485 def python_matches(self, text:str)->List[str]:
1485 """Match attributes or global python names"""
1486 """Match attributes or global python names"""
1486 if "." in text:
1487 if "." in text:
1487 try:
1488 try:
1488 matches = self.attr_matches(text)
1489 matches = self.attr_matches(text)
1489 if text.endswith('.') and self.omit__names:
1490 if text.endswith('.') and self.omit__names:
1490 if self.omit__names == 1:
1491 if self.omit__names == 1:
1491 # true if txt is _not_ a __ name, false otherwise:
1492 # true if txt is _not_ a __ name, false otherwise:
1492 no__name = (lambda txt:
1493 no__name = (lambda txt:
1493 re.match(r'.*\.__.*?__',txt) is None)
1494 re.match(r'.*\.__.*?__',txt) is None)
1494 else:
1495 else:
1495 # true if txt is _not_ a _ name, false otherwise:
1496 # true if txt is _not_ a _ name, false otherwise:
1496 no__name = (lambda txt:
1497 no__name = (lambda txt:
1497 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
1498 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
1498 matches = filter(no__name, matches)
1499 matches = filter(no__name, matches)
1499 except NameError:
1500 except NameError:
1500 # catches <undefined attributes>.<tab>
1501 # catches <undefined attributes>.<tab>
1501 matches = []
1502 matches = []
1502 else:
1503 else:
1503 matches = self.global_matches(text)
1504 matches = self.global_matches(text)
1504 return matches
1505 return matches
1505
1506
1506 def _default_arguments_from_docstring(self, doc):
1507 def _default_arguments_from_docstring(self, doc):
1507 """Parse the first line of docstring for call signature.
1508 """Parse the first line of docstring for call signature.
1508
1509
1509 Docstring should be of the form 'min(iterable[, key=func])\n'.
1510 Docstring should be of the form 'min(iterable[, key=func])\n'.
1510 It can also parse cython docstring of the form
1511 It can also parse cython docstring of the form
1511 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
1512 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
1512 """
1513 """
1513 if doc is None:
1514 if doc is None:
1514 return []
1515 return []
1515
1516
1516 #care only the firstline
1517 #care only the firstline
1517 line = doc.lstrip().splitlines()[0]
1518 line = doc.lstrip().splitlines()[0]
1518
1519
1519 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1520 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1520 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
1521 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
1521 sig = self.docstring_sig_re.search(line)
1522 sig = self.docstring_sig_re.search(line)
1522 if sig is None:
1523 if sig is None:
1523 return []
1524 return []
1524 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
1525 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
1525 sig = sig.groups()[0].split(',')
1526 sig = sig.groups()[0].split(',')
1526 ret = []
1527 ret = []
1527 for s in sig:
1528 for s in sig:
1528 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1529 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1529 ret += self.docstring_kwd_re.findall(s)
1530 ret += self.docstring_kwd_re.findall(s)
1530 return ret
1531 return ret
1531
1532
1532 def _default_arguments(self, obj):
1533 def _default_arguments(self, obj):
1533 """Return the list of default arguments of obj if it is callable,
1534 """Return the list of default arguments of obj if it is callable,
1534 or empty list otherwise."""
1535 or empty list otherwise."""
1535 call_obj = obj
1536 call_obj = obj
1536 ret = []
1537 ret = []
1537 if inspect.isbuiltin(obj):
1538 if inspect.isbuiltin(obj):
1538 pass
1539 pass
1539 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
1540 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
1540 if inspect.isclass(obj):
1541 if inspect.isclass(obj):
1541 #for cython embedsignature=True the constructor docstring
1542 #for cython embedsignature=True the constructor docstring
1542 #belongs to the object itself not __init__
1543 #belongs to the object itself not __init__
1543 ret += self._default_arguments_from_docstring(
1544 ret += self._default_arguments_from_docstring(
1544 getattr(obj, '__doc__', ''))
1545 getattr(obj, '__doc__', ''))
1545 # for classes, check for __init__,__new__
1546 # for classes, check for __init__,__new__
1546 call_obj = (getattr(obj, '__init__', None) or
1547 call_obj = (getattr(obj, '__init__', None) or
1547 getattr(obj, '__new__', None))
1548 getattr(obj, '__new__', None))
1548 # for all others, check if they are __call__able
1549 # for all others, check if they are __call__able
1549 elif hasattr(obj, '__call__'):
1550 elif hasattr(obj, '__call__'):
1550 call_obj = obj.__call__
1551 call_obj = obj.__call__
1551 ret += self._default_arguments_from_docstring(
1552 ret += self._default_arguments_from_docstring(
1552 getattr(call_obj, '__doc__', ''))
1553 getattr(call_obj, '__doc__', ''))
1553
1554
1554 _keeps = (inspect.Parameter.KEYWORD_ONLY,
1555 _keeps = (inspect.Parameter.KEYWORD_ONLY,
1555 inspect.Parameter.POSITIONAL_OR_KEYWORD)
1556 inspect.Parameter.POSITIONAL_OR_KEYWORD)
1556
1557
1557 try:
1558 try:
1558 sig = inspect.signature(call_obj)
1559 sig = inspect.signature(call_obj)
1559 ret.extend(k for k, v in sig.parameters.items() if
1560 ret.extend(k for k, v in sig.parameters.items() if
1560 v.kind in _keeps)
1561 v.kind in _keeps)
1561 except ValueError:
1562 except ValueError:
1562 pass
1563 pass
1563
1564
1564 return list(set(ret))
1565 return list(set(ret))
1565
1566
1566 def python_func_kw_matches(self, text):
1567 def python_func_kw_matches(self, text):
1567 """Match named parameters (kwargs) of the last open function"""
1568 """Match named parameters (kwargs) of the last open function"""
1568
1569
1569 if "." in text: # a parameter cannot be dotted
1570 if "." in text: # a parameter cannot be dotted
1570 return []
1571 return []
1571 try: regexp = self.__funcParamsRegex
1572 try: regexp = self.__funcParamsRegex
1572 except AttributeError:
1573 except AttributeError:
1573 regexp = self.__funcParamsRegex = re.compile(r'''
1574 regexp = self.__funcParamsRegex = re.compile(r'''
1574 '.*?(?<!\\)' | # single quoted strings or
1575 '.*?(?<!\\)' | # single quoted strings or
1575 ".*?(?<!\\)" | # double quoted strings or
1576 ".*?(?<!\\)" | # double quoted strings or
1576 \w+ | # identifier
1577 \w+ | # identifier
1577 \S # other characters
1578 \S # other characters
1578 ''', re.VERBOSE | re.DOTALL)
1579 ''', re.VERBOSE | re.DOTALL)
1579 # 1. find the nearest identifier that comes before an unclosed
1580 # 1. find the nearest identifier that comes before an unclosed
1580 # parenthesis before the cursor
1581 # parenthesis before the cursor
1581 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
1582 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
1582 tokens = regexp.findall(self.text_until_cursor)
1583 tokens = regexp.findall(self.text_until_cursor)
1583 iterTokens = reversed(tokens); openPar = 0
1584 iterTokens = reversed(tokens); openPar = 0
1584
1585
1585 for token in iterTokens:
1586 for token in iterTokens:
1586 if token == ')':
1587 if token == ')':
1587 openPar -= 1
1588 openPar -= 1
1588 elif token == '(':
1589 elif token == '(':
1589 openPar += 1
1590 openPar += 1
1590 if openPar > 0:
1591 if openPar > 0:
1591 # found the last unclosed parenthesis
1592 # found the last unclosed parenthesis
1592 break
1593 break
1593 else:
1594 else:
1594 return []
1595 return []
1595 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
1596 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
1596 ids = []
1597 ids = []
1597 isId = re.compile(r'\w+$').match
1598 isId = re.compile(r'\w+$').match
1598
1599
1599 while True:
1600 while True:
1600 try:
1601 try:
1601 ids.append(next(iterTokens))
1602 ids.append(next(iterTokens))
1602 if not isId(ids[-1]):
1603 if not isId(ids[-1]):
1603 ids.pop(); break
1604 ids.pop(); break
1604 if not next(iterTokens) == '.':
1605 if not next(iterTokens) == '.':
1605 break
1606 break
1606 except StopIteration:
1607 except StopIteration:
1607 break
1608 break
1608
1609
1609 # Find all named arguments already assigned to, as to avoid suggesting
1610 # Find all named arguments already assigned to, as to avoid suggesting
1610 # them again
1611 # them again
1611 usedNamedArgs = set()
1612 usedNamedArgs = set()
1612 par_level = -1
1613 par_level = -1
1613 for token, next_token in zip(tokens, tokens[1:]):
1614 for token, next_token in zip(tokens, tokens[1:]):
1614 if token == '(':
1615 if token == '(':
1615 par_level += 1
1616 par_level += 1
1616 elif token == ')':
1617 elif token == ')':
1617 par_level -= 1
1618 par_level -= 1
1618
1619
1619 if par_level != 0:
1620 if par_level != 0:
1620 continue
1621 continue
1621
1622
1622 if next_token != '=':
1623 if next_token != '=':
1623 continue
1624 continue
1624
1625
1625 usedNamedArgs.add(token)
1626 usedNamedArgs.add(token)
1626
1627
1627 argMatches = []
1628 argMatches = []
1628 try:
1629 try:
1629 callableObj = '.'.join(ids[::-1])
1630 callableObj = '.'.join(ids[::-1])
1630 namedArgs = self._default_arguments(eval(callableObj,
1631 namedArgs = self._default_arguments(eval(callableObj,
1631 self.namespace))
1632 self.namespace))
1632
1633
1633 # Remove used named arguments from the list, no need to show twice
1634 # Remove used named arguments from the list, no need to show twice
1634 for namedArg in set(namedArgs) - usedNamedArgs:
1635 for namedArg in set(namedArgs) - usedNamedArgs:
1635 if namedArg.startswith(text):
1636 if namedArg.startswith(text):
1636 argMatches.append("%s=" %namedArg)
1637 argMatches.append("%s=" %namedArg)
1637 except:
1638 except:
1638 pass
1639 pass
1639
1640
1640 return argMatches
1641 return argMatches
1641
1642
1642 @staticmethod
1643 @staticmethod
1643 def _get_keys(obj: Any) -> List[Any]:
1644 def _get_keys(obj: Any) -> List[Any]:
1644 # Objects can define their own completions by defining an
1645 # Objects can define their own completions by defining an
1645 # _ipy_key_completions_() method.
1646 # _ipy_key_completions_() method.
1646 method = get_real_method(obj, '_ipython_key_completions_')
1647 method = get_real_method(obj, '_ipython_key_completions_')
1647 if method is not None:
1648 if method is not None:
1648 return method()
1649 return method()
1649
1650
1650 # Special case some common in-memory dict-like types
1651 # Special case some common in-memory dict-like types
1651 if isinstance(obj, dict) or\
1652 if isinstance(obj, dict) or\
1652 _safe_isinstance(obj, 'pandas', 'DataFrame'):
1653 _safe_isinstance(obj, 'pandas', 'DataFrame'):
1653 try:
1654 try:
1654 return list(obj.keys())
1655 return list(obj.keys())
1655 except Exception:
1656 except Exception:
1656 return []
1657 return []
1657 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
1658 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
1658 _safe_isinstance(obj, 'numpy', 'void'):
1659 _safe_isinstance(obj, 'numpy', 'void'):
1659 return obj.dtype.names or []
1660 return obj.dtype.names or []
1660 return []
1661 return []
1661
1662
1662 def dict_key_matches(self, text:str) -> List[str]:
1663 def dict_key_matches(self, text:str) -> List[str]:
1663 "Match string keys in a dictionary, after e.g. 'foo[' "
1664 "Match string keys in a dictionary, after e.g. 'foo[' "
1664
1665
1665
1666
1666 if self.__dict_key_regexps is not None:
1667 if self.__dict_key_regexps is not None:
1667 regexps = self.__dict_key_regexps
1668 regexps = self.__dict_key_regexps
1668 else:
1669 else:
1669 dict_key_re_fmt = r'''(?x)
1670 dict_key_re_fmt = r'''(?x)
1670 ( # match dict-referring expression wrt greedy setting
1671 ( # match dict-referring expression wrt greedy setting
1671 %s
1672 %s
1672 )
1673 )
1673 \[ # open bracket
1674 \[ # open bracket
1674 \s* # and optional whitespace
1675 \s* # and optional whitespace
1675 # Capture any number of str-like objects (e.g. "a", "b", 'c')
1676 # Capture any number of str-like objects (e.g. "a", "b", 'c')
1676 ((?:[uUbB]? # string prefix (r not handled)
1677 ((?:[uUbB]? # string prefix (r not handled)
1677 (?:
1678 (?:
1678 '(?:[^']|(?<!\\)\\')*'
1679 '(?:[^']|(?<!\\)\\')*'
1679 |
1680 |
1680 "(?:[^"]|(?<!\\)\\")*"
1681 "(?:[^"]|(?<!\\)\\")*"
1681 )
1682 )
1682 \s*,\s*
1683 \s*,\s*
1683 )*)
1684 )*)
1684 ([uUbB]? # string prefix (r not handled)
1685 ([uUbB]? # string prefix (r not handled)
1685 (?: # unclosed string
1686 (?: # unclosed string
1686 '(?:[^']|(?<!\\)\\')*
1687 '(?:[^']|(?<!\\)\\')*
1687 |
1688 |
1688 "(?:[^"]|(?<!\\)\\")*
1689 "(?:[^"]|(?<!\\)\\")*
1689 )
1690 )
1690 )?
1691 )?
1691 $
1692 $
1692 '''
1693 '''
1693 regexps = self.__dict_key_regexps = {
1694 regexps = self.__dict_key_regexps = {
1694 False: re.compile(dict_key_re_fmt % r'''
1695 False: re.compile(dict_key_re_fmt % r'''
1695 # identifiers separated by .
1696 # identifiers separated by .
1696 (?!\d)\w+
1697 (?!\d)\w+
1697 (?:\.(?!\d)\w+)*
1698 (?:\.(?!\d)\w+)*
1698 '''),
1699 '''),
1699 True: re.compile(dict_key_re_fmt % '''
1700 True: re.compile(dict_key_re_fmt % '''
1700 .+
1701 .+
1701 ''')
1702 ''')
1702 }
1703 }
1703
1704
1704 match = regexps[self.greedy].search(self.text_until_cursor)
1705 match = regexps[self.greedy].search(self.text_until_cursor)
1705
1706
1706 if match is None:
1707 if match is None:
1707 return []
1708 return []
1708
1709
1709 expr, prefix0, prefix = match.groups()
1710 expr, prefix0, prefix = match.groups()
1710 try:
1711 try:
1711 obj = eval(expr, self.namespace)
1712 obj = eval(expr, self.namespace)
1712 except Exception:
1713 except Exception:
1713 try:
1714 try:
1714 obj = eval(expr, self.global_namespace)
1715 obj = eval(expr, self.global_namespace)
1715 except Exception:
1716 except Exception:
1716 return []
1717 return []
1717
1718
1718 keys = self._get_keys(obj)
1719 keys = self._get_keys(obj)
1719 if not keys:
1720 if not keys:
1720 return keys
1721 return keys
1721
1722
1722 extra_prefix = eval(prefix0) if prefix0 != '' else None
1723 extra_prefix = eval(prefix0) if prefix0 != '' else None
1723
1724
1724 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims, extra_prefix=extra_prefix)
1725 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims, extra_prefix=extra_prefix)
1725 if not matches:
1726 if not matches:
1726 return matches
1727 return matches
1727
1728
1728 # get the cursor position of
1729 # get the cursor position of
1729 # - the text being completed
1730 # - the text being completed
1730 # - the start of the key text
1731 # - the start of the key text
1731 # - the start of the completion
1732 # - the start of the completion
1732 text_start = len(self.text_until_cursor) - len(text)
1733 text_start = len(self.text_until_cursor) - len(text)
1733 if prefix:
1734 if prefix:
1734 key_start = match.start(3)
1735 key_start = match.start(3)
1735 completion_start = key_start + token_offset
1736 completion_start = key_start + token_offset
1736 else:
1737 else:
1737 key_start = completion_start = match.end()
1738 key_start = completion_start = match.end()
1738
1739
1739 # grab the leading prefix, to make sure all completions start with `text`
1740 # grab the leading prefix, to make sure all completions start with `text`
1740 if text_start > key_start:
1741 if text_start > key_start:
1741 leading = ''
1742 leading = ''
1742 else:
1743 else:
1743 leading = text[text_start:completion_start]
1744 leading = text[text_start:completion_start]
1744
1745
1745 # the index of the `[` character
1746 # the index of the `[` character
1746 bracket_idx = match.end(1)
1747 bracket_idx = match.end(1)
1747
1748
1748 # append closing quote and bracket as appropriate
1749 # append closing quote and bracket as appropriate
1749 # this is *not* appropriate if the opening quote or bracket is outside
1750 # this is *not* appropriate if the opening quote or bracket is outside
1750 # the text given to this method
1751 # the text given to this method
1751 suf = ''
1752 suf = ''
1752 continuation = self.line_buffer[len(self.text_until_cursor):]
1753 continuation = self.line_buffer[len(self.text_until_cursor):]
1753 if key_start > text_start and closing_quote:
1754 if key_start > text_start and closing_quote:
1754 # quotes were opened inside text, maybe close them
1755 # quotes were opened inside text, maybe close them
1755 if continuation.startswith(closing_quote):
1756 if continuation.startswith(closing_quote):
1756 continuation = continuation[len(closing_quote):]
1757 continuation = continuation[len(closing_quote):]
1757 else:
1758 else:
1758 suf += closing_quote
1759 suf += closing_quote
1759 if bracket_idx > text_start:
1760 if bracket_idx > text_start:
1760 # brackets were opened inside text, maybe close them
1761 # brackets were opened inside text, maybe close them
1761 if not continuation.startswith(']'):
1762 if not continuation.startswith(']'):
1762 suf += ']'
1763 suf += ']'
1763
1764
1764 return [leading + k + suf for k in matches]
1765 return [leading + k + suf for k in matches]
1765
1766
1766 @staticmethod
1767 @staticmethod
1767 def unicode_name_matches(text:str) -> Tuple[str, List[str]] :
1768 def unicode_name_matches(text:str) -> Tuple[str, List[str]] :
1768 """Match Latex-like syntax for unicode characters base
1769 """Match Latex-like syntax for unicode characters base
1769 on the name of the character.
1770 on the name of the character.
1770
1771
1771 This does ``\\GREEK SMALL LETTER ETA`` -> ``Ξ·``
1772 This does ``\\GREEK SMALL LETTER ETA`` -> ``Ξ·``
1772
1773
1773 Works only on valid python 3 identifier, or on combining characters that
1774 Works only on valid python 3 identifier, or on combining characters that
1774 will combine to form a valid identifier.
1775 will combine to form a valid identifier.
1775 """
1776 """
1776 slashpos = text.rfind('\\')
1777 slashpos = text.rfind('\\')
1777 if slashpos > -1:
1778 if slashpos > -1:
1778 s = text[slashpos+1:]
1779 s = text[slashpos+1:]
1779 try :
1780 try :
1780 unic = unicodedata.lookup(s)
1781 unic = unicodedata.lookup(s)
1781 # allow combining chars
1782 # allow combining chars
1782 if ('a'+unic).isidentifier():
1783 if ('a'+unic).isidentifier():
1783 return '\\'+s,[unic]
1784 return '\\'+s,[unic]
1784 except KeyError:
1785 except KeyError:
1785 pass
1786 pass
1786 return '', []
1787 return '', []
1787
1788
1788
1789
1789 def latex_matches(self, text:str) -> Tuple[str, Sequence[str]]:
1790 def latex_matches(self, text:str) -> Tuple[str, Sequence[str]]:
1790 """Match Latex syntax for unicode characters.
1791 """Match Latex syntax for unicode characters.
1791
1792
1792 This does both ``\\alp`` -> ``\\alpha`` and ``\\alpha`` -> ``Ξ±``
1793 This does both ``\\alp`` -> ``\\alpha`` and ``\\alpha`` -> ``Ξ±``
1793 """
1794 """
1794 slashpos = text.rfind('\\')
1795 slashpos = text.rfind('\\')
1795 if slashpos > -1:
1796 if slashpos > -1:
1796 s = text[slashpos:]
1797 s = text[slashpos:]
1797 if s in latex_symbols:
1798 if s in latex_symbols:
1798 # Try to complete a full latex symbol to unicode
1799 # Try to complete a full latex symbol to unicode
1799 # \\alpha -> Ξ±
1800 # \\alpha -> Ξ±
1800 return s, [latex_symbols[s]]
1801 return s, [latex_symbols[s]]
1801 else:
1802 else:
1802 # If a user has partially typed a latex symbol, give them
1803 # If a user has partially typed a latex symbol, give them
1803 # a full list of options \al -> [\aleph, \alpha]
1804 # a full list of options \al -> [\aleph, \alpha]
1804 matches = [k for k in latex_symbols if k.startswith(s)]
1805 matches = [k for k in latex_symbols if k.startswith(s)]
1805 if matches:
1806 if matches:
1806 return s, matches
1807 return s, matches
1807 return '', ()
1808 return '', ()
1808
1809
1809 def dispatch_custom_completer(self, text):
1810 def dispatch_custom_completer(self, text):
1810 if not self.custom_completers:
1811 if not self.custom_completers:
1811 return
1812 return
1812
1813
1813 line = self.line_buffer
1814 line = self.line_buffer
1814 if not line.strip():
1815 if not line.strip():
1815 return None
1816 return None
1816
1817
1817 # Create a little structure to pass all the relevant information about
1818 # Create a little structure to pass all the relevant information about
1818 # the current completion to any custom completer.
1819 # the current completion to any custom completer.
1819 event = SimpleNamespace()
1820 event = SimpleNamespace()
1820 event.line = line
1821 event.line = line
1821 event.symbol = text
1822 event.symbol = text
1822 cmd = line.split(None,1)[0]
1823 cmd = line.split(None,1)[0]
1823 event.command = cmd
1824 event.command = cmd
1824 event.text_until_cursor = self.text_until_cursor
1825 event.text_until_cursor = self.text_until_cursor
1825
1826
1826 # for foo etc, try also to find completer for %foo
1827 # for foo etc, try also to find completer for %foo
1827 if not cmd.startswith(self.magic_escape):
1828 if not cmd.startswith(self.magic_escape):
1828 try_magic = self.custom_completers.s_matches(
1829 try_magic = self.custom_completers.s_matches(
1829 self.magic_escape + cmd)
1830 self.magic_escape + cmd)
1830 else:
1831 else:
1831 try_magic = []
1832 try_magic = []
1832
1833
1833 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1834 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1834 try_magic,
1835 try_magic,
1835 self.custom_completers.flat_matches(self.text_until_cursor)):
1836 self.custom_completers.flat_matches(self.text_until_cursor)):
1836 try:
1837 try:
1837 res = c(event)
1838 res = c(event)
1838 if res:
1839 if res:
1839 # first, try case sensitive match
1840 # first, try case sensitive match
1840 withcase = [r for r in res if r.startswith(text)]
1841 withcase = [r for r in res if r.startswith(text)]
1841 if withcase:
1842 if withcase:
1842 return withcase
1843 return withcase
1843 # if none, then case insensitive ones are ok too
1844 # if none, then case insensitive ones are ok too
1844 text_low = text.lower()
1845 text_low = text.lower()
1845 return [r for r in res if r.lower().startswith(text_low)]
1846 return [r for r in res if r.lower().startswith(text_low)]
1846 except TryNext:
1847 except TryNext:
1847 pass
1848 pass
1848 except KeyboardInterrupt:
1849 except KeyboardInterrupt:
1849 """
1850 """
1850 If custom completer take too long,
1851 If custom completer take too long,
1851 let keyboard interrupt abort and return nothing.
1852 let keyboard interrupt abort and return nothing.
1852 """
1853 """
1853 break
1854 break
1854
1855
1855 return None
1856 return None
1856
1857
1857 def completions(self, text: str, offset: int)->Iterator[Completion]:
1858 def completions(self, text: str, offset: int)->Iterator[Completion]:
1858 """
1859 """
1859 Returns an iterator over the possible completions
1860 Returns an iterator over the possible completions
1860
1861
1861 .. warning:: Unstable
1862 .. warning:: Unstable
1862
1863
1863 This function is unstable, API may change without warning.
1864 This function is unstable, API may change without warning.
1864 It will also raise unless use in proper context manager.
1865 It will also raise unless use in proper context manager.
1865
1866
1866 Parameters
1867 Parameters
1867 ----------
1868 ----------
1868
1869
1869 text:str
1870 text:str
1870 Full text of the current input, multi line string.
1871 Full text of the current input, multi line string.
1871 offset:int
1872 offset:int
1872 Integer representing the position of the cursor in ``text``. Offset
1873 Integer representing the position of the cursor in ``text``. Offset
1873 is 0-based indexed.
1874 is 0-based indexed.
1874
1875
1875 Yields
1876 Yields
1876 ------
1877 ------
1877 :any:`Completion` object
1878 Completion
1878
1879
1880
1881 Notes
1882 -----
1879
1883
1880 The cursor on a text can either be seen as being "in between"
1884 The cursor on a text can either be seen as being "in between"
1881 characters or "On" a character depending on the interface visible to
1885 characters or "On" a character depending on the interface visible to
1882 the user. For consistency the cursor being on "in between" characters X
1886 the user. For consistency the cursor being on "in between" characters X
1883 and Y is equivalent to the cursor being "on" character Y, that is to say
1887 and Y is equivalent to the cursor being "on" character Y, that is to say
1884 the character the cursor is on is considered as being after the cursor.
1888 the character the cursor is on is considered as being after the cursor.
1885
1889
1886 Combining characters may span more that one position in the
1890 Combining characters may span more that one position in the
1887 text.
1891 text.
1888
1892
1889
1893
1890 .. note::
1894 .. note::
1891
1895
1892 If ``IPCompleter.debug`` is :any:`True` will yield a ``--jedi/ipython--``
1896 If ``IPCompleter.debug`` is :any:`True` will yield a ``--jedi/ipython--``
1893 fake Completion token to distinguish completion returned by Jedi
1897 fake Completion token to distinguish completion returned by Jedi
1894 and usual IPython completion.
1898 and usual IPython completion.
1895
1899
1896 .. note::
1900 .. note::
1897
1901
1898 Completions are not completely deduplicated yet. If identical
1902 Completions are not completely deduplicated yet. If identical
1899 completions are coming from different sources this function does not
1903 completions are coming from different sources this function does not
1900 ensure that each completion object will only be present once.
1904 ensure that each completion object will only be present once.
1901 """
1905 """
1902 warnings.warn("_complete is a provisional API (as of IPython 6.0). "
1906 warnings.warn("_complete is a provisional API (as of IPython 6.0). "
1903 "It may change without warnings. "
1907 "It may change without warnings. "
1904 "Use in corresponding context manager.",
1908 "Use in corresponding context manager.",
1905 category=ProvisionalCompleterWarning, stacklevel=2)
1909 category=ProvisionalCompleterWarning, stacklevel=2)
1906
1910
1907 seen = set()
1911 seen = set()
1908 profiler:Optional[cProfile.Profile]
1912 profiler:Optional[cProfile.Profile]
1909 try:
1913 try:
1910 if self.profile_completions:
1914 if self.profile_completions:
1911 import cProfile
1915 import cProfile
1912 profiler = cProfile.Profile()
1916 profiler = cProfile.Profile()
1913 profiler.enable()
1917 profiler.enable()
1914 else:
1918 else:
1915 profiler = None
1919 profiler = None
1916
1920
1917 for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000):
1921 for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000):
1918 if c and (c in seen):
1922 if c and (c in seen):
1919 continue
1923 continue
1920 yield c
1924 yield c
1921 seen.add(c)
1925 seen.add(c)
1922 except KeyboardInterrupt:
1926 except KeyboardInterrupt:
1923 """if completions take too long and users send keyboard interrupt,
1927 """if completions take too long and users send keyboard interrupt,
1924 do not crash and return ASAP. """
1928 do not crash and return ASAP. """
1925 pass
1929 pass
1926 finally:
1930 finally:
1927 if profiler is not None:
1931 if profiler is not None:
1928 profiler.disable()
1932 profiler.disable()
1929 ensure_dir_exists(self.profiler_output_dir)
1933 ensure_dir_exists(self.profiler_output_dir)
1930 output_path = os.path.join(self.profiler_output_dir, str(uuid.uuid4()))
1934 output_path = os.path.join(self.profiler_output_dir, str(uuid.uuid4()))
1931 print("Writing profiler output to", output_path)
1935 print("Writing profiler output to", output_path)
1932 profiler.dump_stats(output_path)
1936 profiler.dump_stats(output_path)
1933
1937
1934 def _completions(self, full_text: str, offset: int, *, _timeout) -> Iterator[Completion]:
1938 def _completions(self, full_text: str, offset: int, *, _timeout) -> Iterator[Completion]:
1935 """
1939 """
1936 Core completion module.Same signature as :any:`completions`, with the
1940 Core completion module.Same signature as :any:`completions`, with the
1937 extra `timeout` parameter (in seconds).
1941 extra `timeout` parameter (in seconds).
1938
1942
1939
1943
1940 Computing jedi's completion ``.type`` can be quite expensive (it is a
1944 Computing jedi's completion ``.type`` can be quite expensive (it is a
1941 lazy property) and can require some warm-up, more warm up than just
1945 lazy property) and can require some warm-up, more warm up than just
1942 computing the ``name`` of a completion. The warm-up can be :
1946 computing the ``name`` of a completion. The warm-up can be :
1943
1947
1944 - Long warm-up the first time a module is encountered after
1948 - Long warm-up the first time a module is encountered after
1945 install/update: actually build parse/inference tree.
1949 install/update: actually build parse/inference tree.
1946
1950
1947 - first time the module is encountered in a session: load tree from
1951 - first time the module is encountered in a session: load tree from
1948 disk.
1952 disk.
1949
1953
1950 We don't want to block completions for tens of seconds so we give the
1954 We don't want to block completions for tens of seconds so we give the
1951 completer a "budget" of ``_timeout`` seconds per invocation to compute
1955 completer a "budget" of ``_timeout`` seconds per invocation to compute
1952 completions types, the completions that have not yet been computed will
1956 completions types, the completions that have not yet been computed will
1953 be marked as "unknown" an will have a chance to be computed next round
1957 be marked as "unknown" an will have a chance to be computed next round
1954 are things get cached.
1958 are things get cached.
1955
1959
1956 Keep in mind that Jedi is not the only thing treating the completion so
1960 Keep in mind that Jedi is not the only thing treating the completion so
1957 keep the timeout short-ish as if we take more than 0.3 second we still
1961 keep the timeout short-ish as if we take more than 0.3 second we still
1958 have lots of processing to do.
1962 have lots of processing to do.
1959
1963
1960 """
1964 """
1961 deadline = time.monotonic() + _timeout
1965 deadline = time.monotonic() + _timeout
1962
1966
1963
1967
1964 before = full_text[:offset]
1968 before = full_text[:offset]
1965 cursor_line, cursor_column = position_to_cursor(full_text, offset)
1969 cursor_line, cursor_column = position_to_cursor(full_text, offset)
1966
1970
1967 matched_text, matches, matches_origin, jedi_matches = self._complete(
1971 matched_text, matches, matches_origin, jedi_matches = self._complete(
1968 full_text=full_text, cursor_line=cursor_line, cursor_pos=cursor_column)
1972 full_text=full_text, cursor_line=cursor_line, cursor_pos=cursor_column)
1969
1973
1970 iter_jm = iter(jedi_matches)
1974 iter_jm = iter(jedi_matches)
1971 if _timeout:
1975 if _timeout:
1972 for jm in iter_jm:
1976 for jm in iter_jm:
1973 try:
1977 try:
1974 type_ = jm.type
1978 type_ = jm.type
1975 except Exception:
1979 except Exception:
1976 if self.debug:
1980 if self.debug:
1977 print("Error in Jedi getting type of ", jm)
1981 print("Error in Jedi getting type of ", jm)
1978 type_ = None
1982 type_ = None
1979 delta = len(jm.name_with_symbols) - len(jm.complete)
1983 delta = len(jm.name_with_symbols) - len(jm.complete)
1980 if type_ == 'function':
1984 if type_ == 'function':
1981 signature = _make_signature(jm)
1985 signature = _make_signature(jm)
1982 else:
1986 else:
1983 signature = ''
1987 signature = ''
1984 yield Completion(start=offset - delta,
1988 yield Completion(start=offset - delta,
1985 end=offset,
1989 end=offset,
1986 text=jm.name_with_symbols,
1990 text=jm.name_with_symbols,
1987 type=type_,
1991 type=type_,
1988 signature=signature,
1992 signature=signature,
1989 _origin='jedi')
1993 _origin='jedi')
1990
1994
1991 if time.monotonic() > deadline:
1995 if time.monotonic() > deadline:
1992 break
1996 break
1993
1997
1994 for jm in iter_jm:
1998 for jm in iter_jm:
1995 delta = len(jm.name_with_symbols) - len(jm.complete)
1999 delta = len(jm.name_with_symbols) - len(jm.complete)
1996 yield Completion(start=offset - delta,
2000 yield Completion(start=offset - delta,
1997 end=offset,
2001 end=offset,
1998 text=jm.name_with_symbols,
2002 text=jm.name_with_symbols,
1999 type='<unknown>', # don't compute type for speed
2003 type='<unknown>', # don't compute type for speed
2000 _origin='jedi',
2004 _origin='jedi',
2001 signature='')
2005 signature='')
2002
2006
2003
2007
2004 start_offset = before.rfind(matched_text)
2008 start_offset = before.rfind(matched_text)
2005
2009
2006 # TODO:
2010 # TODO:
2007 # Suppress this, right now just for debug.
2011 # Suppress this, right now just for debug.
2008 if jedi_matches and matches and self.debug:
2012 if jedi_matches and matches and self.debug:
2009 yield Completion(start=start_offset, end=offset, text='--jedi/ipython--',
2013 yield Completion(start=start_offset, end=offset, text='--jedi/ipython--',
2010 _origin='debug', type='none', signature='')
2014 _origin='debug', type='none', signature='')
2011
2015
2012 # I'm unsure if this is always true, so let's assert and see if it
2016 # I'm unsure if this is always true, so let's assert and see if it
2013 # crash
2017 # crash
2014 assert before.endswith(matched_text)
2018 assert before.endswith(matched_text)
2015 for m, t in zip(matches, matches_origin):
2019 for m, t in zip(matches, matches_origin):
2016 yield Completion(start=start_offset, end=offset, text=m, _origin=t, signature='', type='<unknown>')
2020 yield Completion(start=start_offset, end=offset, text=m, _origin=t, signature='', type='<unknown>')
2017
2021
2018
2022
2019 def complete(self, text=None, line_buffer=None, cursor_pos=None) -> Tuple[str, Sequence[str]]:
2023 def complete(self, text=None, line_buffer=None, cursor_pos=None) -> Tuple[str, Sequence[str]]:
2020 """Find completions for the given text and line context.
2024 """Find completions for the given text and line context.
2021
2025
2022 Note that both the text and the line_buffer are optional, but at least
2026 Note that both the text and the line_buffer are optional, but at least
2023 one of them must be given.
2027 one of them must be given.
2024
2028
2025 Parameters
2029 Parameters
2026 ----------
2030 ----------
2027 text : string, optional
2031 text : string, optional
2028 Text to perform the completion on. If not given, the line buffer
2032 Text to perform the completion on. If not given, the line buffer
2029 is split using the instance's CompletionSplitter object.
2033 is split using the instance's CompletionSplitter object.
2030
2034
2031 line_buffer : string, optional
2035 line_buffer : string, optional
2032 If not given, the completer attempts to obtain the current line
2036 If not given, the completer attempts to obtain the current line
2033 buffer via readline. This keyword allows clients which are
2037 buffer via readline. This keyword allows clients which are
2034 requesting for text completions in non-readline contexts to inform
2038 requesting for text completions in non-readline contexts to inform
2035 the completer of the entire text.
2039 the completer of the entire text.
2036
2040
2037 cursor_pos : int, optional
2041 cursor_pos : int, optional
2038 Index of the cursor in the full line buffer. Should be provided by
2042 Index of the cursor in the full line buffer. Should be provided by
2039 remote frontends where kernel has no access to frontend state.
2043 remote frontends where kernel has no access to frontend state.
2040
2044
2041 Returns
2045 Returns
2042 -------
2046 -------
2043 Tuple of two items:
2047 Tuple of two items:
2044 text : str
2048 text : str
2045 Text that was actually used in the completion.
2049 Text that was actually used in the completion.
2046 matches : list
2050 matches : list
2047 A list of completion matches.
2051 A list of completion matches.
2048
2052
2049
2053
2050 .. note::
2054 Notes
2055 -----
2051
2056
2052 This API is likely to be deprecated and replaced by
2057 This API is likely to be deprecated and replaced by
2053 :any:`IPCompleter.completions` in the future.
2058 :any:`IPCompleter.completions` in the future.
2054
2059
2055
2060
2056 """
2061 """
2057 warnings.warn('`Completer.complete` is pending deprecation since '
2062 warnings.warn('`Completer.complete` is pending deprecation since '
2058 'IPython 6.0 and will be replaced by `Completer.completions`.',
2063 'IPython 6.0 and will be replaced by `Completer.completions`.',
2059 PendingDeprecationWarning)
2064 PendingDeprecationWarning)
2060 # potential todo, FOLD the 3rd throw away argument of _complete
2065 # potential todo, FOLD the 3rd throw away argument of _complete
2061 # into the first 2 one.
2066 # into the first 2 one.
2062 return self._complete(line_buffer=line_buffer, cursor_pos=cursor_pos, text=text, cursor_line=0)[:2]
2067 return self._complete(line_buffer=line_buffer, cursor_pos=cursor_pos, text=text, cursor_line=0)[:2]
2063
2068
2064 def _complete(self, *, cursor_line, cursor_pos, line_buffer=None, text=None,
2069 def _complete(self, *, cursor_line, cursor_pos, line_buffer=None, text=None,
2065 full_text=None) -> _CompleteResult:
2070 full_text=None) -> _CompleteResult:
2066 """
2071 """
2067
2072
2068 Like complete but can also returns raw jedi completions as well as the
2073 Like complete but can also returns raw jedi completions as well as the
2069 origin of the completion text. This could (and should) be made much
2074 origin of the completion text. This could (and should) be made much
2070 cleaner but that will be simpler once we drop the old (and stateful)
2075 cleaner but that will be simpler once we drop the old (and stateful)
2071 :any:`complete` API.
2076 :any:`complete` API.
2072
2077
2073
2078
2074 With current provisional API, cursor_pos act both (depending on the
2079 With current provisional API, cursor_pos act both (depending on the
2075 caller) as the offset in the ``text`` or ``line_buffer``, or as the
2080 caller) as the offset in the ``text`` or ``line_buffer``, or as the
2076 ``column`` when passing multiline strings this could/should be renamed
2081 ``column`` when passing multiline strings this could/should be renamed
2077 but would add extra noise.
2082 but would add extra noise.
2078
2083
2079 Return
2084 Return
2080 ======
2085 ======
2081
2086
2082 A tuple of N elements which are (likely):
2087 A tuple of N elements which are (likely):
2083
2088
2084 matched_text: ? the text that the complete matched
2089 matched_text: ? the text that the complete matched
2085 matches: list of completions ?
2090 matches: list of completions ?
2086 matches_origin: ? list same lenght as matches, and where each completion came from
2091 matches_origin: ? list same lenght as matches, and where each completion came from
2087 jedi_matches: list of Jedi matches, have it's own structure.
2092 jedi_matches: list of Jedi matches, have it's own structure.
2088 """
2093 """
2089
2094
2090
2095
2091 # if the cursor position isn't given, the only sane assumption we can
2096 # if the cursor position isn't given, the only sane assumption we can
2092 # make is that it's at the end of the line (the common case)
2097 # make is that it's at the end of the line (the common case)
2093 if cursor_pos is None:
2098 if cursor_pos is None:
2094 cursor_pos = len(line_buffer) if text is None else len(text)
2099 cursor_pos = len(line_buffer) if text is None else len(text)
2095
2100
2096 if self.use_main_ns:
2101 if self.use_main_ns:
2097 self.namespace = __main__.__dict__
2102 self.namespace = __main__.__dict__
2098
2103
2099 # if text is either None or an empty string, rely on the line buffer
2104 # if text is either None or an empty string, rely on the line buffer
2100 if (not line_buffer) and full_text:
2105 if (not line_buffer) and full_text:
2101 line_buffer = full_text.split('\n')[cursor_line]
2106 line_buffer = full_text.split('\n')[cursor_line]
2102 if not text: # issue #11508: check line_buffer before calling split_line
2107 if not text: # issue #11508: check line_buffer before calling split_line
2103 text = self.splitter.split_line(line_buffer, cursor_pos) if line_buffer else ''
2108 text = self.splitter.split_line(line_buffer, cursor_pos) if line_buffer else ''
2104
2109
2105 if self.backslash_combining_completions:
2110 if self.backslash_combining_completions:
2106 # allow deactivation of these on windows.
2111 # allow deactivation of these on windows.
2107 base_text = text if not line_buffer else line_buffer[:cursor_pos]
2112 base_text = text if not line_buffer else line_buffer[:cursor_pos]
2108
2113
2109 for meth in (self.latex_matches,
2114 for meth in (self.latex_matches,
2110 self.unicode_name_matches,
2115 self.unicode_name_matches,
2111 back_latex_name_matches,
2116 back_latex_name_matches,
2112 back_unicode_name_matches,
2117 back_unicode_name_matches,
2113 self.fwd_unicode_match):
2118 self.fwd_unicode_match):
2114 name_text, name_matches = meth(base_text)
2119 name_text, name_matches = meth(base_text)
2115 if name_text:
2120 if name_text:
2116 return _CompleteResult(name_text, name_matches[:MATCHES_LIMIT], \
2121 return _CompleteResult(name_text, name_matches[:MATCHES_LIMIT], \
2117 [meth.__qualname__]*min(len(name_matches), MATCHES_LIMIT), ())
2122 [meth.__qualname__]*min(len(name_matches), MATCHES_LIMIT), ())
2118
2123
2119
2124
2120 # If no line buffer is given, assume the input text is all there was
2125 # If no line buffer is given, assume the input text is all there was
2121 if line_buffer is None:
2126 if line_buffer is None:
2122 line_buffer = text
2127 line_buffer = text
2123
2128
2124 self.line_buffer = line_buffer
2129 self.line_buffer = line_buffer
2125 self.text_until_cursor = self.line_buffer[:cursor_pos]
2130 self.text_until_cursor = self.line_buffer[:cursor_pos]
2126
2131
2127 # Do magic arg matches
2132 # Do magic arg matches
2128 for matcher in self.magic_arg_matchers:
2133 for matcher in self.magic_arg_matchers:
2129 matches = list(matcher(line_buffer))[:MATCHES_LIMIT]
2134 matches = list(matcher(line_buffer))[:MATCHES_LIMIT]
2130 if matches:
2135 if matches:
2131 origins = [matcher.__qualname__] * len(matches)
2136 origins = [matcher.__qualname__] * len(matches)
2132 return _CompleteResult(text, matches, origins, ())
2137 return _CompleteResult(text, matches, origins, ())
2133
2138
2134 # Start with a clean slate of completions
2139 # Start with a clean slate of completions
2135 matches = []
2140 matches = []
2136
2141
2137 # FIXME: we should extend our api to return a dict with completions for
2142 # FIXME: we should extend our api to return a dict with completions for
2138 # different types of objects. The rlcomplete() method could then
2143 # different types of objects. The rlcomplete() method could then
2139 # simply collapse the dict into a list for readline, but we'd have
2144 # simply collapse the dict into a list for readline, but we'd have
2140 # richer completion semantics in other environments.
2145 # richer completion semantics in other environments.
2141 completions:Iterable[Any] = []
2146 completions:Iterable[Any] = []
2142 if self.use_jedi:
2147 if self.use_jedi:
2143 if not full_text:
2148 if not full_text:
2144 full_text = line_buffer
2149 full_text = line_buffer
2145 completions = self._jedi_matches(
2150 completions = self._jedi_matches(
2146 cursor_pos, cursor_line, full_text)
2151 cursor_pos, cursor_line, full_text)
2147
2152
2148 if self.merge_completions:
2153 if self.merge_completions:
2149 matches = []
2154 matches = []
2150 for matcher in self.matchers:
2155 for matcher in self.matchers:
2151 try:
2156 try:
2152 matches.extend([(m, matcher.__qualname__)
2157 matches.extend([(m, matcher.__qualname__)
2153 for m in matcher(text)])
2158 for m in matcher(text)])
2154 except:
2159 except:
2155 # Show the ugly traceback if the matcher causes an
2160 # Show the ugly traceback if the matcher causes an
2156 # exception, but do NOT crash the kernel!
2161 # exception, but do NOT crash the kernel!
2157 sys.excepthook(*sys.exc_info())
2162 sys.excepthook(*sys.exc_info())
2158 else:
2163 else:
2159 for matcher in self.matchers:
2164 for matcher in self.matchers:
2160 matches = [(m, matcher.__qualname__)
2165 matches = [(m, matcher.__qualname__)
2161 for m in matcher(text)]
2166 for m in matcher(text)]
2162 if matches:
2167 if matches:
2163 break
2168 break
2164
2169
2165 seen = set()
2170 seen = set()
2166 filtered_matches = set()
2171 filtered_matches = set()
2167 for m in matches:
2172 for m in matches:
2168 t, c = m
2173 t, c = m
2169 if t not in seen:
2174 if t not in seen:
2170 filtered_matches.add(m)
2175 filtered_matches.add(m)
2171 seen.add(t)
2176 seen.add(t)
2172
2177
2173 _filtered_matches = sorted(filtered_matches, key=lambda x: completions_sorting_key(x[0]))
2178 _filtered_matches = sorted(filtered_matches, key=lambda x: completions_sorting_key(x[0]))
2174
2179
2175 custom_res = [(m, 'custom') for m in self.dispatch_custom_completer(text) or []]
2180 custom_res = [(m, 'custom') for m in self.dispatch_custom_completer(text) or []]
2176
2181
2177 _filtered_matches = custom_res or _filtered_matches
2182 _filtered_matches = custom_res or _filtered_matches
2178
2183
2179 _filtered_matches = _filtered_matches[:MATCHES_LIMIT]
2184 _filtered_matches = _filtered_matches[:MATCHES_LIMIT]
2180 _matches = [m[0] for m in _filtered_matches]
2185 _matches = [m[0] for m in _filtered_matches]
2181 origins = [m[1] for m in _filtered_matches]
2186 origins = [m[1] for m in _filtered_matches]
2182
2187
2183 self.matches = _matches
2188 self.matches = _matches
2184
2189
2185 return _CompleteResult(text, _matches, origins, completions)
2190 return _CompleteResult(text, _matches, origins, completions)
2186
2191
2187 def fwd_unicode_match(self, text:str) -> Tuple[str, Sequence[str]]:
2192 def fwd_unicode_match(self, text:str) -> Tuple[str, Sequence[str]]:
2188 """
2193 """
2189
2194
2190 Forward match a string starting with a backslash with a list of
2195 Forward match a string starting with a backslash with a list of
2191 potential Unicode completions.
2196 potential Unicode completions.
2192
2197
2193 Will compute list list of Unicode character names on first call and cache it.
2198 Will compute list list of Unicode character names on first call and cache it.
2194
2199
2195 Return
2200 Return
2196 ======
2201 ======
2197
2202
2198 At tuple with:
2203 At tuple with:
2199 - matched text (empty if no matches)
2204 - matched text (empty if no matches)
2200 - list of potential completions, empty tuple otherwise)
2205 - list of potential completions, empty tuple otherwise)
2201 """
2206 """
2202 # TODO: self.unicode_names is here a list we traverse each time with ~100k elements.
2207 # TODO: self.unicode_names is here a list we traverse each time with ~100k elements.
2203 # We could do a faster match using a Trie.
2208 # We could do a faster match using a Trie.
2204
2209
2205 # Using pygtrie the follwing seem to work:
2210 # Using pygtrie the follwing seem to work:
2206
2211
2207 # s = PrefixSet()
2212 # s = PrefixSet()
2208
2213
2209 # for c in range(0,0x10FFFF + 1):
2214 # for c in range(0,0x10FFFF + 1):
2210 # try:
2215 # try:
2211 # s.add(unicodedata.name(chr(c)))
2216 # s.add(unicodedata.name(chr(c)))
2212 # except ValueError:
2217 # except ValueError:
2213 # pass
2218 # pass
2214 # [''.join(k) for k in s.iter(prefix)]
2219 # [''.join(k) for k in s.iter(prefix)]
2215
2220
2216 # But need to be timed and adds an extra dependency.
2221 # But need to be timed and adds an extra dependency.
2217
2222
2218 slashpos = text.rfind('\\')
2223 slashpos = text.rfind('\\')
2219 # if text starts with slash
2224 # if text starts with slash
2220 if slashpos > -1:
2225 if slashpos > -1:
2221 # PERF: It's important that we don't access self._unicode_names
2226 # PERF: It's important that we don't access self._unicode_names
2222 # until we're inside this if-block. _unicode_names is lazily
2227 # until we're inside this if-block. _unicode_names is lazily
2223 # initialized, and it takes a user-noticeable amount of time to
2228 # initialized, and it takes a user-noticeable amount of time to
2224 # initialize it, so we don't want to initialize it unless we're
2229 # initialize it, so we don't want to initialize it unless we're
2225 # actually going to use it.
2230 # actually going to use it.
2226 s = text[slashpos+1:]
2231 s = text[slashpos+1:]
2227 candidates = [x for x in self.unicode_names if x.startswith(s)]
2232 candidates = [x for x in self.unicode_names if x.startswith(s)]
2228 if candidates:
2233 if candidates:
2229 return s, candidates
2234 return s, candidates
2230 else:
2235 else:
2231 return '', ()
2236 return '', ()
2232
2237
2233 # if text does not start with slash
2238 # if text does not start with slash
2234 else:
2239 else:
2235 return '', ()
2240 return '', ()
2236
2241
2237 @property
2242 @property
2238 def unicode_names(self) -> List[str]:
2243 def unicode_names(self) -> List[str]:
2239 """List of names of unicode code points that can be completed.
2244 """List of names of unicode code points that can be completed.
2240
2245
2241 The list is lazily initialized on first access.
2246 The list is lazily initialized on first access.
2242 """
2247 """
2243 if self._unicode_names is None:
2248 if self._unicode_names is None:
2244 names = []
2249 names = []
2245 for c in range(0,0x10FFFF + 1):
2250 for c in range(0,0x10FFFF + 1):
2246 try:
2251 try:
2247 names.append(unicodedata.name(chr(c)))
2252 names.append(unicodedata.name(chr(c)))
2248 except ValueError:
2253 except ValueError:
2249 pass
2254 pass
2250 self._unicode_names = _unicode_name_compute(_UNICODE_RANGES)
2255 self._unicode_names = _unicode_name_compute(_UNICODE_RANGES)
2251
2256
2252 return self._unicode_names
2257 return self._unicode_names
2253
2258
2254 def _unicode_name_compute(ranges:List[Tuple[int,int]]) -> List[str]:
2259 def _unicode_name_compute(ranges:List[Tuple[int,int]]) -> List[str]:
2255 names = []
2260 names = []
2256 for start,stop in ranges:
2261 for start,stop in ranges:
2257 for c in range(start, stop) :
2262 for c in range(start, stop) :
2258 try:
2263 try:
2259 names.append(unicodedata.name(chr(c)))
2264 names.append(unicodedata.name(chr(c)))
2260 except ValueError:
2265 except ValueError:
2261 pass
2266 pass
2262 return names
2267 return names
General Comments 0
You need to be logged in to leave comments. Login now