##// END OF EJS Templates
Merge pull request #11393 from hugovk/replace-simplegeneric...
Matthias Bussonnier -
r24716:6d9a28a2 merge
parent child Browse files
Show More
@@ -1,1029 +1,1029 b''
1 1 # encoding: utf-8
2 2 """Tests for the IPython tab-completion machinery."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7 import os
8 8 import sys
9 9 import textwrap
10 10 import unittest
11 11
12 12 from contextlib import contextmanager
13 13
14 14 import nose.tools as nt
15 15
16 16 from traitlets.config.loader import Config
17 17 from IPython import get_ipython
18 18 from IPython.core import completer
19 19 from IPython.external.decorators import knownfailureif
20 20 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
21 21 from IPython.utils.generics import complete_object
22 22 from IPython.testing import decorators as dec
23 23
24 24 from IPython.core.completer import (
25 25 Completion, provisionalcompleter, match_dict_keys, _deduplicate_completions)
26 26 from nose.tools import assert_in, assert_not_in
27 27
28 28 #-----------------------------------------------------------------------------
29 29 # Test functions
30 30 #-----------------------------------------------------------------------------
31 31
32 32 @contextmanager
33 33 def greedy_completion():
34 34 ip = get_ipython()
35 35 greedy_original = ip.Completer.greedy
36 36 try:
37 37 ip.Completer.greedy = True
38 38 yield
39 39 finally:
40 40 ip.Completer.greedy = greedy_original
41 41
42 42 def test_protect_filename():
43 43 if sys.platform == 'win32':
44 44 pairs = [('abc','abc'),
45 45 (' abc','" abc"'),
46 46 ('a bc','"a bc"'),
47 47 ('a bc','"a bc"'),
48 48 (' bc','" bc"'),
49 49 ]
50 50 else:
51 51 pairs = [('abc','abc'),
52 52 (' abc',r'\ abc'),
53 53 ('a bc',r'a\ bc'),
54 54 ('a bc',r'a\ \ bc'),
55 55 (' bc',r'\ \ bc'),
56 56 # On posix, we also protect parens and other special characters.
57 57 ('a(bc',r'a\(bc'),
58 58 ('a)bc',r'a\)bc'),
59 59 ('a( )bc',r'a\(\ \)bc'),
60 60 ('a[1]bc', r'a\[1\]bc'),
61 61 ('a{1}bc', r'a\{1\}bc'),
62 62 ('a#bc', r'a\#bc'),
63 63 ('a?bc', r'a\?bc'),
64 64 ('a=bc', r'a\=bc'),
65 65 ('a\\bc', r'a\\bc'),
66 66 ('a|bc', r'a\|bc'),
67 67 ('a;bc', r'a\;bc'),
68 68 ('a:bc', r'a\:bc'),
69 69 ("a'bc", r"a\'bc"),
70 70 ('a*bc', r'a\*bc'),
71 71 ('a"bc', r'a\"bc'),
72 72 ('a^bc', r'a\^bc'),
73 73 ('a&bc', r'a\&bc'),
74 74 ]
75 75 # run the actual tests
76 76 for s1, s2 in pairs:
77 77 s1p = completer.protect_filename(s1)
78 78 nt.assert_equal(s1p, s2)
79 79
80 80
81 81 def check_line_split(splitter, test_specs):
82 82 for part1, part2, split in test_specs:
83 83 cursor_pos = len(part1)
84 84 line = part1+part2
85 85 out = splitter.split_line(line, cursor_pos)
86 86 nt.assert_equal(out, split)
87 87
88 88
89 89 def test_line_split():
90 90 """Basic line splitter test with default specs."""
91 91 sp = completer.CompletionSplitter()
92 92 # The format of the test specs is: part1, part2, expected answer. Parts 1
93 93 # and 2 are joined into the 'line' sent to the splitter, as if the cursor
94 94 # was at the end of part1. So an empty part2 represents someone hitting
95 95 # tab at the end of the line, the most common case.
96 96 t = [('run some/scrip', '', 'some/scrip'),
97 97 ('run scripts/er', 'ror.py foo', 'scripts/er'),
98 98 ('echo $HOM', '', 'HOM'),
99 99 ('print sys.pa', '', 'sys.pa'),
100 100 ('print(sys.pa', '', 'sys.pa'),
101 101 ("execfile('scripts/er", '', 'scripts/er'),
102 102 ('a[x.', '', 'x.'),
103 103 ('a[x.', 'y', 'x.'),
104 104 ('cd "some_file/', '', 'some_file/'),
105 105 ]
106 106 check_line_split(sp, t)
107 107 # Ensure splitting works OK with unicode by re-running the tests with
108 108 # all inputs turned into unicode
109 109 check_line_split(sp, [ map(str, p) for p in t] )
110 110
111 111
112 112 def test_custom_completion_error():
113 113 """Test that errors from custom attribute completers are silenced."""
114 114 ip = get_ipython()
115 115 class A(object): pass
116 116 ip.user_ns['a'] = A()
117 117
118 @complete_object.when_type(A)
118 @complete_object.register(A)
119 119 def complete_A(a, existing_completions):
120 120 raise TypeError("this should be silenced")
121 121
122 122 ip.complete("a.")
123 123
124 124
125 125 def test_unicode_completions():
126 126 ip = get_ipython()
127 127 # Some strings that trigger different types of completion. Check them both
128 128 # in str and unicode forms
129 129 s = ['ru', '%ru', 'cd /', 'floa', 'float(x)/']
130 130 for t in s + list(map(str, s)):
131 131 # We don't need to check exact completion values (they may change
132 132 # depending on the state of the namespace, but at least no exceptions
133 133 # should be thrown and the return value should be a pair of text, list
134 134 # values.
135 135 text, matches = ip.complete(t)
136 136 nt.assert_true(isinstance(text, str))
137 137 nt.assert_true(isinstance(matches, list))
138 138
139 139 def test_latex_completions():
140 140 from IPython.core.latex_symbols import latex_symbols
141 141 import random
142 142 ip = get_ipython()
143 143 # Test some random unicode symbols
144 144 keys = random.sample(latex_symbols.keys(), 10)
145 145 for k in keys:
146 146 text, matches = ip.complete(k)
147 147 nt.assert_equal(len(matches),1)
148 148 nt.assert_equal(text, k)
149 149 nt.assert_equal(matches[0], latex_symbols[k])
150 150 # Test a more complex line
151 151 text, matches = ip.complete(u'print(\\alpha')
152 152 nt.assert_equal(text, u'\\alpha')
153 153 nt.assert_equal(matches[0], latex_symbols['\\alpha'])
154 154 # Test multiple matching latex symbols
155 155 text, matches = ip.complete(u'\\al')
156 156 nt.assert_in('\\alpha', matches)
157 157 nt.assert_in('\\aleph', matches)
158 158
159 159
160 160
161 161
162 162 def test_back_latex_completion():
163 163 ip = get_ipython()
164 164
165 165 # do not return more than 1 matches fro \beta, only the latex one.
166 166 name, matches = ip.complete('\\Ξ²')
167 167 nt.assert_equal(len(matches), 1)
168 168 nt.assert_equal(matches[0], '\\beta')
169 169
170 170 def test_back_unicode_completion():
171 171 ip = get_ipython()
172 172
173 173 name, matches = ip.complete('\\β…€')
174 174 nt.assert_equal(len(matches), 1)
175 175 nt.assert_equal(matches[0], '\\ROMAN NUMERAL FIVE')
176 176
177 177
178 178 def test_forward_unicode_completion():
179 179 ip = get_ipython()
180 180
181 181 name, matches = ip.complete('\\ROMAN NUMERAL FIVE')
182 182 nt.assert_equal(len(matches), 1)
183 183 nt.assert_equal(matches[0], 'β…€')
184 184
185 185 @dec.knownfailureif(sys.platform == 'win32', 'Fails if there is a C:\\j... path')
186 186 def test_no_ascii_back_completion():
187 187 ip = get_ipython()
188 188 with TemporaryWorkingDirectory(): # Avoid any filename completions
189 189 # single ascii letter that don't have yet completions
190 190 for letter in 'jJ' :
191 191 name, matches = ip.complete('\\'+letter)
192 192 nt.assert_equal(matches, [])
193 193
194 194
195 195
196 196
197 197 class CompletionSplitterTestCase(unittest.TestCase):
198 198 def setUp(self):
199 199 self.sp = completer.CompletionSplitter()
200 200
201 201 def test_delim_setting(self):
202 202 self.sp.delims = ' '
203 203 nt.assert_equal(self.sp.delims, ' ')
204 204 nt.assert_equal(self.sp._delim_expr, '[\ ]')
205 205
206 206 def test_spaces(self):
207 207 """Test with only spaces as split chars."""
208 208 self.sp.delims = ' '
209 209 t = [('foo', '', 'foo'),
210 210 ('run foo', '', 'foo'),
211 211 ('run foo', 'bar', 'foo'),
212 212 ]
213 213 check_line_split(self.sp, t)
214 214
215 215
216 216 def test_has_open_quotes1():
217 217 for s in ["'", "'''", "'hi' '"]:
218 218 nt.assert_equal(completer.has_open_quotes(s), "'")
219 219
220 220
221 221 def test_has_open_quotes2():
222 222 for s in ['"', '"""', '"hi" "']:
223 223 nt.assert_equal(completer.has_open_quotes(s), '"')
224 224
225 225
226 226 def test_has_open_quotes3():
227 227 for s in ["''", "''' '''", "'hi' 'ipython'"]:
228 228 nt.assert_false(completer.has_open_quotes(s))
229 229
230 230
231 231 def test_has_open_quotes4():
232 232 for s in ['""', '""" """', '"hi" "ipython"']:
233 233 nt.assert_false(completer.has_open_quotes(s))
234 234
235 235
236 236 @knownfailureif(sys.platform == 'win32', "abspath completions fail on Windows")
237 237 def test_abspath_file_completions():
238 238 ip = get_ipython()
239 239 with TemporaryDirectory() as tmpdir:
240 240 prefix = os.path.join(tmpdir, 'foo')
241 241 suffixes = ['1', '2']
242 242 names = [prefix+s for s in suffixes]
243 243 for n in names:
244 244 open(n, 'w').close()
245 245
246 246 # Check simple completion
247 247 c = ip.complete(prefix)[1]
248 248 nt.assert_equal(c, names)
249 249
250 250 # Now check with a function call
251 251 cmd = 'a = f("%s' % prefix
252 252 c = ip.complete(prefix, cmd)[1]
253 253 comp = [prefix+s for s in suffixes]
254 254 nt.assert_equal(c, comp)
255 255
256 256
257 257 def test_local_file_completions():
258 258 ip = get_ipython()
259 259 with TemporaryWorkingDirectory():
260 260 prefix = './foo'
261 261 suffixes = ['1', '2']
262 262 names = [prefix+s for s in suffixes]
263 263 for n in names:
264 264 open(n, 'w').close()
265 265
266 266 # Check simple completion
267 267 c = ip.complete(prefix)[1]
268 268 nt.assert_equal(c, names)
269 269
270 270 # Now check with a function call
271 271 cmd = 'a = f("%s' % prefix
272 272 c = ip.complete(prefix, cmd)[1]
273 273 comp = set(prefix+s for s in suffixes)
274 274 nt.assert_true(comp.issubset(set(c)))
275 275
276 276
277 277 def test_quoted_file_completions():
278 278 ip = get_ipython()
279 279 with TemporaryWorkingDirectory():
280 280 name = "foo'bar"
281 281 open(name, 'w').close()
282 282
283 283 # Don't escape Windows
284 284 escaped = name if sys.platform == "win32" else "foo\\'bar"
285 285
286 286 # Single quote matches embedded single quote
287 287 text = "open('foo"
288 288 c = ip.Completer._complete(cursor_line=0,
289 289 cursor_pos=len(text),
290 290 full_text=text)[1]
291 291 nt.assert_equal(c, [escaped])
292 292
293 293 # Double quote requires no escape
294 294 text = 'open("foo'
295 295 c = ip.Completer._complete(cursor_line=0,
296 296 cursor_pos=len(text),
297 297 full_text=text)[1]
298 298 nt.assert_equal(c, [name])
299 299
300 300 # No quote requires an escape
301 301 text = '%ls foo'
302 302 c = ip.Completer._complete(cursor_line=0,
303 303 cursor_pos=len(text),
304 304 full_text=text)[1]
305 305 nt.assert_equal(c, [escaped])
306 306
307 307
308 308 def test_jedi():
309 309 """
310 310 A couple of issue we had with Jedi
311 311 """
312 312 ip = get_ipython()
313 313
314 314 def _test_complete(reason, s, comp, start=None, end=None):
315 315 l = len(s)
316 316 start = start if start is not None else l
317 317 end = end if end is not None else l
318 318 with provisionalcompleter():
319 319 ip.Completer.use_jedi = True
320 320 completions = set(ip.Completer.completions(s, l))
321 321 ip.Completer.use_jedi = False
322 322 assert_in(Completion(start, end, comp), completions, reason)
323 323
324 324 def _test_not_complete(reason, s, comp):
325 325 l = len(s)
326 326 with provisionalcompleter():
327 327 ip.Completer.use_jedi = True
328 328 completions = set(ip.Completer.completions(s, l))
329 329 ip.Completer.use_jedi = False
330 330 assert_not_in(Completion(l, l, comp), completions, reason)
331 331
332 332 import jedi
333 333 jedi_version = tuple(int(i) for i in jedi.__version__.split('.')[:3])
334 334 if jedi_version > (0, 10):
335 335 yield _test_complete, 'jedi >0.9 should complete and not crash', 'a=1;a.', 'real'
336 336 yield _test_complete, 'can infer first argument', 'a=(1,"foo");a[0].', 'real'
337 337 yield _test_complete, 'can infer second argument', 'a=(1,"foo");a[1].', 'capitalize'
338 338 yield _test_complete, 'cover duplicate completions', 'im', 'import', 0, 2
339 339
340 340 yield _test_not_complete, 'does not mix types', 'a=(1,"foo");a[0].', 'capitalize'
341 341
342 342 def test_completion_have_signature():
343 343 """
344 344 Lets make sure jedi is capable of pulling out the signature of the function we are completing.
345 345 """
346 346 ip = get_ipython()
347 347 with provisionalcompleter():
348 348 ip.Completer.use_jedi = True
349 349 completions = ip.Completer.completions('ope', 3)
350 350 c = next(completions) # should be `open`
351 351 ip.Completer.use_jedi = False
352 352 assert 'file' in c.signature, "Signature of function was not found by completer"
353 353 assert 'encoding' in c.signature, "Signature of function was not found by completer"
354 354
355 355
356 356 def test_deduplicate_completions():
357 357 """
358 358 Test that completions are correctly deduplicated (even if ranges are not the same)
359 359 """
360 360 ip = get_ipython()
361 361 ip.ex(textwrap.dedent('''
362 362 class Z:
363 363 zoo = 1
364 364 '''))
365 365 with provisionalcompleter():
366 366 ip.Completer.use_jedi = True
367 367 l = list(_deduplicate_completions('Z.z', ip.Completer.completions('Z.z', 3)))
368 368 ip.Completer.use_jedi = False
369 369
370 370 assert len(l) == 1, 'Completions (Z.z<tab>) correctly deduplicate: %s ' % l
371 371 assert l[0].text == 'zoo' # and not `it.accumulate`
372 372
373 373
374 374 def test_greedy_completions():
375 375 """
376 376 Test the capability of the Greedy completer.
377 377
378 378 Most of the test here does not really show off the greedy completer, for proof
379 379 each of the text below now pass with Jedi. The greedy completer is capable of more.
380 380
381 381 See the :any:`test_dict_key_completion_contexts`
382 382
383 383 """
384 384 ip = get_ipython()
385 385 ip.ex('a=list(range(5))')
386 386 _,c = ip.complete('.',line='a[0].')
387 387 nt.assert_false('.real' in c,
388 388 "Shouldn't have completed on a[0]: %s"%c)
389 389 with greedy_completion(), provisionalcompleter():
390 390 def _(line, cursor_pos, expect, message, completion):
391 391 ip.Completer.use_jedi = False
392 392 _,c = ip.complete('.', line=line, cursor_pos=cursor_pos)
393 393 nt.assert_in(expect, c, message % c)
394 394
395 395 ip.Completer.use_jedi = True
396 396 with provisionalcompleter():
397 397 completions = ip.Completer.completions(line, cursor_pos)
398 398 nt.assert_in(completion, completions)
399 399
400 400 yield _, 'a[0].', 5, 'a[0].real', "Should have completed on a[0].: %s", Completion(5,5, 'real')
401 401 yield _, 'a[0].r', 6, 'a[0].real', "Should have completed on a[0].r: %s", Completion(5,6, 'real')
402 402
403 403 if sys.version_info > (3, 4):
404 404 yield _, 'a[0].from_', 10, 'a[0].from_bytes', "Should have completed on a[0].from_: %s", Completion(5, 10, 'from_bytes')
405 405
406 406
407 407 def test_omit__names():
408 408 # also happens to test IPCompleter as a configurable
409 409 ip = get_ipython()
410 410 ip._hidden_attr = 1
411 411 ip._x = {}
412 412 c = ip.Completer
413 413 ip.ex('ip=get_ipython()')
414 414 cfg = Config()
415 415 cfg.IPCompleter.omit__names = 0
416 416 c.update_config(cfg)
417 417 with provisionalcompleter():
418 418 c.use_jedi = False
419 419 s,matches = c.complete('ip.')
420 420 nt.assert_in('ip.__str__', matches)
421 421 nt.assert_in('ip._hidden_attr', matches)
422 422
423 423 # c.use_jedi = True
424 424 # completions = set(c.completions('ip.', 3))
425 425 # nt.assert_in(Completion(3, 3, '__str__'), completions)
426 426 # nt.assert_in(Completion(3,3, "_hidden_attr"), completions)
427 427
428 428
429 429 cfg = Config()
430 430 cfg.IPCompleter.omit__names = 1
431 431 c.update_config(cfg)
432 432 with provisionalcompleter():
433 433 c.use_jedi = False
434 434 s,matches = c.complete('ip.')
435 435 nt.assert_not_in('ip.__str__', matches)
436 436 # nt.assert_in('ip._hidden_attr', matches)
437 437
438 438 # c.use_jedi = True
439 439 # completions = set(c.completions('ip.', 3))
440 440 # nt.assert_not_in(Completion(3,3,'__str__'), completions)
441 441 # nt.assert_in(Completion(3,3, "_hidden_attr"), completions)
442 442
443 443 cfg = Config()
444 444 cfg.IPCompleter.omit__names = 2
445 445 c.update_config(cfg)
446 446 with provisionalcompleter():
447 447 c.use_jedi = False
448 448 s,matches = c.complete('ip.')
449 449 nt.assert_not_in('ip.__str__', matches)
450 450 nt.assert_not_in('ip._hidden_attr', matches)
451 451
452 452 # c.use_jedi = True
453 453 # completions = set(c.completions('ip.', 3))
454 454 # nt.assert_not_in(Completion(3,3,'__str__'), completions)
455 455 # nt.assert_not_in(Completion(3,3, "_hidden_attr"), completions)
456 456
457 457 with provisionalcompleter():
458 458 c.use_jedi = False
459 459 s,matches = c.complete('ip._x.')
460 460 nt.assert_in('ip._x.keys', matches)
461 461
462 462 # c.use_jedi = True
463 463 # completions = set(c.completions('ip._x.', 6))
464 464 # nt.assert_in(Completion(6,6, "keys"), completions)
465 465
466 466 del ip._hidden_attr
467 467 del ip._x
468 468
469 469
470 470 def test_limit_to__all__False_ok():
471 471 """
472 472 Limit to all is deprecated, once we remove it this test can go away.
473 473 """
474 474 ip = get_ipython()
475 475 c = ip.Completer
476 476 c.use_jedi = False
477 477 ip.ex('class D: x=24')
478 478 ip.ex('d=D()')
479 479 cfg = Config()
480 480 cfg.IPCompleter.limit_to__all__ = False
481 481 c.update_config(cfg)
482 482 s, matches = c.complete('d.')
483 483 nt.assert_in('d.x', matches)
484 484
485 485
486 486 def test_get__all__entries_ok():
487 487 class A(object):
488 488 __all__ = ['x', 1]
489 489 words = completer.get__all__entries(A())
490 490 nt.assert_equal(words, ['x'])
491 491
492 492
493 493 def test_get__all__entries_no__all__ok():
494 494 class A(object):
495 495 pass
496 496 words = completer.get__all__entries(A())
497 497 nt.assert_equal(words, [])
498 498
499 499
500 500 def test_func_kw_completions():
501 501 ip = get_ipython()
502 502 c = ip.Completer
503 503 c.use_jedi = False
504 504 ip.ex('def myfunc(a=1,b=2): return a+b')
505 505 s, matches = c.complete(None, 'myfunc(1,b')
506 506 nt.assert_in('b=', matches)
507 507 # Simulate completing with cursor right after b (pos==10):
508 508 s, matches = c.complete(None, 'myfunc(1,b)', 10)
509 509 nt.assert_in('b=', matches)
510 510 s, matches = c.complete(None, 'myfunc(a="escaped\\")string",b')
511 511 nt.assert_in('b=', matches)
512 512 #builtin function
513 513 s, matches = c.complete(None, 'min(k, k')
514 514 nt.assert_in('key=', matches)
515 515
516 516
517 517 def test_default_arguments_from_docstring():
518 518 ip = get_ipython()
519 519 c = ip.Completer
520 520 kwd = c._default_arguments_from_docstring(
521 521 'min(iterable[, key=func]) -> value')
522 522 nt.assert_equal(kwd, ['key'])
523 523 #with cython type etc
524 524 kwd = c._default_arguments_from_docstring(
525 525 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
526 526 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
527 527 #white spaces
528 528 kwd = c._default_arguments_from_docstring(
529 529 '\n Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
530 530 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
531 531
532 532 def test_line_magics():
533 533 ip = get_ipython()
534 534 c = ip.Completer
535 535 s, matches = c.complete(None, 'lsmag')
536 536 nt.assert_in('%lsmagic', matches)
537 537 s, matches = c.complete(None, '%lsmag')
538 538 nt.assert_in('%lsmagic', matches)
539 539
540 540
541 541 def test_cell_magics():
542 542 from IPython.core.magic import register_cell_magic
543 543
544 544 @register_cell_magic
545 545 def _foo_cellm(line, cell):
546 546 pass
547 547
548 548 ip = get_ipython()
549 549 c = ip.Completer
550 550
551 551 s, matches = c.complete(None, '_foo_ce')
552 552 nt.assert_in('%%_foo_cellm', matches)
553 553 s, matches = c.complete(None, '%%_foo_ce')
554 554 nt.assert_in('%%_foo_cellm', matches)
555 555
556 556
557 557 def test_line_cell_magics():
558 558 from IPython.core.magic import register_line_cell_magic
559 559
560 560 @register_line_cell_magic
561 561 def _bar_cellm(line, cell):
562 562 pass
563 563
564 564 ip = get_ipython()
565 565 c = ip.Completer
566 566
567 567 # The policy here is trickier, see comments in completion code. The
568 568 # returned values depend on whether the user passes %% or not explicitly,
569 569 # and this will show a difference if the same name is both a line and cell
570 570 # magic.
571 571 s, matches = c.complete(None, '_bar_ce')
572 572 nt.assert_in('%_bar_cellm', matches)
573 573 nt.assert_in('%%_bar_cellm', matches)
574 574 s, matches = c.complete(None, '%_bar_ce')
575 575 nt.assert_in('%_bar_cellm', matches)
576 576 nt.assert_in('%%_bar_cellm', matches)
577 577 s, matches = c.complete(None, '%%_bar_ce')
578 578 nt.assert_not_in('%_bar_cellm', matches)
579 579 nt.assert_in('%%_bar_cellm', matches)
580 580
581 581
582 582 def test_magic_completion_order():
583 583 ip = get_ipython()
584 584 c = ip.Completer
585 585
586 586 # Test ordering of line and cell magics.
587 587 text, matches = c.complete("timeit")
588 588 nt.assert_equal(matches, ["%timeit", "%%timeit"])
589 589
590 590
591 591 def test_magic_completion_shadowing():
592 592 ip = get_ipython()
593 593 c = ip.Completer
594 594 c.use_jedi = False
595 595
596 596 # Before importing matplotlib, %matplotlib magic should be the only option.
597 597 text, matches = c.complete("mat")
598 598 nt.assert_equal(matches, ["%matplotlib"])
599 599
600 600 # The newly introduced name should shadow the magic.
601 601 ip.run_cell("matplotlib = 1")
602 602 text, matches = c.complete("mat")
603 603 nt.assert_equal(matches, ["matplotlib"])
604 604
605 605 # After removing matplotlib from namespace, the magic should again be
606 606 # the only option.
607 607 del ip.user_ns["matplotlib"]
608 608 text, matches = c.complete("mat")
609 609 nt.assert_equal(matches, ["%matplotlib"])
610 610
611 611 def test_magic_completion_shadowing_explicit():
612 612 """
613 613 If the user try to complete a shadowed magic, and explicit % start should
614 614 still return the completions.
615 615 """
616 616 ip = get_ipython()
617 617 c = ip.Completer
618 618
619 619 # Before importing matplotlib, %matplotlib magic should be the only option.
620 620 text, matches = c.complete("%mat")
621 621 nt.assert_equal(matches, ["%matplotlib"])
622 622
623 623 ip.run_cell("matplotlib = 1")
624 624
625 625 # After removing matplotlib from namespace, the magic should still be
626 626 # the only option.
627 627 text, matches = c.complete("%mat")
628 628 nt.assert_equal(matches, ["%matplotlib"])
629 629
630 630 def test_magic_config():
631 631 ip = get_ipython()
632 632 c = ip.Completer
633 633
634 634 s, matches = c.complete(None, 'conf')
635 635 nt.assert_in('%config', matches)
636 636 s, matches = c.complete(None, 'conf')
637 637 nt.assert_not_in('AliasManager', matches)
638 638 s, matches = c.complete(None, 'config ')
639 639 nt.assert_in('AliasManager', matches)
640 640 s, matches = c.complete(None, '%config ')
641 641 nt.assert_in('AliasManager', matches)
642 642 s, matches = c.complete(None, 'config Ali')
643 643 nt.assert_list_equal(['AliasManager'], matches)
644 644 s, matches = c.complete(None, '%config Ali')
645 645 nt.assert_list_equal(['AliasManager'], matches)
646 646 s, matches = c.complete(None, 'config AliasManager')
647 647 nt.assert_list_equal(['AliasManager'], matches)
648 648 s, matches = c.complete(None, '%config AliasManager')
649 649 nt.assert_list_equal(['AliasManager'], matches)
650 650 s, matches = c.complete(None, 'config AliasManager.')
651 651 nt.assert_in('AliasManager.default_aliases', matches)
652 652 s, matches = c.complete(None, '%config AliasManager.')
653 653 nt.assert_in('AliasManager.default_aliases', matches)
654 654 s, matches = c.complete(None, 'config AliasManager.de')
655 655 nt.assert_list_equal(['AliasManager.default_aliases'], matches)
656 656 s, matches = c.complete(None, 'config AliasManager.de')
657 657 nt.assert_list_equal(['AliasManager.default_aliases'], matches)
658 658
659 659
660 660 def test_magic_color():
661 661 ip = get_ipython()
662 662 c = ip.Completer
663 663
664 664 s, matches = c.complete(None, 'colo')
665 665 nt.assert_in('%colors', matches)
666 666 s, matches = c.complete(None, 'colo')
667 667 nt.assert_not_in('NoColor', matches)
668 668 s, matches = c.complete(None, '%colors') # No trailing space
669 669 nt.assert_not_in('NoColor', matches)
670 670 s, matches = c.complete(None, 'colors ')
671 671 nt.assert_in('NoColor', matches)
672 672 s, matches = c.complete(None, '%colors ')
673 673 nt.assert_in('NoColor', matches)
674 674 s, matches = c.complete(None, 'colors NoCo')
675 675 nt.assert_list_equal(['NoColor'], matches)
676 676 s, matches = c.complete(None, '%colors NoCo')
677 677 nt.assert_list_equal(['NoColor'], matches)
678 678
679 679
680 680 def test_match_dict_keys():
681 681 """
682 682 Test that match_dict_keys works on a couple of use case does return what
683 683 expected, and does not crash
684 684 """
685 685 delims = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
686 686
687 687
688 688 keys = ['foo', b'far']
689 689 assert match_dict_keys(keys, "b'", delims=delims) == ("'", 2 ,['far'])
690 690 assert match_dict_keys(keys, "b'f", delims=delims) == ("'", 2 ,['far'])
691 691 assert match_dict_keys(keys, 'b"', delims=delims) == ('"', 2 ,['far'])
692 692 assert match_dict_keys(keys, 'b"f', delims=delims) == ('"', 2 ,['far'])
693 693
694 694 assert match_dict_keys(keys, "'", delims=delims) == ("'", 1 ,['foo'])
695 695 assert match_dict_keys(keys, "'f", delims=delims) == ("'", 1 ,['foo'])
696 696 assert match_dict_keys(keys, '"', delims=delims) == ('"', 1 ,['foo'])
697 697 assert match_dict_keys(keys, '"f', delims=delims) == ('"', 1 ,['foo'])
698 698
699 699 match_dict_keys
700 700
701 701
702 702 def test_dict_key_completion_string():
703 703 """Test dictionary key completion for string keys"""
704 704 ip = get_ipython()
705 705 complete = ip.Completer.complete
706 706
707 707 ip.user_ns['d'] = {'abc': None}
708 708
709 709 # check completion at different stages
710 710 _, matches = complete(line_buffer="d[")
711 711 nt.assert_in("'abc'", matches)
712 712 nt.assert_not_in("'abc']", matches)
713 713
714 714 _, matches = complete(line_buffer="d['")
715 715 nt.assert_in("abc", matches)
716 716 nt.assert_not_in("abc']", matches)
717 717
718 718 _, matches = complete(line_buffer="d['a")
719 719 nt.assert_in("abc", matches)
720 720 nt.assert_not_in("abc']", matches)
721 721
722 722 # check use of different quoting
723 723 _, matches = complete(line_buffer="d[\"")
724 724 nt.assert_in("abc", matches)
725 725 nt.assert_not_in('abc\"]', matches)
726 726
727 727 _, matches = complete(line_buffer="d[\"a")
728 728 nt.assert_in("abc", matches)
729 729 nt.assert_not_in('abc\"]', matches)
730 730
731 731 # check sensitivity to following context
732 732 _, matches = complete(line_buffer="d[]", cursor_pos=2)
733 733 nt.assert_in("'abc'", matches)
734 734
735 735 _, matches = complete(line_buffer="d['']", cursor_pos=3)
736 736 nt.assert_in("abc", matches)
737 737 nt.assert_not_in("abc'", matches)
738 738 nt.assert_not_in("abc']", matches)
739 739
740 740 # check multiple solutions are correctly returned and that noise is not
741 741 ip.user_ns['d'] = {'abc': None, 'abd': None, 'bad': None, object(): None,
742 742 5: None}
743 743
744 744 _, matches = complete(line_buffer="d['a")
745 745 nt.assert_in("abc", matches)
746 746 nt.assert_in("abd", matches)
747 747 nt.assert_not_in("bad", matches)
748 748 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
749 749
750 750 # check escaping and whitespace
751 751 ip.user_ns['d'] = {'a\nb': None, 'a\'b': None, 'a"b': None, 'a word': None}
752 752 _, matches = complete(line_buffer="d['a")
753 753 nt.assert_in("a\\nb", matches)
754 754 nt.assert_in("a\\'b", matches)
755 755 nt.assert_in("a\"b", matches)
756 756 nt.assert_in("a word", matches)
757 757 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
758 758
759 759 # - can complete on non-initial word of the string
760 760 _, matches = complete(line_buffer="d['a w")
761 761 nt.assert_in("word", matches)
762 762
763 763 # - understands quote escaping
764 764 _, matches = complete(line_buffer="d['a\\'")
765 765 nt.assert_in("b", matches)
766 766
767 767 # - default quoting should work like repr
768 768 _, matches = complete(line_buffer="d[")
769 769 nt.assert_in("\"a'b\"", matches)
770 770
771 771 # - when opening quote with ", possible to match with unescaped apostrophe
772 772 _, matches = complete(line_buffer="d[\"a'")
773 773 nt.assert_in("b", matches)
774 774
775 775 # need to not split at delims that readline won't split at
776 776 if '-' not in ip.Completer.splitter.delims:
777 777 ip.user_ns['d'] = {'before-after': None}
778 778 _, matches = complete(line_buffer="d['before-af")
779 779 nt.assert_in('before-after', matches)
780 780
781 781 def test_dict_key_completion_contexts():
782 782 """Test expression contexts in which dict key completion occurs"""
783 783 ip = get_ipython()
784 784 complete = ip.Completer.complete
785 785 d = {'abc': None}
786 786 ip.user_ns['d'] = d
787 787
788 788 class C:
789 789 data = d
790 790 ip.user_ns['C'] = C
791 791 ip.user_ns['get'] = lambda: d
792 792
793 793 def assert_no_completion(**kwargs):
794 794 _, matches = complete(**kwargs)
795 795 nt.assert_not_in('abc', matches)
796 796 nt.assert_not_in('abc\'', matches)
797 797 nt.assert_not_in('abc\']', matches)
798 798 nt.assert_not_in('\'abc\'', matches)
799 799 nt.assert_not_in('\'abc\']', matches)
800 800
801 801 def assert_completion(**kwargs):
802 802 _, matches = complete(**kwargs)
803 803 nt.assert_in("'abc'", matches)
804 804 nt.assert_not_in("'abc']", matches)
805 805
806 806 # no completion after string closed, even if reopened
807 807 assert_no_completion(line_buffer="d['a'")
808 808 assert_no_completion(line_buffer="d[\"a\"")
809 809 assert_no_completion(line_buffer="d['a' + ")
810 810 assert_no_completion(line_buffer="d['a' + '")
811 811
812 812 # completion in non-trivial expressions
813 813 assert_completion(line_buffer="+ d[")
814 814 assert_completion(line_buffer="(d[")
815 815 assert_completion(line_buffer="C.data[")
816 816
817 817 # greedy flag
818 818 def assert_completion(**kwargs):
819 819 _, matches = complete(**kwargs)
820 820 nt.assert_in("get()['abc']", matches)
821 821
822 822 assert_no_completion(line_buffer="get()[")
823 823 with greedy_completion():
824 824 assert_completion(line_buffer="get()[")
825 825 assert_completion(line_buffer="get()['")
826 826 assert_completion(line_buffer="get()['a")
827 827 assert_completion(line_buffer="get()['ab")
828 828 assert_completion(line_buffer="get()['abc")
829 829
830 830
831 831
832 832 def test_dict_key_completion_bytes():
833 833 """Test handling of bytes in dict key completion"""
834 834 ip = get_ipython()
835 835 complete = ip.Completer.complete
836 836
837 837 ip.user_ns['d'] = {'abc': None, b'abd': None}
838 838
839 839 _, matches = complete(line_buffer="d[")
840 840 nt.assert_in("'abc'", matches)
841 841 nt.assert_in("b'abd'", matches)
842 842
843 843 if False: # not currently implemented
844 844 _, matches = complete(line_buffer="d[b")
845 845 nt.assert_in("b'abd'", matches)
846 846 nt.assert_not_in("b'abc'", matches)
847 847
848 848 _, matches = complete(line_buffer="d[b'")
849 849 nt.assert_in("abd", matches)
850 850 nt.assert_not_in("abc", matches)
851 851
852 852 _, matches = complete(line_buffer="d[B'")
853 853 nt.assert_in("abd", matches)
854 854 nt.assert_not_in("abc", matches)
855 855
856 856 _, matches = complete(line_buffer="d['")
857 857 nt.assert_in("abc", matches)
858 858 nt.assert_not_in("abd", matches)
859 859
860 860
861 861 def test_dict_key_completion_unicode_py3():
862 862 """Test handling of unicode in dict key completion"""
863 863 ip = get_ipython()
864 864 complete = ip.Completer.complete
865 865
866 866 ip.user_ns['d'] = {u'a\u05d0': None}
867 867
868 868 # query using escape
869 869 if sys.platform != 'win32':
870 870 # Known failure on Windows
871 871 _, matches = complete(line_buffer="d['a\\u05d0")
872 872 nt.assert_in("u05d0", matches) # tokenized after \\
873 873
874 874 # query using character
875 875 _, matches = complete(line_buffer="d['a\u05d0")
876 876 nt.assert_in(u"a\u05d0", matches)
877 877
878 878 with greedy_completion():
879 879 # query using escape
880 880 _, matches = complete(line_buffer="d['a\\u05d0")
881 881 nt.assert_in("d['a\\u05d0']", matches) # tokenized after \\
882 882
883 883 # query using character
884 884 _, matches = complete(line_buffer="d['a\u05d0")
885 885 nt.assert_in(u"d['a\u05d0']", matches)
886 886
887 887
888 888
889 889 @dec.skip_without('numpy')
890 890 def test_struct_array_key_completion():
891 891 """Test dict key completion applies to numpy struct arrays"""
892 892 import numpy
893 893 ip = get_ipython()
894 894 complete = ip.Completer.complete
895 895 ip.user_ns['d'] = numpy.array([], dtype=[('hello', 'f'), ('world', 'f')])
896 896 _, matches = complete(line_buffer="d['")
897 897 nt.assert_in("hello", matches)
898 898 nt.assert_in("world", matches)
899 899 # complete on the numpy struct itself
900 900 dt = numpy.dtype([('my_head', [('my_dt', '>u4'), ('my_df', '>u4')]),
901 901 ('my_data', '>f4', 5)])
902 902 x = numpy.zeros(2, dtype=dt)
903 903 ip.user_ns['d'] = x[1]
904 904 _, matches = complete(line_buffer="d['")
905 905 nt.assert_in("my_head", matches)
906 906 nt.assert_in("my_data", matches)
907 907 # complete on a nested level
908 908 with greedy_completion():
909 909 ip.user_ns['d'] = numpy.zeros(2, dtype=dt)
910 910 _, matches = complete(line_buffer="d[1]['my_head']['")
911 911 nt.assert_true(any(["my_dt" in m for m in matches]))
912 912 nt.assert_true(any(["my_df" in m for m in matches]))
913 913
914 914
915 915 @dec.skip_without('pandas')
916 916 def test_dataframe_key_completion():
917 917 """Test dict key completion applies to pandas DataFrames"""
918 918 import pandas
919 919 ip = get_ipython()
920 920 complete = ip.Completer.complete
921 921 ip.user_ns['d'] = pandas.DataFrame({'hello': [1], 'world': [2]})
922 922 _, matches = complete(line_buffer="d['")
923 923 nt.assert_in("hello", matches)
924 924 nt.assert_in("world", matches)
925 925
926 926
927 927 def test_dict_key_completion_invalids():
928 928 """Smoke test cases dict key completion can't handle"""
929 929 ip = get_ipython()
930 930 complete = ip.Completer.complete
931 931
932 932 ip.user_ns['no_getitem'] = None
933 933 ip.user_ns['no_keys'] = []
934 934 ip.user_ns['cant_call_keys'] = dict
935 935 ip.user_ns['empty'] = {}
936 936 ip.user_ns['d'] = {'abc': 5}
937 937
938 938 _, matches = complete(line_buffer="no_getitem['")
939 939 _, matches = complete(line_buffer="no_keys['")
940 940 _, matches = complete(line_buffer="cant_call_keys['")
941 941 _, matches = complete(line_buffer="empty['")
942 942 _, matches = complete(line_buffer="name_error['")
943 943 _, matches = complete(line_buffer="d['\\") # incomplete escape
944 944
945 945 class KeyCompletable(object):
946 946 def __init__(self, things=()):
947 947 self.things = things
948 948
949 949 def _ipython_key_completions_(self):
950 950 return list(self.things)
951 951
952 952 def test_object_key_completion():
953 953 ip = get_ipython()
954 954 ip.user_ns['key_completable'] = KeyCompletable(['qwerty', 'qwick'])
955 955
956 956 _, matches = ip.Completer.complete(line_buffer="key_completable['qw")
957 957 nt.assert_in('qwerty', matches)
958 958 nt.assert_in('qwick', matches)
959 959
960 960
961 961 class NamedInstanceMetaclass(type):
962 962 def __getitem__(cls, item):
963 963 return cls.get_instance(item)
964 964
965 965 class NamedInstanceClass(object, metaclass=NamedInstanceMetaclass):
966 966 def __init__(self, name):
967 967 if not hasattr(self.__class__, 'instances'):
968 968 self.__class__.instances = {}
969 969 self.__class__.instances[name] = self
970 970
971 971 @classmethod
972 972 def _ipython_key_completions_(cls):
973 973 return cls.instances.keys()
974 974
975 975 @classmethod
976 976 def get_instance(cls, name):
977 977 return cls.instances[name]
978 978
979 979 def test_class_key_completion():
980 980 ip = get_ipython()
981 981 NamedInstanceClass('qwerty')
982 982 NamedInstanceClass('qwick')
983 983 ip.user_ns['named_instance_class'] = NamedInstanceClass
984 984
985 985 _, matches = ip.Completer.complete(line_buffer="named_instance_class['qw")
986 986 nt.assert_in('qwerty', matches)
987 987 nt.assert_in('qwick', matches)
988 988
989 989 def test_tryimport():
990 990 """
991 991 Test that try-import don't crash on trailing dot, and import modules before
992 992 """
993 993 from IPython.core.completerlib import try_import
994 994 assert(try_import("IPython."))
995 995
996 996
997 997 def test_aimport_module_completer():
998 998 ip = get_ipython()
999 999 _, matches = ip.complete('i', '%aimport i')
1000 1000 nt.assert_in('io', matches)
1001 1001 nt.assert_not_in('int', matches)
1002 1002
1003 1003 def test_nested_import_module_completer():
1004 1004 ip = get_ipython()
1005 1005 _, matches = ip.complete(None, 'import IPython.co', 17)
1006 1006 nt.assert_in('IPython.core', matches)
1007 1007 nt.assert_not_in('import IPython.core', matches)
1008 1008 nt.assert_not_in('IPython.display', matches)
1009 1009
1010 1010 def test_import_module_completer():
1011 1011 ip = get_ipython()
1012 1012 _, matches = ip.complete('i', 'import i')
1013 1013 nt.assert_in('io', matches)
1014 1014 nt.assert_not_in('int', matches)
1015 1015
1016 1016 def test_from_module_completer():
1017 1017 ip = get_ipython()
1018 1018 _, matches = ip.complete('B', 'from io import B', 16)
1019 1019 nt.assert_in('BytesIO', matches)
1020 1020 nt.assert_not_in('BaseException', matches)
1021 1021
1022 1022 def test_snake_case_completion():
1023 1023 ip = get_ipython()
1024 1024 ip.Completer.use_jedi = False
1025 1025 ip.user_ns['some_three'] = 3
1026 1026 ip.user_ns['some_four'] = 4
1027 1027 _, matches = ip.complete("s_", "print(s_f")
1028 1028 nt.assert_in('some_three', matches)
1029 1029 nt.assert_in('some_four', matches)
@@ -1,5 +1,5 b''
1 1 """
2 2 This package contains all third-party modules bundled with IPython.
3 3 """
4 4
5 __all__ = ["simplegeneric"]
5 __all__ = []
@@ -1,34 +1,30 b''
1 1 # encoding: utf-8
2 2 """Generic functions for extending IPython.
3
4 See http://pypi.python.org/pypi/simplegeneric.
5 3 """
6 4
7 5 from IPython.core.error import TryNext
8 from simplegeneric import generic
6 from functools import singledispatch
9 7
10 8
11 @generic
9 @singledispatch
12 10 def inspect_object(obj):
13 11 """Called when you do obj?"""
14 12 raise TryNext
15 13
16 14
17 @generic
15 @singledispatch
18 16 def complete_object(obj, prev_completions):
19 17 """Custom completer dispatching for python objects.
20 18
21 19 Parameters
22 20 ----------
23 21 obj : object
24 22 The object to complete.
25 23 prev_completions : list
26 24 List of attributes discovered so far.
27 25
28 26 This should return the list of attributes in obj. If you only wish to
29 27 add to the attributes already discovered normally, return
30 28 own_attrs + prev_completions.
31 29 """
32 30 raise TryNext
33
34
@@ -1,772 +1,772 b''
1 1 # encoding: utf-8
2 2 """
3 3 Utilities for working with strings and text.
4 4
5 5 Inheritance diagram:
6 6
7 7 .. inheritance-diagram:: IPython.utils.text
8 8 :parts: 3
9 9 """
10 10
11 11 import os
12 12 import re
13 13 import sys
14 14 import textwrap
15 15 from string import Formatter
16 16 from pathlib import Path
17 17
18 18 from IPython.utils import py3compat
19 19
20 20 # datetime.strftime date format for ipython
21 21 if sys.platform == 'win32':
22 22 date_format = "%B %d, %Y"
23 23 else:
24 24 date_format = "%B %-d, %Y"
25 25
26 26 class LSString(str):
27 27 """String derivative with a special access attributes.
28 28
29 29 These are normal strings, but with the special attributes:
30 30
31 31 .l (or .list) : value as list (split on newlines).
32 32 .n (or .nlstr): original value (the string itself).
33 33 .s (or .spstr): value as whitespace-separated string.
34 34 .p (or .paths): list of path objects (requires path.py package)
35 35
36 36 Any values which require transformations are computed only once and
37 37 cached.
38 38
39 39 Such strings are very useful to efficiently interact with the shell, which
40 40 typically only understands whitespace-separated options for commands."""
41 41
42 42 def get_list(self):
43 43 try:
44 44 return self.__list
45 45 except AttributeError:
46 46 self.__list = self.split('\n')
47 47 return self.__list
48 48
49 49 l = list = property(get_list)
50 50
51 51 def get_spstr(self):
52 52 try:
53 53 return self.__spstr
54 54 except AttributeError:
55 55 self.__spstr = self.replace('\n',' ')
56 56 return self.__spstr
57 57
58 58 s = spstr = property(get_spstr)
59 59
60 60 def get_nlstr(self):
61 61 return self
62 62
63 63 n = nlstr = property(get_nlstr)
64 64
65 65 def get_paths(self):
66 66 try:
67 67 return self.__paths
68 68 except AttributeError:
69 69 self.__paths = [Path(p) for p in self.split('\n') if os.path.exists(p)]
70 70 return self.__paths
71 71
72 72 p = paths = property(get_paths)
73 73
74 74 # FIXME: We need to reimplement type specific displayhook and then add this
75 75 # back as a custom printer. This should also be moved outside utils into the
76 76 # core.
77 77
78 78 # def print_lsstring(arg):
79 79 # """ Prettier (non-repr-like) and more informative printer for LSString """
80 80 # print "LSString (.p, .n, .l, .s available). Value:"
81 81 # print arg
82 82 #
83 83 #
84 # print_lsstring = result_display.when_type(LSString)(print_lsstring)
84 # print_lsstring = result_display.register(LSString)(print_lsstring)
85 85
86 86
87 87 class SList(list):
88 88 """List derivative with a special access attributes.
89 89
90 90 These are normal lists, but with the special attributes:
91 91
92 92 * .l (or .list) : value as list (the list itself).
93 93 * .n (or .nlstr): value as a string, joined on newlines.
94 94 * .s (or .spstr): value as a string, joined on spaces.
95 95 * .p (or .paths): list of path objects (requires path.py package)
96 96
97 97 Any values which require transformations are computed only once and
98 98 cached."""
99 99
100 100 def get_list(self):
101 101 return self
102 102
103 103 l = list = property(get_list)
104 104
105 105 def get_spstr(self):
106 106 try:
107 107 return self.__spstr
108 108 except AttributeError:
109 109 self.__spstr = ' '.join(self)
110 110 return self.__spstr
111 111
112 112 s = spstr = property(get_spstr)
113 113
114 114 def get_nlstr(self):
115 115 try:
116 116 return self.__nlstr
117 117 except AttributeError:
118 118 self.__nlstr = '\n'.join(self)
119 119 return self.__nlstr
120 120
121 121 n = nlstr = property(get_nlstr)
122 122
123 123 def get_paths(self):
124 124 try:
125 125 return self.__paths
126 126 except AttributeError:
127 127 self.__paths = [Path(p) for p in self if os.path.exists(p)]
128 128 return self.__paths
129 129
130 130 p = paths = property(get_paths)
131 131
132 132 def grep(self, pattern, prune = False, field = None):
133 133 """ Return all strings matching 'pattern' (a regex or callable)
134 134
135 135 This is case-insensitive. If prune is true, return all items
136 136 NOT matching the pattern.
137 137
138 138 If field is specified, the match must occur in the specified
139 139 whitespace-separated field.
140 140
141 141 Examples::
142 142
143 143 a.grep( lambda x: x.startswith('C') )
144 144 a.grep('Cha.*log', prune=1)
145 145 a.grep('chm', field=-1)
146 146 """
147 147
148 148 def match_target(s):
149 149 if field is None:
150 150 return s
151 151 parts = s.split()
152 152 try:
153 153 tgt = parts[field]
154 154 return tgt
155 155 except IndexError:
156 156 return ""
157 157
158 158 if isinstance(pattern, str):
159 159 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
160 160 else:
161 161 pred = pattern
162 162 if not prune:
163 163 return SList([el for el in self if pred(match_target(el))])
164 164 else:
165 165 return SList([el for el in self if not pred(match_target(el))])
166 166
167 167 def fields(self, *fields):
168 168 """ Collect whitespace-separated fields from string list
169 169
170 170 Allows quick awk-like usage of string lists.
171 171
172 172 Example data (in var a, created by 'a = !ls -l')::
173 173
174 174 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
175 175 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
176 176
177 177 * ``a.fields(0)`` is ``['-rwxrwxrwx', 'drwxrwxrwx+']``
178 178 * ``a.fields(1,0)`` is ``['1 -rwxrwxrwx', '6 drwxrwxrwx+']``
179 179 (note the joining by space).
180 180 * ``a.fields(-1)`` is ``['ChangeLog', 'IPython']``
181 181
182 182 IndexErrors are ignored.
183 183
184 184 Without args, fields() just split()'s the strings.
185 185 """
186 186 if len(fields) == 0:
187 187 return [el.split() for el in self]
188 188
189 189 res = SList()
190 190 for el in [f.split() for f in self]:
191 191 lineparts = []
192 192
193 193 for fd in fields:
194 194 try:
195 195 lineparts.append(el[fd])
196 196 except IndexError:
197 197 pass
198 198 if lineparts:
199 199 res.append(" ".join(lineparts))
200 200
201 201 return res
202 202
203 203 def sort(self,field= None, nums = False):
204 204 """ sort by specified fields (see fields())
205 205
206 206 Example::
207 207
208 208 a.sort(1, nums = True)
209 209
210 210 Sorts a by second field, in numerical order (so that 21 > 3)
211 211
212 212 """
213 213
214 214 #decorate, sort, undecorate
215 215 if field is not None:
216 216 dsu = [[SList([line]).fields(field), line] for line in self]
217 217 else:
218 218 dsu = [[line, line] for line in self]
219 219 if nums:
220 220 for i in range(len(dsu)):
221 221 numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
222 222 try:
223 223 n = int(numstr)
224 224 except ValueError:
225 225 n = 0
226 226 dsu[i][0] = n
227 227
228 228
229 229 dsu.sort()
230 230 return SList([t[1] for t in dsu])
231 231
232 232
233 233 # FIXME: We need to reimplement type specific displayhook and then add this
234 234 # back as a custom printer. This should also be moved outside utils into the
235 235 # core.
236 236
237 237 # def print_slist(arg):
238 238 # """ Prettier (non-repr-like) and more informative printer for SList """
239 239 # print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
240 240 # if hasattr(arg, 'hideonce') and arg.hideonce:
241 241 # arg.hideonce = False
242 242 # return
243 243 #
244 244 # nlprint(arg) # This was a nested list printer, now removed.
245 245 #
246 # print_slist = result_display.when_type(SList)(print_slist)
246 # print_slist = result_display.register(SList)(print_slist)
247 247
248 248
249 249 def indent(instr,nspaces=4, ntabs=0, flatten=False):
250 250 """Indent a string a given number of spaces or tabstops.
251 251
252 252 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
253 253
254 254 Parameters
255 255 ----------
256 256
257 257 instr : basestring
258 258 The string to be indented.
259 259 nspaces : int (default: 4)
260 260 The number of spaces to be indented.
261 261 ntabs : int (default: 0)
262 262 The number of tabs to be indented.
263 263 flatten : bool (default: False)
264 264 Whether to scrub existing indentation. If True, all lines will be
265 265 aligned to the same indentation. If False, existing indentation will
266 266 be strictly increased.
267 267
268 268 Returns
269 269 -------
270 270
271 271 str|unicode : string indented by ntabs and nspaces.
272 272
273 273 """
274 274 if instr is None:
275 275 return
276 276 ind = '\t'*ntabs+' '*nspaces
277 277 if flatten:
278 278 pat = re.compile(r'^\s*', re.MULTILINE)
279 279 else:
280 280 pat = re.compile(r'^', re.MULTILINE)
281 281 outstr = re.sub(pat, ind, instr)
282 282 if outstr.endswith(os.linesep+ind):
283 283 return outstr[:-len(ind)]
284 284 else:
285 285 return outstr
286 286
287 287
288 288 def list_strings(arg):
289 289 """Always return a list of strings, given a string or list of strings
290 290 as input.
291 291
292 292 Examples
293 293 --------
294 294 ::
295 295
296 296 In [7]: list_strings('A single string')
297 297 Out[7]: ['A single string']
298 298
299 299 In [8]: list_strings(['A single string in a list'])
300 300 Out[8]: ['A single string in a list']
301 301
302 302 In [9]: list_strings(['A','list','of','strings'])
303 303 Out[9]: ['A', 'list', 'of', 'strings']
304 304 """
305 305
306 306 if isinstance(arg, str):
307 307 return [arg]
308 308 else:
309 309 return arg
310 310
311 311
312 312 def marquee(txt='',width=78,mark='*'):
313 313 """Return the input string centered in a 'marquee'.
314 314
315 315 Examples
316 316 --------
317 317 ::
318 318
319 319 In [16]: marquee('A test',40)
320 320 Out[16]: '**************** A test ****************'
321 321
322 322 In [17]: marquee('A test',40,'-')
323 323 Out[17]: '---------------- A test ----------------'
324 324
325 325 In [18]: marquee('A test',40,' ')
326 326 Out[18]: ' A test '
327 327
328 328 """
329 329 if not txt:
330 330 return (mark*width)[:width]
331 331 nmark = (width-len(txt)-2)//len(mark)//2
332 332 if nmark < 0: nmark =0
333 333 marks = mark*nmark
334 334 return '%s %s %s' % (marks,txt,marks)
335 335
336 336
337 337 ini_spaces_re = re.compile(r'^(\s+)')
338 338
339 339 def num_ini_spaces(strng):
340 340 """Return the number of initial spaces in a string"""
341 341
342 342 ini_spaces = ini_spaces_re.match(strng)
343 343 if ini_spaces:
344 344 return ini_spaces.end()
345 345 else:
346 346 return 0
347 347
348 348
349 349 def format_screen(strng):
350 350 """Format a string for screen printing.
351 351
352 352 This removes some latex-type format codes."""
353 353 # Paragraph continue
354 354 par_re = re.compile(r'\\$',re.MULTILINE)
355 355 strng = par_re.sub('',strng)
356 356 return strng
357 357
358 358
359 359 def dedent(text):
360 360 """Equivalent of textwrap.dedent that ignores unindented first line.
361 361
362 362 This means it will still dedent strings like:
363 363 '''foo
364 364 is a bar
365 365 '''
366 366
367 367 For use in wrap_paragraphs.
368 368 """
369 369
370 370 if text.startswith('\n'):
371 371 # text starts with blank line, don't ignore the first line
372 372 return textwrap.dedent(text)
373 373
374 374 # split first line
375 375 splits = text.split('\n',1)
376 376 if len(splits) == 1:
377 377 # only one line
378 378 return textwrap.dedent(text)
379 379
380 380 first, rest = splits
381 381 # dedent everything but the first line
382 382 rest = textwrap.dedent(rest)
383 383 return '\n'.join([first, rest])
384 384
385 385
386 386 def wrap_paragraphs(text, ncols=80):
387 387 """Wrap multiple paragraphs to fit a specified width.
388 388
389 389 This is equivalent to textwrap.wrap, but with support for multiple
390 390 paragraphs, as separated by empty lines.
391 391
392 392 Returns
393 393 -------
394 394
395 395 list of complete paragraphs, wrapped to fill `ncols` columns.
396 396 """
397 397 paragraph_re = re.compile(r'\n(\s*\n)+', re.MULTILINE)
398 398 text = dedent(text).strip()
399 399 paragraphs = paragraph_re.split(text)[::2] # every other entry is space
400 400 out_ps = []
401 401 indent_re = re.compile(r'\n\s+', re.MULTILINE)
402 402 for p in paragraphs:
403 403 # presume indentation that survives dedent is meaningful formatting,
404 404 # so don't fill unless text is flush.
405 405 if indent_re.search(p) is None:
406 406 # wrap paragraph
407 407 p = textwrap.fill(p, ncols)
408 408 out_ps.append(p)
409 409 return out_ps
410 410
411 411
412 412 def long_substr(data):
413 413 """Return the longest common substring in a list of strings.
414 414
415 415 Credit: http://stackoverflow.com/questions/2892931/longest-common-substring-from-more-than-two-strings-python
416 416 """
417 417 substr = ''
418 418 if len(data) > 1 and len(data[0]) > 0:
419 419 for i in range(len(data[0])):
420 420 for j in range(len(data[0])-i+1):
421 421 if j > len(substr) and all(data[0][i:i+j] in x for x in data):
422 422 substr = data[0][i:i+j]
423 423 elif len(data) == 1:
424 424 substr = data[0]
425 425 return substr
426 426
427 427
428 428 def strip_email_quotes(text):
429 429 """Strip leading email quotation characters ('>').
430 430
431 431 Removes any combination of leading '>' interspersed with whitespace that
432 432 appears *identically* in all lines of the input text.
433 433
434 434 Parameters
435 435 ----------
436 436 text : str
437 437
438 438 Examples
439 439 --------
440 440
441 441 Simple uses::
442 442
443 443 In [2]: strip_email_quotes('> > text')
444 444 Out[2]: 'text'
445 445
446 446 In [3]: strip_email_quotes('> > text\\n> > more')
447 447 Out[3]: 'text\\nmore'
448 448
449 449 Note how only the common prefix that appears in all lines is stripped::
450 450
451 451 In [4]: strip_email_quotes('> > text\\n> > more\\n> more...')
452 452 Out[4]: '> text\\n> more\\nmore...'
453 453
454 454 So if any line has no quote marks ('>') , then none are stripped from any
455 455 of them ::
456 456
457 457 In [5]: strip_email_quotes('> > text\\n> > more\\nlast different')
458 458 Out[5]: '> > text\\n> > more\\nlast different'
459 459 """
460 460 lines = text.splitlines()
461 461 matches = set()
462 462 for line in lines:
463 463 prefix = re.match(r'^(\s*>[ >]*)', line)
464 464 if prefix:
465 465 matches.add(prefix.group(1))
466 466 else:
467 467 break
468 468 else:
469 469 prefix = long_substr(list(matches))
470 470 if prefix:
471 471 strip = len(prefix)
472 472 text = '\n'.join([ ln[strip:] for ln in lines])
473 473 return text
474 474
475 475 def strip_ansi(source):
476 476 """
477 477 Remove ansi escape codes from text.
478 478
479 479 Parameters
480 480 ----------
481 481 source : str
482 482 Source to remove the ansi from
483 483 """
484 484 return re.sub(r'\033\[(\d|;)+?m', '', source)
485 485
486 486
487 487 class EvalFormatter(Formatter):
488 488 """A String Formatter that allows evaluation of simple expressions.
489 489
490 490 Note that this version interprets a : as specifying a format string (as per
491 491 standard string formatting), so if slicing is required, you must explicitly
492 492 create a slice.
493 493
494 494 This is to be used in templating cases, such as the parallel batch
495 495 script templates, where simple arithmetic on arguments is useful.
496 496
497 497 Examples
498 498 --------
499 499 ::
500 500
501 501 In [1]: f = EvalFormatter()
502 502 In [2]: f.format('{n//4}', n=8)
503 503 Out[2]: '2'
504 504
505 505 In [3]: f.format("{greeting[slice(2,4)]}", greeting="Hello")
506 506 Out[3]: 'll'
507 507 """
508 508 def get_field(self, name, args, kwargs):
509 509 v = eval(name, kwargs)
510 510 return v, name
511 511
512 512 #XXX: As of Python 3.4, the format string parsing no longer splits on a colon
513 513 # inside [], so EvalFormatter can handle slicing. Once we only support 3.4 and
514 514 # above, it should be possible to remove FullEvalFormatter.
515 515
516 516 class FullEvalFormatter(Formatter):
517 517 """A String Formatter that allows evaluation of simple expressions.
518 518
519 519 Any time a format key is not found in the kwargs,
520 520 it will be tried as an expression in the kwargs namespace.
521 521
522 522 Note that this version allows slicing using [1:2], so you cannot specify
523 523 a format string. Use :class:`EvalFormatter` to permit format strings.
524 524
525 525 Examples
526 526 --------
527 527 ::
528 528
529 529 In [1]: f = FullEvalFormatter()
530 530 In [2]: f.format('{n//4}', n=8)
531 531 Out[2]: '2'
532 532
533 533 In [3]: f.format('{list(range(5))[2:4]}')
534 534 Out[3]: '[2, 3]'
535 535
536 536 In [4]: f.format('{3*2}')
537 537 Out[4]: '6'
538 538 """
539 539 # copied from Formatter._vformat with minor changes to allow eval
540 540 # and replace the format_spec code with slicing
541 541 def vformat(self, format_string, args, kwargs):
542 542 result = []
543 543 for literal_text, field_name, format_spec, conversion in \
544 544 self.parse(format_string):
545 545
546 546 # output the literal text
547 547 if literal_text:
548 548 result.append(literal_text)
549 549
550 550 # if there's a field, output it
551 551 if field_name is not None:
552 552 # this is some markup, find the object and do
553 553 # the formatting
554 554
555 555 if format_spec:
556 556 # override format spec, to allow slicing:
557 557 field_name = ':'.join([field_name, format_spec])
558 558
559 559 # eval the contents of the field for the object
560 560 # to be formatted
561 561 obj = eval(field_name, kwargs)
562 562
563 563 # do any conversion on the resulting object
564 564 obj = self.convert_field(obj, conversion)
565 565
566 566 # format the object and append to the result
567 567 result.append(self.format_field(obj, ''))
568 568
569 569 return ''.join(py3compat.cast_unicode(s) for s in result)
570 570
571 571
572 572 class DollarFormatter(FullEvalFormatter):
573 573 """Formatter allowing Itpl style $foo replacement, for names and attribute
574 574 access only. Standard {foo} replacement also works, and allows full
575 575 evaluation of its arguments.
576 576
577 577 Examples
578 578 --------
579 579 ::
580 580
581 581 In [1]: f = DollarFormatter()
582 582 In [2]: f.format('{n//4}', n=8)
583 583 Out[2]: '2'
584 584
585 585 In [3]: f.format('23 * 76 is $result', result=23*76)
586 586 Out[3]: '23 * 76 is 1748'
587 587
588 588 In [4]: f.format('$a or {b}', a=1, b=2)
589 589 Out[4]: '1 or 2'
590 590 """
591 591 _dollar_pattern_ignore_single_quote = re.compile(r"(.*?)\$(\$?[\w\.]+)(?=([^']*'[^']*')*[^']*$)")
592 592 def parse(self, fmt_string):
593 593 for literal_txt, field_name, format_spec, conversion \
594 594 in Formatter.parse(self, fmt_string):
595 595
596 596 # Find $foo patterns in the literal text.
597 597 continue_from = 0
598 598 txt = ""
599 599 for m in self._dollar_pattern_ignore_single_quote.finditer(literal_txt):
600 600 new_txt, new_field = m.group(1,2)
601 601 # $$foo --> $foo
602 602 if new_field.startswith("$"):
603 603 txt += new_txt + new_field
604 604 else:
605 605 yield (txt + new_txt, new_field, "", None)
606 606 txt = ""
607 607 continue_from = m.end()
608 608
609 609 # Re-yield the {foo} style pattern
610 610 yield (txt + literal_txt[continue_from:], field_name, format_spec, conversion)
611 611
612 612 #-----------------------------------------------------------------------------
613 613 # Utils to columnize a list of string
614 614 #-----------------------------------------------------------------------------
615 615
616 616 def _col_chunks(l, max_rows, row_first=False):
617 617 """Yield successive max_rows-sized column chunks from l."""
618 618 if row_first:
619 619 ncols = (len(l) // max_rows) + (len(l) % max_rows > 0)
620 620 for i in range(ncols):
621 621 yield [l[j] for j in range(i, len(l), ncols)]
622 622 else:
623 623 for i in range(0, len(l), max_rows):
624 624 yield l[i:(i + max_rows)]
625 625
626 626
627 627 def _find_optimal(rlist, row_first=False, separator_size=2, displaywidth=80):
628 628 """Calculate optimal info to columnize a list of string"""
629 629 for max_rows in range(1, len(rlist) + 1):
630 630 col_widths = list(map(max, _col_chunks(rlist, max_rows, row_first)))
631 631 sumlength = sum(col_widths)
632 632 ncols = len(col_widths)
633 633 if sumlength + separator_size * (ncols - 1) <= displaywidth:
634 634 break
635 635 return {'num_columns': ncols,
636 636 'optimal_separator_width': (displaywidth - sumlength) // (ncols - 1) if (ncols - 1) else 0,
637 637 'max_rows': max_rows,
638 638 'column_widths': col_widths
639 639 }
640 640
641 641
642 642 def _get_or_default(mylist, i, default=None):
643 643 """return list item number, or default if don't exist"""
644 644 if i >= len(mylist):
645 645 return default
646 646 else :
647 647 return mylist[i]
648 648
649 649
650 650 def compute_item_matrix(items, row_first=False, empty=None, *args, **kwargs) :
651 651 """Returns a nested list, and info to columnize items
652 652
653 653 Parameters
654 654 ----------
655 655
656 656 items
657 657 list of strings to columize
658 658 row_first : (default False)
659 659 Whether to compute columns for a row-first matrix instead of
660 660 column-first (default).
661 661 empty : (default None)
662 662 default value to fill list if needed
663 663 separator_size : int (default=2)
664 664 How much characters will be used as a separation between each columns.
665 665 displaywidth : int (default=80)
666 666 The width of the area onto which the columns should enter
667 667
668 668 Returns
669 669 -------
670 670
671 671 strings_matrix
672 672
673 673 nested list of string, the outer most list contains as many list as
674 674 rows, the innermost lists have each as many element as columns. If the
675 675 total number of elements in `items` does not equal the product of
676 676 rows*columns, the last element of some lists are filled with `None`.
677 677
678 678 dict_info
679 679 some info to make columnize easier:
680 680
681 681 num_columns
682 682 number of columns
683 683 max_rows
684 684 maximum number of rows (final number may be less)
685 685 column_widths
686 686 list of with of each columns
687 687 optimal_separator_width
688 688 best separator width between columns
689 689
690 690 Examples
691 691 --------
692 692 ::
693 693
694 694 In [1]: l = ['aaa','b','cc','d','eeeee','f','g','h','i','j','k','l']
695 695 In [2]: list, info = compute_item_matrix(l, displaywidth=12)
696 696 In [3]: list
697 697 Out[3]: [['aaa', 'f', 'k'], ['b', 'g', 'l'], ['cc', 'h', None], ['d', 'i', None], ['eeeee', 'j', None]]
698 698 In [4]: ideal = {'num_columns': 3, 'column_widths': [5, 1, 1], 'optimal_separator_width': 2, 'max_rows': 5}
699 699 In [5]: all((info[k] == ideal[k] for k in ideal.keys()))
700 700 Out[5]: True
701 701 """
702 702 info = _find_optimal(list(map(len, items)), row_first, *args, **kwargs)
703 703 nrow, ncol = info['max_rows'], info['num_columns']
704 704 if row_first:
705 705 return ([[_get_or_default(items, r * ncol + c, default=empty) for c in range(ncol)] for r in range(nrow)], info)
706 706 else:
707 707 return ([[_get_or_default(items, c * nrow + r, default=empty) for c in range(ncol)] for r in range(nrow)], info)
708 708
709 709
710 710 def columnize(items, row_first=False, separator=' ', displaywidth=80, spread=False):
711 711 """ Transform a list of strings into a single string with columns.
712 712
713 713 Parameters
714 714 ----------
715 715 items : sequence of strings
716 716 The strings to process.
717 717
718 718 row_first : (default False)
719 719 Whether to compute columns for a row-first matrix instead of
720 720 column-first (default).
721 721
722 722 separator : str, optional [default is two spaces]
723 723 The string that separates columns.
724 724
725 725 displaywidth : int, optional [default is 80]
726 726 Width of the display in number of characters.
727 727
728 728 Returns
729 729 -------
730 730 The formatted string.
731 731 """
732 732 if not items:
733 733 return '\n'
734 734 matrix, info = compute_item_matrix(items, row_first=row_first, separator_size=len(separator), displaywidth=displaywidth)
735 735 if spread:
736 736 separator = separator.ljust(int(info['optimal_separator_width']))
737 737 fmatrix = [filter(None, x) for x in matrix]
738 738 sjoin = lambda x : separator.join([ y.ljust(w, ' ') for y, w in zip(x, info['column_widths'])])
739 739 return '\n'.join(map(sjoin, fmatrix))+'\n'
740 740
741 741
742 742 def get_text_list(list_, last_sep=' and ', sep=", ", wrap_item_with=""):
743 743 """
744 744 Return a string with a natural enumeration of items
745 745
746 746 >>> get_text_list(['a', 'b', 'c', 'd'])
747 747 'a, b, c and d'
748 748 >>> get_text_list(['a', 'b', 'c'], ' or ')
749 749 'a, b or c'
750 750 >>> get_text_list(['a', 'b', 'c'], ', ')
751 751 'a, b, c'
752 752 >>> get_text_list(['a', 'b'], ' or ')
753 753 'a or b'
754 754 >>> get_text_list(['a'])
755 755 'a'
756 756 >>> get_text_list([])
757 757 ''
758 758 >>> get_text_list(['a', 'b'], wrap_item_with="`")
759 759 '`a` and `b`'
760 760 >>> get_text_list(['a', 'b', 'c', 'd'], " = ", sep=" + ")
761 761 'a + b + c = d'
762 762 """
763 763 if len(list_) == 0:
764 764 return ''
765 765 if wrap_item_with:
766 766 list_ = ['%s%s%s' % (wrap_item_with, item, wrap_item_with) for
767 767 item in list_]
768 768 if len(list_) == 1:
769 769 return list_[0]
770 770 return '%s%s%s' % (
771 771 sep.join(i for i in list_[:-1]),
772 772 last_sep, list_[-1])
@@ -1,264 +1,263 b''
1 1 #!/usr/bin/env python3
2 2 # -*- coding: utf-8 -*-
3 3 """Setup script for IPython.
4 4
5 5 Under Posix environments it works like a typical setup.py script.
6 6 Under Windows, the command sdist is not supported, since IPython
7 7 requires utilities which are not available under Windows."""
8 8
9 9 #-----------------------------------------------------------------------------
10 10 # Copyright (c) 2008-2011, IPython Development Team.
11 11 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
12 12 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
13 13 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
14 14 #
15 15 # Distributed under the terms of the Modified BSD License.
16 16 #
17 17 # The full license is in the file COPYING.rst, distributed with this software.
18 18 #-----------------------------------------------------------------------------
19 19
20 20 from __future__ import print_function
21 21
22 22 import os
23 23 import sys
24 24
25 25 # **Python version check**
26 26 #
27 27 # This check is also made in IPython/__init__, don't forget to update both when
28 28 # changing Python version requirements.
29 29 if sys.version_info < (3, 5):
30 30 pip_message = 'This may be due to an out of date pip. Make sure you have pip >= 9.0.1.'
31 31 try:
32 32 import pip
33 33 pip_version = tuple([int(x) for x in pip.__version__.split('.')[:3]])
34 34 if pip_version < (9, 0, 1) :
35 35 pip_message = 'Your pip version is out of date, please install pip >= 9.0.1. '\
36 36 'pip {} detected.'.format(pip.__version__)
37 37 else:
38 38 # pip is new enough - it must be something else
39 39 pip_message = ''
40 40 except Exception:
41 41 pass
42 42
43 43
44 44 error = """
45 45 IPython 7.0+ supports Python 3.5 and above.
46 46 When using Python 2.7, please install IPython 5.x LTS Long Term Support version.
47 47 Python 3.3 and 3.4 were supported up to IPython 6.x.
48 48
49 49 See IPython `README.rst` file for more information:
50 50
51 51 https://github.com/ipython/ipython/blob/master/README.rst
52 52
53 53 Python {py} detected.
54 54 {pip}
55 55 """.format(py=sys.version_info, pip=pip_message )
56 56
57 57 print(error, file=sys.stderr)
58 58 sys.exit(1)
59 59
60 60 # At least we're on the python version we need, move on.
61 61
62 62 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
63 63 # update it when the contents of directories change.
64 64 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
65 65
66 66 from distutils.core import setup
67 67
68 68 # Our own imports
69 69 from setupbase import target_update
70 70
71 71 from setupbase import (
72 72 setup_args,
73 73 find_packages,
74 74 find_package_data,
75 75 check_package_data_first,
76 76 find_entry_points,
77 77 build_scripts_entrypt,
78 78 find_data_files,
79 79 git_prebuild,
80 80 install_symlinked,
81 81 install_lib_symlink,
82 82 install_scripts_for_symlink,
83 83 unsymlink,
84 84 )
85 85
86 86 isfile = os.path.isfile
87 87 pjoin = os.path.join
88 88
89 89 #-------------------------------------------------------------------------------
90 90 # Handle OS specific things
91 91 #-------------------------------------------------------------------------------
92 92
93 93 if os.name in ('nt','dos'):
94 94 os_name = 'windows'
95 95 else:
96 96 os_name = os.name
97 97
98 98 # Under Windows, 'sdist' has not been supported. Now that the docs build with
99 99 # Sphinx it might work, but let's not turn it on until someone confirms that it
100 100 # actually works.
101 101 if os_name == 'windows' and 'sdist' in sys.argv:
102 102 print('The sdist command is not available under Windows. Exiting.')
103 103 sys.exit(1)
104 104
105 105
106 106 #-------------------------------------------------------------------------------
107 107 # Things related to the IPython documentation
108 108 #-------------------------------------------------------------------------------
109 109
110 110 # update the manuals when building a source dist
111 111 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
112 112
113 113 # List of things to be updated. Each entry is a triplet of args for
114 114 # target_update()
115 115 to_update = [
116 116 ('docs/man/ipython.1.gz',
117 117 ['docs/man/ipython.1'],
118 118 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
119 119 ]
120 120
121 121
122 122 [ target_update(*t) for t in to_update ]
123 123
124 124 #---------------------------------------------------------------------------
125 125 # Find all the packages, package data, and data_files
126 126 #---------------------------------------------------------------------------
127 127
128 128 packages = find_packages()
129 129 package_data = find_package_data()
130 130
131 131 data_files = find_data_files()
132 132
133 133 setup_args['packages'] = packages
134 134 setup_args['package_data'] = package_data
135 135 setup_args['data_files'] = data_files
136 136
137 137 #---------------------------------------------------------------------------
138 138 # custom distutils commands
139 139 #---------------------------------------------------------------------------
140 140 # imports here, so they are after setuptools import if there was one
141 141 from distutils.command.sdist import sdist
142 142
143 143 setup_args['cmdclass'] = {
144 144 'build_py': \
145 145 check_package_data_first(git_prebuild('IPython')),
146 146 'sdist' : git_prebuild('IPython', sdist),
147 147 'symlink': install_symlinked,
148 148 'install_lib_symlink': install_lib_symlink,
149 149 'install_scripts_sym': install_scripts_for_symlink,
150 150 'unsymlink': unsymlink,
151 151 }
152 152
153 153
154 154 #---------------------------------------------------------------------------
155 155 # Handle scripts, dependencies, and setuptools specific things
156 156 #---------------------------------------------------------------------------
157 157
158 158 # For some commands, use setuptools. Note that we do NOT list install here!
159 159 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
160 160 needs_setuptools = {'develop', 'release', 'bdist_egg', 'bdist_rpm',
161 161 'bdist', 'bdist_dumb', 'bdist_wininst', 'bdist_wheel',
162 162 'egg_info', 'easy_install', 'upload', 'install_egg_info',
163 163 }
164 164
165 165 if len(needs_setuptools.intersection(sys.argv)) > 0:
166 166 import setuptools
167 167
168 168 # This dict is used for passing extra arguments that are setuptools
169 169 # specific to setup
170 170 setuptools_extra_args = {}
171 171
172 172 # setuptools requirements
173 173
174 174 extras_require = dict(
175 175 parallel = ['ipyparallel'],
176 176 qtconsole = ['qtconsole'],
177 177 doc = ['Sphinx>=1.3'],
178 178 test = ['nose>=0.10.1', 'requests', 'testpath', 'pygments', 'nbformat', 'ipykernel', 'numpy'],
179 179 terminal = [],
180 180 kernel = ['ipykernel'],
181 181 nbformat = ['nbformat'],
182 182 notebook = ['notebook', 'ipywidgets'],
183 183 nbconvert = ['nbconvert'],
184 184 )
185 185
186 186 install_requires = [
187 187 'setuptools>=18.5',
188 188 'jedi>=0.10',
189 189 'decorator',
190 190 'pickleshare',
191 'simplegeneric>0.8',
192 191 'traitlets>=4.2',
193 192 'prompt_toolkit>=2.0.0,<2.1.0',
194 193 'pygments',
195 194 'backcall',
196 195 ]
197 196
198 197 # Platform-specific dependencies:
199 198 # This is the correct way to specify these,
200 199 # but requires pip >= 6. pip < 6 ignores these.
201 200
202 201 extras_require.update({
203 202 ':python_version == "3.4"': ['typing'],
204 203 ':sys_platform != "win32"': ['pexpect'],
205 204 ':sys_platform == "darwin"': ['appnope'],
206 205 ':sys_platform == "win32"': ['colorama'],
207 206 ':sys_platform == "win32" and python_version < "3.6"': ['win_unicode_console>=0.5'],
208 207 })
209 208 # FIXME: re-specify above platform dependencies for pip < 6
210 209 # These would result in non-portable bdists.
211 210 if not any(arg.startswith('bdist') for arg in sys.argv):
212 211 if sys.platform == 'darwin':
213 212 install_requires.extend(['appnope'])
214 213
215 214 if not sys.platform.startswith('win'):
216 215 install_requires.append('pexpect')
217 216
218 217 # workaround pypa/setuptools#147, where setuptools misspells
219 218 # platform_python_implementation as python_implementation
220 219 if 'setuptools' in sys.modules:
221 220 for key in list(extras_require):
222 221 if 'platform_python_implementation' in key:
223 222 new_key = key.replace('platform_python_implementation', 'python_implementation')
224 223 extras_require[new_key] = extras_require.pop(key)
225 224
226 225 everything = set()
227 226 for key, deps in extras_require.items():
228 227 if ':' not in key:
229 228 everything.update(deps)
230 229 extras_require['all'] = everything
231 230
232 231 if 'setuptools' in sys.modules:
233 232 setuptools_extra_args['python_requires'] = '>=3.5'
234 233 setuptools_extra_args['zip_safe'] = False
235 234 setuptools_extra_args['entry_points'] = {
236 235 'console_scripts': find_entry_points(),
237 236 'pygments.lexers': [
238 237 'ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer',
239 238 'ipython = IPython.lib.lexers:IPythonLexer',
240 239 'ipython3 = IPython.lib.lexers:IPython3Lexer',
241 240 ],
242 241 }
243 242 setup_args['extras_require'] = extras_require
244 243 setup_args['install_requires'] = install_requires
245 244
246 245 else:
247 246 # scripts has to be a non-empty list, or install_scripts isn't called
248 247 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
249 248
250 249 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
251 250
252 251 #---------------------------------------------------------------------------
253 252 # Do the actual setup now
254 253 #---------------------------------------------------------------------------
255 254
256 255 setup_args.update(setuptools_extra_args)
257 256
258 257
259 258
260 259 def main():
261 260 setup(**setup_args)
262 261
263 262 if __name__ == '__main__':
264 263 main()
General Comments 0
You need to be logged in to leave comments. Login now