##// END OF EJS Templates
Summary of changes:...
Doug Blank -
Show More
@@ -1,147 +1,147 b''
1 1 """Compiler tools with improved interactive support.
2 2
3 3 Provides compilation machinery similar to codeop, but with caching support so
4 4 we can provide interactive tracebacks.
5 5
6 6 Authors
7 7 -------
8 8 * Robert Kern
9 9 * Fernando Perez
10 10 * Thomas Kluyver
11 11 """
12 12
13 13 # Note: though it might be more natural to name this module 'compiler', that
14 14 # name is in the stdlib and name collisions with the stdlib tend to produce
15 15 # weird problems (often with third-party tools).
16 16
17 17 #-----------------------------------------------------------------------------
18 18 # Copyright (C) 2010-2011 The IPython Development Team.
19 19 #
20 20 # Distributed under the terms of the BSD License.
21 21 #
22 22 # The full license is in the file COPYING.txt, distributed with this software.
23 23 #-----------------------------------------------------------------------------
24 24
25 25 #-----------------------------------------------------------------------------
26 26 # Imports
27 27 #-----------------------------------------------------------------------------
28 28 from __future__ import print_function
29 29
30 30 # Stdlib imports
31 31 import __future__
32 32 from ast import PyCF_ONLY_AST
33 33 import codeop
34 34 import functools
35 35 import hashlib
36 36 import linecache
37 37 import operator
38 38 import time
39 39
40 40 #-----------------------------------------------------------------------------
41 41 # Constants
42 42 #-----------------------------------------------------------------------------
43 43
44 44 # Roughtly equal to PyCF_MASK | PyCF_MASK_OBSOLETE as defined in pythonrun.h,
45 45 # this is used as a bitmask to extract future-related code flags.
46 PyCF_MASK = functools.reduce(operator.or_,
47 (getattr(__future__, fname).compiler_flag
48 for fname in __future__.all_feature_names
49 if (hasattr(__future__, fname) and
50 hasattr(getattr(__future__, fname), "compiler_flag"))),
51 0)
46 try:
47 PyCF_MASK = functools.reduce(operator.or_,
48 (getattr(__future__, fname).compiler_flag
49 for fname in __future__.all_feature_names))
50 except AttributeError: # IronPython __future__'s are non-standard, 2/8/2014
51 PyCF_MASK = 0
52 52
53 53 #-----------------------------------------------------------------------------
54 54 # Local utilities
55 55 #-----------------------------------------------------------------------------
56 56
57 57 def code_name(code, number=0):
58 58 """ Compute a (probably) unique name for code for caching.
59 59
60 60 This now expects code to be unicode.
61 61 """
62 62 hash_digest = hashlib.md5(code.encode("utf-8")).hexdigest()
63 63 # Include the number and 12 characters of the hash in the name. It's
64 64 # pretty much impossible that in a single session we'll have collisions
65 65 # even with truncated hashes, and the full one makes tracebacks too long
66 66 return '<ipython-input-{0}-{1}>'.format(number, hash_digest[:12])
67 67
68 68 #-----------------------------------------------------------------------------
69 69 # Classes and functions
70 70 #-----------------------------------------------------------------------------
71 71
72 72 class CachingCompiler(codeop.Compile):
73 73 """A compiler that caches code compiled from interactive statements.
74 74 """
75 75
76 76 def __init__(self):
77 77 codeop.Compile.__init__(self)
78 78
79 79 # This is ugly, but it must be done this way to allow multiple
80 80 # simultaneous ipython instances to coexist. Since Python itself
81 81 # directly accesses the data structures in the linecache module, and
82 82 # the cache therein is global, we must work with that data structure.
83 83 # We must hold a reference to the original checkcache routine and call
84 84 # that in our own check_cache() below, but the special IPython cache
85 85 # must also be shared by all IPython instances. If we were to hold
86 86 # separate caches (one in each CachingCompiler instance), any call made
87 87 # by Python itself to linecache.checkcache() would obliterate the
88 88 # cached data from the other IPython instances.
89 89 if not hasattr(linecache, '_ipython_cache'):
90 90 linecache._ipython_cache = {}
91 91 if not hasattr(linecache, '_checkcache_ori'):
92 92 linecache._checkcache_ori = linecache.checkcache
93 93 # Now, we must monkeypatch the linecache directly so that parts of the
94 94 # stdlib that call it outside our control go through our codepath
95 95 # (otherwise we'd lose our tracebacks).
96 96 linecache.checkcache = check_linecache_ipython
97 97
98 98 def ast_parse(self, source, filename='<unknown>', symbol='exec'):
99 99 """Parse code to an AST with the current compiler flags active.
100 100
101 101 Arguments are exactly the same as ast.parse (in the standard library),
102 102 and are passed to the built-in compile function."""
103 103 return compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1)
104 104
105 105 def reset_compiler_flags(self):
106 106 """Reset compiler flags to default state."""
107 107 # This value is copied from codeop.Compile.__init__, so if that ever
108 108 # changes, it will need to be updated.
109 109 self.flags = codeop.PyCF_DONT_IMPLY_DEDENT
110 110
111 111 @property
112 112 def compiler_flags(self):
113 113 """Flags currently active in the compilation process.
114 114 """
115 115 return self.flags
116 116
117 117 def cache(self, code, number=0):
118 118 """Make a name for a block of code, and cache the code.
119 119
120 120 Parameters
121 121 ----------
122 122 code : str
123 123 The Python source code to cache.
124 124 number : int
125 125 A number which forms part of the code's name. Used for the execution
126 126 counter.
127 127
128 128 Returns
129 129 -------
130 130 The name of the cached code (as a string). Pass this as the filename
131 131 argument to compilation, so that tracebacks are correctly hooked up.
132 132 """
133 133 name = code_name(code, number)
134 134 entry = (len(code), time.time(),
135 135 [line+'\n' for line in code.splitlines()], name)
136 136 linecache.cache[name] = entry
137 137 linecache._ipython_cache[name] = entry
138 138 return name
139 139
140 140 def check_linecache_ipython(*args):
141 141 """Call linecache.checkcache() safely protecting our cached values.
142 142 """
143 143 # First call the orignal checkcache as intended
144 144 linecache._checkcache_ori(*args)
145 145 # Then, update back the cache with our data, so that tracebacks related
146 146 # to our compiled codes can be produced.
147 147 linecache.cache.update(linecache._ipython_cache)
@@ -1,1000 +1,997 b''
1 1 """Word completion for IPython.
2 2
3 3 This module is a fork of the rlcompleter module in the Python standard
4 4 library. The original enhancements made to rlcompleter have been sent
5 5 upstream and were accepted as of Python 2.3, but we need a lot more
6 6 functionality specific to IPython, so this module will continue to live as an
7 7 IPython-specific utility.
8 8
9 9 Original rlcompleter documentation:
10 10
11 11 This requires the latest extension to the readline module (the
12 12 completes keywords, built-ins and globals in __main__; when completing
13 13 NAME.NAME..., it evaluates (!) the expression up to the last dot and
14 14 completes its attributes.
15 15
16 16 It's very cool to do "import string" type "string.", hit the
17 17 completion key (twice), and see the list of names defined by the
18 18 string module!
19 19
20 20 Tip: to use the tab key as the completion key, call
21 21
22 22 readline.parse_and_bind("tab: complete")
23 23
24 24 Notes:
25 25
26 26 - Exceptions raised by the completer function are *ignored* (and
27 27 generally cause the completion to fail). This is a feature -- since
28 28 readline sets the tty device in raw (or cbreak) mode, printing a
29 29 traceback wouldn't work well without some complicated hoopla to save,
30 30 reset and restore the tty state.
31 31
32 32 - The evaluation of the NAME.NAME... form may cause arbitrary
33 33 application defined code to be executed if an object with a
34 34 ``__getattr__`` hook is found. Since it is the responsibility of the
35 35 application (or the user) to enable this feature, I consider this an
36 36 acceptable risk. More complicated expressions (e.g. function calls or
37 37 indexing operations) are *not* evaluated.
38 38
39 39 - GNU readline is also used by the built-in functions input() and
40 40 raw_input(), and thus these also benefit/suffer from the completer
41 41 features. Clearly an interactive application can benefit by
42 42 specifying its own completer function and using raw_input() for all
43 43 its input.
44 44
45 45 - When the original stdin is not a tty device, GNU readline is never
46 46 used, and this module (and the readline module) are silently inactive.
47 47 """
48 48
49 49 #*****************************************************************************
50 50 #
51 51 # Since this file is essentially a minimally modified copy of the rlcompleter
52 52 # module which is part of the standard Python distribution, I assume that the
53 53 # proper procedure is to maintain its copyright as belonging to the Python
54 54 # Software Foundation (in addition to my own, for all new code).
55 55 #
56 56 # Copyright (C) 2008 IPython Development Team
57 57 # Copyright (C) 2001 Fernando Perez. <fperez@colorado.edu>
58 58 # Copyright (C) 2001 Python Software Foundation, www.python.org
59 59 #
60 60 # Distributed under the terms of the BSD License. The full license is in
61 61 # the file COPYING, distributed as part of this software.
62 62 #
63 63 #*****************************************************************************
64 64
65 65 #-----------------------------------------------------------------------------
66 66 # Imports
67 67 #-----------------------------------------------------------------------------
68 68
69 try:
70 import __main__
71 except ImportError:
72 pass
69 import __main__
73 70 import glob
74 71 import inspect
75 72 import itertools
76 73 import keyword
77 74 import os
78 75 import re
79 76 import sys
80 77
81 78 from IPython.config.configurable import Configurable
82 79 from IPython.core.error import TryNext
83 80 from IPython.core.inputsplitter import ESC_MAGIC
84 81 from IPython.utils import generics
85 82 from IPython.utils import io
86 83 from IPython.utils.dir2 import dir2
87 84 from IPython.utils.process import arg_split
88 85 from IPython.utils.py3compat import builtin_mod, string_types
89 86 from IPython.utils.traitlets import CBool, Enum
90 87
91 88 #-----------------------------------------------------------------------------
92 89 # Globals
93 90 #-----------------------------------------------------------------------------
94 91
95 92 # Public API
96 93 __all__ = ['Completer','IPCompleter']
97 94
98 95 if sys.platform == 'win32':
99 96 PROTECTABLES = ' '
100 97 else:
101 98 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
102 99
103 100 #-----------------------------------------------------------------------------
104 101 # Main functions and classes
105 102 #-----------------------------------------------------------------------------
106 103
107 104 def has_open_quotes(s):
108 105 """Return whether a string has open quotes.
109 106
110 107 This simply counts whether the number of quote characters of either type in
111 108 the string is odd.
112 109
113 110 Returns
114 111 -------
115 112 If there is an open quote, the quote character is returned. Else, return
116 113 False.
117 114 """
118 115 # We check " first, then ', so complex cases with nested quotes will get
119 116 # the " to take precedence.
120 117 if s.count('"') % 2:
121 118 return '"'
122 119 elif s.count("'") % 2:
123 120 return "'"
124 121 else:
125 122 return False
126 123
127 124
128 125 def protect_filename(s):
129 126 """Escape a string to protect certain characters."""
130 127
131 128 return "".join([(ch in PROTECTABLES and '\\' + ch or ch)
132 129 for ch in s])
133 130
134 131 def expand_user(path):
135 132 """Expand '~'-style usernames in strings.
136 133
137 134 This is similar to :func:`os.path.expanduser`, but it computes and returns
138 135 extra information that will be useful if the input was being used in
139 136 computing completions, and you wish to return the completions with the
140 137 original '~' instead of its expanded value.
141 138
142 139 Parameters
143 140 ----------
144 141 path : str
145 142 String to be expanded. If no ~ is present, the output is the same as the
146 143 input.
147 144
148 145 Returns
149 146 -------
150 147 newpath : str
151 148 Result of ~ expansion in the input path.
152 149 tilde_expand : bool
153 150 Whether any expansion was performed or not.
154 151 tilde_val : str
155 152 The value that ~ was replaced with.
156 153 """
157 154 # Default values
158 155 tilde_expand = False
159 156 tilde_val = ''
160 157 newpath = path
161 158
162 159 if path.startswith('~'):
163 160 tilde_expand = True
164 161 rest = len(path)-1
165 162 newpath = os.path.expanduser(path)
166 163 if rest:
167 164 tilde_val = newpath[:-rest]
168 165 else:
169 166 tilde_val = newpath
170 167
171 168 return newpath, tilde_expand, tilde_val
172 169
173 170
174 171 def compress_user(path, tilde_expand, tilde_val):
175 172 """Does the opposite of expand_user, with its outputs.
176 173 """
177 174 if tilde_expand:
178 175 return path.replace(tilde_val, '~')
179 176 else:
180 177 return path
181 178
182 179
183 180
184 181 def penalize_magics_key(word):
185 182 """key for sorting that penalizes magic commands in the ordering
186 183
187 184 Normal words are left alone.
188 185
189 186 Magic commands have the initial % moved to the end, e.g.
190 187 %matplotlib is transformed as follows:
191 188
192 189 %matplotlib -> matplotlib%
193 190
194 191 [The choice of the final % is arbitrary.]
195 192
196 193 Since "matplotlib" < "matplotlib%" as strings,
197 194 "timeit" will appear before the magic "%timeit" in the ordering
198 195
199 196 For consistency, move "%%" to the end, so cell magics appear *after*
200 197 line magics with the same name.
201 198
202 199 A check is performed that there are no other "%" in the string;
203 200 if there are, then the string is not a magic command and is left unchanged.
204 201
205 202 """
206 203
207 204 # Move any % signs from start to end of the key
208 205 # provided there are no others elsewhere in the string
209 206
210 207 if word[:2] == "%%":
211 208 if not "%" in word[2:]:
212 209 return word[2:] + "%%"
213 210
214 211 if word[:1] == "%":
215 212 if not "%" in word[1:]:
216 213 return word[1:] + "%"
217 214
218 215 return word
219 216
220 217
221 218
222 219 class Bunch(object): pass
223 220
224 221
225 222 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
226 223 GREEDY_DELIMS = ' =\r\n'
227 224
228 225
229 226 class CompletionSplitter(object):
230 227 """An object to split an input line in a manner similar to readline.
231 228
232 229 By having our own implementation, we can expose readline-like completion in
233 230 a uniform manner to all frontends. This object only needs to be given the
234 231 line of text to be split and the cursor position on said line, and it
235 232 returns the 'word' to be completed on at the cursor after splitting the
236 233 entire line.
237 234
238 235 What characters are used as splitting delimiters can be controlled by
239 236 setting the `delims` attribute (this is a property that internally
240 237 automatically builds the necessary regular expression)"""
241 238
242 239 # Private interface
243 240
244 241 # A string of delimiter characters. The default value makes sense for
245 242 # IPython's most typical usage patterns.
246 243 _delims = DELIMS
247 244
248 245 # The expression (a normal string) to be compiled into a regular expression
249 246 # for actual splitting. We store it as an attribute mostly for ease of
250 247 # debugging, since this type of code can be so tricky to debug.
251 248 _delim_expr = None
252 249
253 250 # The regular expression that does the actual splitting
254 251 _delim_re = None
255 252
256 253 def __init__(self, delims=None):
257 254 delims = CompletionSplitter._delims if delims is None else delims
258 255 self.delims = delims
259 256
260 257 @property
261 258 def delims(self):
262 259 """Return the string of delimiter characters."""
263 260 return self._delims
264 261
265 262 @delims.setter
266 263 def delims(self, delims):
267 264 """Set the delimiters for line splitting."""
268 265 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
269 266 self._delim_re = re.compile(expr)
270 267 self._delims = delims
271 268 self._delim_expr = expr
272 269
273 270 def split_line(self, line, cursor_pos=None):
274 271 """Split a line of text with a cursor at the given position.
275 272 """
276 273 l = line if cursor_pos is None else line[:cursor_pos]
277 274 return self._delim_re.split(l)[-1]
278 275
279 276
280 277 class Completer(Configurable):
281 278
282 279 greedy = CBool(False, config=True,
283 280 help="""Activate greedy completion
284 281
285 282 This will enable completion on elements of lists, results of function calls, etc.,
286 283 but can be unsafe because the code is actually evaluated on TAB.
287 284 """
288 285 )
289 286
290 287
291 288 def __init__(self, namespace=None, global_namespace=None, **kwargs):
292 289 """Create a new completer for the command line.
293 290
294 291 Completer(namespace=ns,global_namespace=ns2) -> completer instance.
295 292
296 293 If unspecified, the default namespace where completions are performed
297 294 is __main__ (technically, __main__.__dict__). Namespaces should be
298 295 given as dictionaries.
299 296
300 297 An optional second namespace can be given. This allows the completer
301 298 to handle cases where both the local and global scopes need to be
302 299 distinguished.
303 300
304 301 Completer instances should be used as the completion mechanism of
305 302 readline via the set_completer() call:
306 303
307 304 readline.set_completer(Completer(my_namespace).complete)
308 305 """
309 306
310 307 # Don't bind to namespace quite yet, but flag whether the user wants a
311 308 # specific namespace or to use __main__.__dict__. This will allow us
312 309 # to bind to __main__.__dict__ at completion time, not now.
313 310 if namespace is None:
314 311 self.use_main_ns = 1
315 312 else:
316 313 self.use_main_ns = 0
317 314 self.namespace = namespace
318 315
319 316 # The global namespace, if given, can be bound directly
320 317 if global_namespace is None:
321 318 self.global_namespace = {}
322 319 else:
323 320 self.global_namespace = global_namespace
324 321
325 322 super(Completer, self).__init__(**kwargs)
326 323
327 324 def complete(self, text, state):
328 325 """Return the next possible completion for 'text'.
329 326
330 327 This is called successively with state == 0, 1, 2, ... until it
331 328 returns None. The completion should begin with 'text'.
332 329
333 330 """
334 331 if self.use_main_ns:
335 332 self.namespace = __main__.__dict__
336 333
337 334 if state == 0:
338 335 if "." in text:
339 336 self.matches = self.attr_matches(text)
340 337 else:
341 338 self.matches = self.global_matches(text)
342 339 try:
343 340 return self.matches[state]
344 341 except IndexError:
345 342 return None
346 343
347 344 def global_matches(self, text):
348 345 """Compute matches when text is a simple name.
349 346
350 347 Return a list of all keywords, built-in functions and names currently
351 348 defined in self.namespace or self.global_namespace that match.
352 349
353 350 """
354 351 #print 'Completer->global_matches, txt=%r' % text # dbg
355 352 matches = []
356 353 match_append = matches.append
357 354 n = len(text)
358 355 for lst in [keyword.kwlist,
359 356 builtin_mod.__dict__.keys(),
360 357 self.namespace.keys(),
361 358 self.global_namespace.keys()]:
362 359 for word in lst:
363 360 if word[:n] == text and word != "__builtins__":
364 361 match_append(word)
365 362 return matches
366 363
367 364 def attr_matches(self, text):
368 365 """Compute matches when text contains a dot.
369 366
370 367 Assuming the text is of the form NAME.NAME....[NAME], and is
371 368 evaluatable in self.namespace or self.global_namespace, it will be
372 369 evaluated and its attributes (as revealed by dir()) are used as
373 370 possible completions. (For class instances, class members are are
374 371 also considered.)
375 372
376 373 WARNING: this can still invoke arbitrary C code, if an object
377 374 with a __getattr__ hook is evaluated.
378 375
379 376 """
380 377
381 378 #io.rprint('Completer->attr_matches, txt=%r' % text) # dbg
382 379 # Another option, seems to work great. Catches things like ''.<tab>
383 380 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
384 381
385 382 if m:
386 383 expr, attr = m.group(1, 3)
387 384 elif self.greedy:
388 385 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
389 386 if not m2:
390 387 return []
391 388 expr, attr = m2.group(1,2)
392 389 else:
393 390 return []
394 391
395 392 try:
396 393 obj = eval(expr, self.namespace)
397 394 except:
398 395 try:
399 396 obj = eval(expr, self.global_namespace)
400 397 except:
401 398 return []
402 399
403 400 if self.limit_to__all__ and hasattr(obj, '__all__'):
404 401 words = get__all__entries(obj)
405 402 else:
406 403 words = dir2(obj)
407 404
408 405 try:
409 406 words = generics.complete_object(obj, words)
410 407 except TryNext:
411 408 pass
412 409 except Exception:
413 410 # Silence errors from completion function
414 411 #raise # dbg
415 412 pass
416 413 # Build match list to return
417 414 n = len(attr)
418 415 res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ]
419 416 return res
420 417
421 418
422 419 def get__all__entries(obj):
423 420 """returns the strings in the __all__ attribute"""
424 421 try:
425 422 words = getattr(obj, '__all__')
426 423 except:
427 424 return []
428 425
429 426 return [w for w in words if isinstance(w, string_types)]
430 427
431 428
432 429 class IPCompleter(Completer):
433 430 """Extension of the completer class with IPython-specific features"""
434 431
435 432 def _greedy_changed(self, name, old, new):
436 433 """update the splitter and readline delims when greedy is changed"""
437 434 if new:
438 435 self.splitter.delims = GREEDY_DELIMS
439 436 else:
440 437 self.splitter.delims = DELIMS
441 438
442 439 if self.readline:
443 440 self.readline.set_completer_delims(self.splitter.delims)
444 441
445 442 merge_completions = CBool(True, config=True,
446 443 help="""Whether to merge completion results into a single list
447 444
448 445 If False, only the completion results from the first non-empty
449 446 completer will be returned.
450 447 """
451 448 )
452 449 omit__names = Enum((0,1,2), default_value=2, config=True,
453 450 help="""Instruct the completer to omit private method names
454 451
455 452 Specifically, when completing on ``object.<tab>``.
456 453
457 454 When 2 [default]: all names that start with '_' will be excluded.
458 455
459 456 When 1: all 'magic' names (``__foo__``) will be excluded.
460 457
461 458 When 0: nothing will be excluded.
462 459 """
463 460 )
464 461 limit_to__all__ = CBool(default_value=False, config=True,
465 462 help="""Instruct the completer to use __all__ for the completion
466 463
467 464 Specifically, when completing on ``object.<tab>``.
468 465
469 466 When True: only those names in obj.__all__ will be included.
470 467
471 468 When False [default]: the __all__ attribute is ignored
472 469 """
473 470 )
474 471
475 472 def __init__(self, shell=None, namespace=None, global_namespace=None,
476 473 use_readline=True, config=None, **kwargs):
477 474 """IPCompleter() -> completer
478 475
479 476 Return a completer object suitable for use by the readline library
480 477 via readline.set_completer().
481 478
482 479 Inputs:
483 480
484 481 - shell: a pointer to the ipython shell itself. This is needed
485 482 because this completer knows about magic functions, and those can
486 483 only be accessed via the ipython instance.
487 484
488 485 - namespace: an optional dict where completions are performed.
489 486
490 487 - global_namespace: secondary optional dict for completions, to
491 488 handle cases (such as IPython embedded inside functions) where
492 489 both Python scopes are visible.
493 490
494 491 use_readline : bool, optional
495 492 If true, use the readline library. This completer can still function
496 493 without readline, though in that case callers must provide some extra
497 494 information on each call about the current line."""
498 495
499 496 self.magic_escape = ESC_MAGIC
500 497 self.splitter = CompletionSplitter()
501 498
502 499 # Readline configuration, only used by the rlcompleter method.
503 500 if use_readline:
504 501 # We store the right version of readline so that later code
505 502 import IPython.utils.rlineimpl as readline
506 503 self.readline = readline
507 504 else:
508 505 self.readline = None
509 506
510 507 # _greedy_changed() depends on splitter and readline being defined:
511 508 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
512 509 config=config, **kwargs)
513 510
514 511 # List where completion matches will be stored
515 512 self.matches = []
516 513 self.shell = shell
517 514 # Regexp to split filenames with spaces in them
518 515 self.space_name_re = re.compile(r'([^\\] )')
519 516 # Hold a local ref. to glob.glob for speed
520 517 self.glob = glob.glob
521 518
522 519 # Determine if we are running on 'dumb' terminals, like (X)Emacs
523 520 # buffers, to avoid completion problems.
524 521 term = os.environ.get('TERM','xterm')
525 522 self.dumb_terminal = term in ['dumb','emacs']
526 523
527 524 # Special handling of backslashes needed in win32 platforms
528 525 if sys.platform == "win32":
529 526 self.clean_glob = self._clean_glob_win32
530 527 else:
531 528 self.clean_glob = self._clean_glob
532 529
533 530 #regexp to parse docstring for function signature
534 531 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
535 532 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
536 533 #use this if positional argument name is also needed
537 534 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
538 535
539 536 # All active matcher routines for completion
540 537 self.matchers = [self.python_matches,
541 538 self.file_matches,
542 539 self.magic_matches,
543 540 self.python_func_kw_matches,
544 541 ]
545 542
546 543 def all_completions(self, text):
547 544 """
548 545 Wrapper around the complete method for the benefit of emacs
549 546 and pydb.
550 547 """
551 548 return self.complete(text)[1]
552 549
553 550 def _clean_glob(self,text):
554 551 return self.glob("%s*" % text)
555 552
556 553 def _clean_glob_win32(self,text):
557 554 return [f.replace("\\","/")
558 555 for f in self.glob("%s*" % text)]
559 556
560 557 def file_matches(self, text):
561 558 """Match filenames, expanding ~USER type strings.
562 559
563 560 Most of the seemingly convoluted logic in this completer is an
564 561 attempt to handle filenames with spaces in them. And yet it's not
565 562 quite perfect, because Python's readline doesn't expose all of the
566 563 GNU readline details needed for this to be done correctly.
567 564
568 565 For a filename with a space in it, the printed completions will be
569 566 only the parts after what's already been typed (instead of the
570 567 full completions, as is normally done). I don't think with the
571 568 current (as of Python 2.3) Python readline it's possible to do
572 569 better."""
573 570
574 571 #io.rprint('Completer->file_matches: <%r>' % text) # dbg
575 572
576 573 # chars that require escaping with backslash - i.e. chars
577 574 # that readline treats incorrectly as delimiters, but we
578 575 # don't want to treat as delimiters in filename matching
579 576 # when escaped with backslash
580 577 if text.startswith('!'):
581 578 text = text[1:]
582 579 text_prefix = '!'
583 580 else:
584 581 text_prefix = ''
585 582
586 583 text_until_cursor = self.text_until_cursor
587 584 # track strings with open quotes
588 585 open_quotes = has_open_quotes(text_until_cursor)
589 586
590 587 if '(' in text_until_cursor or '[' in text_until_cursor:
591 588 lsplit = text
592 589 else:
593 590 try:
594 591 # arg_split ~ shlex.split, but with unicode bugs fixed by us
595 592 lsplit = arg_split(text_until_cursor)[-1]
596 593 except ValueError:
597 594 # typically an unmatched ", or backslash without escaped char.
598 595 if open_quotes:
599 596 lsplit = text_until_cursor.split(open_quotes)[-1]
600 597 else:
601 598 return []
602 599 except IndexError:
603 600 # tab pressed on empty line
604 601 lsplit = ""
605 602
606 603 if not open_quotes and lsplit != protect_filename(lsplit):
607 604 # if protectables are found, do matching on the whole escaped name
608 605 has_protectables = True
609 606 text0,text = text,lsplit
610 607 else:
611 608 has_protectables = False
612 609 text = os.path.expanduser(text)
613 610
614 611 if text == "":
615 612 return [text_prefix + protect_filename(f) for f in self.glob("*")]
616 613
617 614 # Compute the matches from the filesystem
618 615 m0 = self.clean_glob(text.replace('\\',''))
619 616
620 617 if has_protectables:
621 618 # If we had protectables, we need to revert our changes to the
622 619 # beginning of filename so that we don't double-write the part
623 620 # of the filename we have so far
624 621 len_lsplit = len(lsplit)
625 622 matches = [text_prefix + text0 +
626 623 protect_filename(f[len_lsplit:]) for f in m0]
627 624 else:
628 625 if open_quotes:
629 626 # if we have a string with an open quote, we don't need to
630 627 # protect the names at all (and we _shouldn't_, as it
631 628 # would cause bugs when the filesystem call is made).
632 629 matches = m0
633 630 else:
634 631 matches = [text_prefix +
635 632 protect_filename(f) for f in m0]
636 633
637 634 #io.rprint('mm', matches) # dbg
638 635
639 636 # Mark directories in input list by appending '/' to their names.
640 637 matches = [x+'/' if os.path.isdir(x) else x for x in matches]
641 638 return matches
642 639
643 640 def magic_matches(self, text):
644 641 """Match magics"""
645 642 #print 'Completer->magic_matches:',text,'lb',self.text_until_cursor # dbg
646 643 # Get all shell magics now rather than statically, so magics loaded at
647 644 # runtime show up too.
648 645 lsm = self.shell.magics_manager.lsmagic()
649 646 line_magics = lsm['line']
650 647 cell_magics = lsm['cell']
651 648 pre = self.magic_escape
652 649 pre2 = pre+pre
653 650
654 651 # Completion logic:
655 652 # - user gives %%: only do cell magics
656 653 # - user gives %: do both line and cell magics
657 654 # - no prefix: do both
658 655 # In other words, line magics are skipped if the user gives %% explicitly
659 656 bare_text = text.lstrip(pre)
660 657 comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)]
661 658 if not text.startswith(pre2):
662 659 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
663 660 return comp
664 661
665 662 def python_matches(self,text):
666 663 """Match attributes or global python names"""
667 664
668 665 #io.rprint('Completer->python_matches, txt=%r' % text) # dbg
669 666 if "." in text:
670 667 try:
671 668 matches = self.attr_matches(text)
672 669 if text.endswith('.') and self.omit__names:
673 670 if self.omit__names == 1:
674 671 # true if txt is _not_ a __ name, false otherwise:
675 672 no__name = (lambda txt:
676 673 re.match(r'.*\.__.*?__',txt) is None)
677 674 else:
678 675 # true if txt is _not_ a _ name, false otherwise:
679 676 no__name = (lambda txt:
680 677 re.match(r'.*\._.*?',txt) is None)
681 678 matches = filter(no__name, matches)
682 679 except NameError:
683 680 # catches <undefined attributes>.<tab>
684 681 matches = []
685 682 else:
686 683 matches = self.global_matches(text)
687 684
688 685 return matches
689 686
690 687 def _default_arguments_from_docstring(self, doc):
691 688 """Parse the first line of docstring for call signature.
692 689
693 690 Docstring should be of the form 'min(iterable[, key=func])\n'.
694 691 It can also parse cython docstring of the form
695 692 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
696 693 """
697 694 if doc is None:
698 695 return []
699 696
700 697 #care only the firstline
701 698 line = doc.lstrip().splitlines()[0]
702 699
703 700 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
704 701 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
705 702 sig = self.docstring_sig_re.search(line)
706 703 if sig is None:
707 704 return []
708 705 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
709 706 sig = sig.groups()[0].split(',')
710 707 ret = []
711 708 for s in sig:
712 709 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
713 710 ret += self.docstring_kwd_re.findall(s)
714 711 return ret
715 712
716 713 def _default_arguments(self, obj):
717 714 """Return the list of default arguments of obj if it is callable,
718 715 or empty list otherwise."""
719 716 call_obj = obj
720 717 ret = []
721 718 if inspect.isbuiltin(obj):
722 719 pass
723 720 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
724 721 if inspect.isclass(obj):
725 722 #for cython embededsignature=True the constructor docstring
726 723 #belongs to the object itself not __init__
727 724 ret += self._default_arguments_from_docstring(
728 725 getattr(obj, '__doc__', ''))
729 726 # for classes, check for __init__,__new__
730 727 call_obj = (getattr(obj, '__init__', None) or
731 728 getattr(obj, '__new__', None))
732 729 # for all others, check if they are __call__able
733 730 elif hasattr(obj, '__call__'):
734 731 call_obj = obj.__call__
735 732
736 733 ret += self._default_arguments_from_docstring(
737 734 getattr(call_obj, '__doc__', ''))
738 735
739 736 try:
740 737 args,_,_1,defaults = inspect.getargspec(call_obj)
741 738 if defaults:
742 739 ret+=args[-len(defaults):]
743 740 except TypeError:
744 741 pass
745 742
746 743 return list(set(ret))
747 744
748 745 def python_func_kw_matches(self,text):
749 746 """Match named parameters (kwargs) of the last open function"""
750 747
751 748 if "." in text: # a parameter cannot be dotted
752 749 return []
753 750 try: regexp = self.__funcParamsRegex
754 751 except AttributeError:
755 752 regexp = self.__funcParamsRegex = re.compile(r'''
756 753 '.*?(?<!\\)' | # single quoted strings or
757 754 ".*?(?<!\\)" | # double quoted strings or
758 755 \w+ | # identifier
759 756 \S # other characters
760 757 ''', re.VERBOSE | re.DOTALL)
761 758 # 1. find the nearest identifier that comes before an unclosed
762 759 # parenthesis before the cursor
763 760 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
764 761 tokens = regexp.findall(self.text_until_cursor)
765 762 tokens.reverse()
766 763 iterTokens = iter(tokens); openPar = 0
767 764
768 765 for token in iterTokens:
769 766 if token == ')':
770 767 openPar -= 1
771 768 elif token == '(':
772 769 openPar += 1
773 770 if openPar > 0:
774 771 # found the last unclosed parenthesis
775 772 break
776 773 else:
777 774 return []
778 775 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
779 776 ids = []
780 777 isId = re.compile(r'\w+$').match
781 778
782 779 while True:
783 780 try:
784 781 ids.append(next(iterTokens))
785 782 if not isId(ids[-1]):
786 783 ids.pop(); break
787 784 if not next(iterTokens) == '.':
788 785 break
789 786 except StopIteration:
790 787 break
791 788 # lookup the candidate callable matches either using global_matches
792 789 # or attr_matches for dotted names
793 790 if len(ids) == 1:
794 791 callableMatches = self.global_matches(ids[0])
795 792 else:
796 793 callableMatches = self.attr_matches('.'.join(ids[::-1]))
797 794 argMatches = []
798 795 for callableMatch in callableMatches:
799 796 try:
800 797 namedArgs = self._default_arguments(eval(callableMatch,
801 798 self.namespace))
802 799 except:
803 800 continue
804 801
805 802 for namedArg in namedArgs:
806 803 if namedArg.startswith(text):
807 804 argMatches.append("%s=" %namedArg)
808 805 return argMatches
809 806
810 807 def dispatch_custom_completer(self, text):
811 808 #io.rprint("Custom! '%s' %s" % (text, self.custom_completers)) # dbg
812 809 line = self.line_buffer
813 810 if not line.strip():
814 811 return None
815 812
816 813 # Create a little structure to pass all the relevant information about
817 814 # the current completion to any custom completer.
818 815 event = Bunch()
819 816 event.line = line
820 817 event.symbol = text
821 818 cmd = line.split(None,1)[0]
822 819 event.command = cmd
823 820 event.text_until_cursor = self.text_until_cursor
824 821
825 822 #print "\ncustom:{%s]\n" % event # dbg
826 823
827 824 # for foo etc, try also to find completer for %foo
828 825 if not cmd.startswith(self.magic_escape):
829 826 try_magic = self.custom_completers.s_matches(
830 827 self.magic_escape + cmd)
831 828 else:
832 829 try_magic = []
833 830
834 831 for c in itertools.chain(self.custom_completers.s_matches(cmd),
835 832 try_magic,
836 833 self.custom_completers.flat_matches(self.text_until_cursor)):
837 834 #print "try",c # dbg
838 835 try:
839 836 res = c(event)
840 837 if res:
841 838 # first, try case sensitive match
842 839 withcase = [r for r in res if r.startswith(text)]
843 840 if withcase:
844 841 return withcase
845 842 # if none, then case insensitive ones are ok too
846 843 text_low = text.lower()
847 844 return [r for r in res if r.lower().startswith(text_low)]
848 845 except TryNext:
849 846 pass
850 847
851 848 return None
852 849
853 850 def complete(self, text=None, line_buffer=None, cursor_pos=None):
854 851 """Find completions for the given text and line context.
855 852
856 853 This is called successively with state == 0, 1, 2, ... until it
857 854 returns None. The completion should begin with 'text'.
858 855
859 856 Note that both the text and the line_buffer are optional, but at least
860 857 one of them must be given.
861 858
862 859 Parameters
863 860 ----------
864 861 text : string, optional
865 862 Text to perform the completion on. If not given, the line buffer
866 863 is split using the instance's CompletionSplitter object.
867 864
868 865 line_buffer : string, optional
869 866 If not given, the completer attempts to obtain the current line
870 867 buffer via readline. This keyword allows clients which are
871 868 requesting for text completions in non-readline contexts to inform
872 869 the completer of the entire text.
873 870
874 871 cursor_pos : int, optional
875 872 Index of the cursor in the full line buffer. Should be provided by
876 873 remote frontends where kernel has no access to frontend state.
877 874
878 875 Returns
879 876 -------
880 877 text : str
881 878 Text that was actually used in the completion.
882 879
883 880 matches : list
884 881 A list of completion matches.
885 882 """
886 883 #io.rprint('\nCOMP1 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
887 884
888 885 # if the cursor position isn't given, the only sane assumption we can
889 886 # make is that it's at the end of the line (the common case)
890 887 if cursor_pos is None:
891 888 cursor_pos = len(line_buffer) if text is None else len(text)
892 889
893 890 # if text is either None or an empty string, rely on the line buffer
894 891 if not text:
895 892 text = self.splitter.split_line(line_buffer, cursor_pos)
896 893
897 894 # If no line buffer is given, assume the input text is all there was
898 895 if line_buffer is None:
899 896 line_buffer = text
900 897
901 898 self.line_buffer = line_buffer
902 899 self.text_until_cursor = self.line_buffer[:cursor_pos]
903 900 #io.rprint('COMP2 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
904 901
905 902 # Start with a clean slate of completions
906 903 self.matches[:] = []
907 904 custom_res = self.dispatch_custom_completer(text)
908 905 if custom_res is not None:
909 906 # did custom completers produce something?
910 907 self.matches = custom_res
911 908 else:
912 909 # Extend the list of completions with the results of each
913 910 # matcher, so we return results to the user from all
914 911 # namespaces.
915 912 if self.merge_completions:
916 913 self.matches = []
917 914 for matcher in self.matchers:
918 915 try:
919 916 self.matches.extend(matcher(text))
920 917 except:
921 918 # Show the ugly traceback if the matcher causes an
922 919 # exception, but do NOT crash the kernel!
923 920 sys.excepthook(*sys.exc_info())
924 921 else:
925 922 for matcher in self.matchers:
926 923 self.matches = matcher(text)
927 924 if self.matches:
928 925 break
929 926 # FIXME: we should extend our api to return a dict with completions for
930 927 # different types of objects. The rlcomplete() method could then
931 928 # simply collapse the dict into a list for readline, but we'd have
932 929 # richer completion semantics in other evironments.
933 930
934 931 # use penalize_magics_key to put magics after variables with same name
935 932 self.matches = sorted(set(self.matches), key=penalize_magics_key)
936 933
937 934 #io.rprint('COMP TEXT, MATCHES: %r, %r' % (text, self.matches)) # dbg
938 935 return text, self.matches
939 936
940 937 def rlcomplete(self, text, state):
941 938 """Return the state-th possible completion for 'text'.
942 939
943 940 This is called successively with state == 0, 1, 2, ... until it
944 941 returns None. The completion should begin with 'text'.
945 942
946 943 Parameters
947 944 ----------
948 945 text : string
949 946 Text to perform the completion on.
950 947
951 948 state : int
952 949 Counter used by readline.
953 950 """
954 951 if state==0:
955 952
956 953 self.line_buffer = line_buffer = self.readline.get_line_buffer()
957 954 cursor_pos = self.readline.get_endidx()
958 955
959 956 #io.rprint("\nRLCOMPLETE: %r %r %r" %
960 957 # (text, line_buffer, cursor_pos) ) # dbg
961 958
962 959 # if there is only a tab on a line with only whitespace, instead of
963 960 # the mostly useless 'do you want to see all million completions'
964 961 # message, just do the right thing and give the user his tab!
965 962 # Incidentally, this enables pasting of tabbed text from an editor
966 963 # (as long as autoindent is off).
967 964
968 965 # It should be noted that at least pyreadline still shows file
969 966 # completions - is there a way around it?
970 967
971 968 # don't apply this on 'dumb' terminals, such as emacs buffers, so
972 969 # we don't interfere with their own tab-completion mechanism.
973 970 if not (self.dumb_terminal or line_buffer.strip()):
974 971 self.readline.insert_text('\t')
975 972 sys.stdout.flush()
976 973 return None
977 974
978 975 # Note: debugging exceptions that may occur in completion is very
979 976 # tricky, because readline unconditionally silences them. So if
980 977 # during development you suspect a bug in the completion code, turn
981 978 # this flag on temporarily by uncommenting the second form (don't
982 979 # flip the value in the first line, as the '# dbg' marker can be
983 980 # automatically detected and is used elsewhere).
984 981 DEBUG = False
985 982 #DEBUG = True # dbg
986 983 if DEBUG:
987 984 try:
988 985 self.complete(text, line_buffer, cursor_pos)
989 986 except:
990 987 import traceback; traceback.print_exc()
991 988 else:
992 989 # The normal production version is here
993 990
994 991 # This method computes the self.matches array
995 992 self.complete(text, line_buffer, cursor_pos)
996 993
997 994 try:
998 995 return self.matches[state]
999 996 except IndexError:
1000 997 return None
@@ -1,440 +1,442 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Classes for handling input/output prompts.
3 3
4 4 Authors:
5 5
6 6 * Fernando Perez
7 7 * Brian Granger
8 8 * Thomas Kluyver
9 9 """
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Copyright (C) 2008-2011 The IPython Development Team
13 13 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
14 14 #
15 15 # Distributed under the terms of the BSD License. The full license is in
16 16 # the file COPYING, distributed as part of this software.
17 17 #-----------------------------------------------------------------------------
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Imports
21 21 #-----------------------------------------------------------------------------
22 22
23 23 import os
24 24 import re
25 25 import socket
26 26 import sys
27 27 import time
28 28
29 29 from string import Formatter
30 30
31 31 from IPython.config.configurable import Configurable
32 32 from IPython.core import release
33 33 from IPython.utils import coloransi, py3compat
34 34 from IPython.utils.traitlets import (Unicode, Instance, Dict, Bool, Int)
35 35
36 36 #-----------------------------------------------------------------------------
37 37 # Color schemes for prompts
38 38 #-----------------------------------------------------------------------------
39 39
40 40 InputColors = coloransi.InputTermColors # just a shorthand
41 41 Colors = coloransi.TermColors # just a shorthand
42 42
43 43 color_lists = dict(normal=Colors(), inp=InputColors(), nocolor=coloransi.NoColors())
44 44
45 45 PColNoColors = coloransi.ColorScheme(
46 46 'NoColor',
47 47 in_prompt = InputColors.NoColor, # Input prompt
48 48 in_number = InputColors.NoColor, # Input prompt number
49 49 in_prompt2 = InputColors.NoColor, # Continuation prompt
50 50 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
51 51
52 52 out_prompt = Colors.NoColor, # Output prompt
53 53 out_number = Colors.NoColor, # Output prompt number
54 54
55 55 normal = Colors.NoColor # color off (usu. Colors.Normal)
56 56 )
57 57
58 58 # make some schemes as instances so we can copy them for modification easily:
59 59 PColLinux = coloransi.ColorScheme(
60 60 'Linux',
61 61 in_prompt = InputColors.Green,
62 62 in_number = InputColors.LightGreen,
63 63 in_prompt2 = InputColors.Green,
64 64 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
65 65
66 66 out_prompt = Colors.Red,
67 67 out_number = Colors.LightRed,
68 68
69 69 normal = Colors.Normal
70 70 )
71 71
72 72 # Slightly modified Linux for light backgrounds
73 73 PColLightBG = PColLinux.copy('LightBG')
74 74
75 75 PColLightBG.colors.update(
76 76 in_prompt = InputColors.Blue,
77 77 in_number = InputColors.LightBlue,
78 78 in_prompt2 = InputColors.Blue
79 79 )
80 80
81 81 #-----------------------------------------------------------------------------
82 82 # Utilities
83 83 #-----------------------------------------------------------------------------
84 84
85 85 class LazyEvaluate(object):
86 86 """This is used for formatting strings with values that need to be updated
87 87 at that time, such as the current time or working directory."""
88 88 def __init__(self, func, *args, **kwargs):
89 89 self.func = func
90 90 self.args = args
91 91 self.kwargs = kwargs
92 92
93 93 def __call__(self, **kwargs):
94 94 self.kwargs.update(kwargs)
95 95 return self.func(*self.args, **self.kwargs)
96 96
97 97 def __str__(self):
98 98 return str(self())
99 99
100 100 def __unicode__(self):
101 101 return py3compat.unicode_type(self())
102 102
103 103 def __format__(self, format_spec):
104 104 return format(self(), format_spec)
105 105
106 106 def multiple_replace(dict, text):
107 107 """ Replace in 'text' all occurences of any key in the given
108 108 dictionary by its corresponding value. Returns the new string."""
109 109
110 110 # Function by Xavier Defrang, originally found at:
111 111 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
112 112
113 113 # Create a regular expression from the dictionary keys
114 114 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
115 115 # For each match, look-up corresponding value in dictionary
116 116 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
117 117
118 118 #-----------------------------------------------------------------------------
119 119 # Special characters that can be used in prompt templates, mainly bash-like
120 120 #-----------------------------------------------------------------------------
121 121
122 122 # If $HOME isn't defined (Windows), make it an absurd string so that it can
123 123 # never be expanded out into '~'. Basically anything which can never be a
124 124 # reasonable directory name will do, we just want the $HOME -> '~' operation
125 125 # to become a no-op. We pre-compute $HOME here so it's not done on every
126 126 # prompt call.
127 127
128 128 # FIXME:
129 129
130 130 # - This should be turned into a class which does proper namespace management,
131 131 # since the prompt specials need to be evaluated in a certain namespace.
132 132 # Currently it's just globals, which need to be managed manually by code
133 133 # below.
134 134
135 135 # - I also need to split up the color schemes from the prompt specials
136 136 # somehow. I don't have a clean design for that quite yet.
137 137
138 138 HOME = py3compat.str_to_unicode(os.environ.get("HOME","//////:::::ZZZZZ,,,~~~"))
139 139
140 140 # This is needed on FreeBSD, and maybe other systems which symlink /home to
141 141 # /usr/home, but retain the $HOME variable as pointing to /home
142 142 HOME = os.path.realpath(HOME)
143 143
144 144 # We precompute a few more strings here for the prompt_specials, which are
145 145 # fixed once ipython starts. This reduces the runtime overhead of computing
146 146 # prompt strings.
147 147 USER = py3compat.str_to_unicode(os.environ.get("USER",''))
148 148 HOSTNAME = py3compat.str_to_unicode(socket.gethostname())
149 149 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
150 150
151 # IronPython doesn't currently have os.getuid() even if
152 # os.name == 'posix'; 2/8/2014
151 153 ROOT_SYMBOL = "#" if (os.name=='nt' or sys.platform=='cli' or os.getuid()==0) else "$"
152 154
153 155 prompt_abbreviations = {
154 156 # Prompt/history count
155 157 '%n' : '{color.number}' '{count}' '{color.prompt}',
156 158 r'\#': '{color.number}' '{count}' '{color.prompt}',
157 159 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
158 160 # can get numbers displayed in whatever color they want.
159 161 r'\N': '{count}',
160 162
161 163 # Prompt/history count, with the actual digits replaced by dots. Used
162 164 # mainly in continuation prompts (prompt_in2)
163 165 r'\D': '{dots}',
164 166
165 167 # Current time
166 168 r'\T' : '{time}',
167 169 # Current working directory
168 170 r'\w': '{cwd}',
169 171 # Basename of current working directory.
170 172 # (use os.sep to make this portable across OSes)
171 173 r'\W' : '{cwd_last}',
172 174 # These X<N> are an extension to the normal bash prompts. They return
173 175 # N terms of the path, after replacing $HOME with '~'
174 176 r'\X0': '{cwd_x[0]}',
175 177 r'\X1': '{cwd_x[1]}',
176 178 r'\X2': '{cwd_x[2]}',
177 179 r'\X3': '{cwd_x[3]}',
178 180 r'\X4': '{cwd_x[4]}',
179 181 r'\X5': '{cwd_x[5]}',
180 182 # Y<N> are similar to X<N>, but they show '~' if it's the directory
181 183 # N+1 in the list. Somewhat like %cN in tcsh.
182 184 r'\Y0': '{cwd_y[0]}',
183 185 r'\Y1': '{cwd_y[1]}',
184 186 r'\Y2': '{cwd_y[2]}',
185 187 r'\Y3': '{cwd_y[3]}',
186 188 r'\Y4': '{cwd_y[4]}',
187 189 r'\Y5': '{cwd_y[5]}',
188 190 # Hostname up to first .
189 191 r'\h': HOSTNAME_SHORT,
190 192 # Full hostname
191 193 r'\H': HOSTNAME,
192 194 # Username of current user
193 195 r'\u': USER,
194 196 # Escaped '\'
195 197 '\\\\': '\\',
196 198 # Newline
197 199 r'\n': '\n',
198 200 # Carriage return
199 201 r'\r': '\r',
200 202 # Release version
201 203 r'\v': release.version,
202 204 # Root symbol ($ or #)
203 205 r'\$': ROOT_SYMBOL,
204 206 }
205 207
206 208 #-----------------------------------------------------------------------------
207 209 # More utilities
208 210 #-----------------------------------------------------------------------------
209 211
210 212 def cwd_filt(depth):
211 213 """Return the last depth elements of the current working directory.
212 214
213 215 $HOME is always replaced with '~'.
214 216 If depth==0, the full path is returned."""
215 217
216 218 cwd = py3compat.getcwd().replace(HOME,"~")
217 219 out = os.sep.join(cwd.split(os.sep)[-depth:])
218 220 return out or os.sep
219 221
220 222 def cwd_filt2(depth):
221 223 """Return the last depth elements of the current working directory.
222 224
223 225 $HOME is always replaced with '~'.
224 226 If depth==0, the full path is returned."""
225 227
226 228 full_cwd = py3compat.getcwd()
227 229 cwd = full_cwd.replace(HOME,"~").split(os.sep)
228 230 if '~' in cwd and len(cwd) == depth+1:
229 231 depth += 1
230 232 drivepart = ''
231 233 if sys.platform == 'win32' and len(cwd) > depth:
232 234 drivepart = os.path.splitdrive(full_cwd)[0]
233 235 out = drivepart + '/'.join(cwd[-depth:])
234 236
235 237 return out or os.sep
236 238
237 239 #-----------------------------------------------------------------------------
238 240 # Prompt classes
239 241 #-----------------------------------------------------------------------------
240 242
241 243 lazily_evaluate = {'time': LazyEvaluate(time.strftime, "%H:%M:%S"),
242 244 'cwd': LazyEvaluate(py3compat.getcwd),
243 245 'cwd_last': LazyEvaluate(lambda: py3compat.getcwd().split(os.sep)[-1]),
244 246 'cwd_x': [LazyEvaluate(lambda: py3compat.getcwd().replace(HOME,"~"))] +\
245 247 [LazyEvaluate(cwd_filt, x) for x in range(1,6)],
246 248 'cwd_y': [LazyEvaluate(cwd_filt2, x) for x in range(6)]
247 249 }
248 250
249 251 def _lenlastline(s):
250 252 """Get the length of the last line. More intelligent than
251 253 len(s.splitlines()[-1]).
252 254 """
253 255 if not s or s.endswith(('\n', '\r')):
254 256 return 0
255 257 return len(s.splitlines()[-1])
256 258
257 259
258 260 class UserNSFormatter(Formatter):
259 261 """A Formatter that falls back on a shell's user_ns and __builtins__ for name resolution"""
260 262 def __init__(self, shell):
261 263 self.shell = shell
262 264
263 265 def get_value(self, key, args, kwargs):
264 266 # try regular formatting first:
265 267 try:
266 268 return Formatter.get_value(self, key, args, kwargs)
267 269 except Exception:
268 270 pass
269 271 # next, look in user_ns and builtins:
270 272 for container in (self.shell.user_ns, __builtins__):
271 273 if key in container:
272 274 return container[key]
273 275 # nothing found, put error message in its place
274 276 return "<ERROR: '%s' not found>" % key
275 277
276 278
277 279 class PromptManager(Configurable):
278 280 """This is the primary interface for producing IPython's prompts."""
279 281 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
280 282
281 283 color_scheme_table = Instance(coloransi.ColorSchemeTable)
282 284 color_scheme = Unicode('Linux', config=True)
283 285 def _color_scheme_changed(self, name, new_value):
284 286 self.color_scheme_table.set_active_scheme(new_value)
285 287 for pname in ['in', 'in2', 'out', 'rewrite']:
286 288 # We need to recalculate the number of invisible characters
287 289 self.update_prompt(pname)
288 290
289 291 lazy_evaluate_fields = Dict(help="""
290 292 This maps field names used in the prompt templates to functions which
291 293 will be called when the prompt is rendered. This allows us to include
292 294 things like the current time in the prompts. Functions are only called
293 295 if they are used in the prompt.
294 296 """)
295 297 def _lazy_evaluate_fields_default(self): return lazily_evaluate.copy()
296 298
297 299 in_template = Unicode('In [\\#]: ', config=True,
298 300 help="Input prompt. '\\#' will be transformed to the prompt number")
299 301 in2_template = Unicode(' .\\D.: ', config=True,
300 302 help="Continuation prompt.")
301 303 out_template = Unicode('Out[\\#]: ', config=True,
302 304 help="Output prompt. '\\#' will be transformed to the prompt number")
303 305
304 306 justify = Bool(True, config=True, help="""
305 307 If True (default), each prompt will be right-aligned with the
306 308 preceding one.
307 309 """)
308 310
309 311 # We actually store the expanded templates here:
310 312 templates = Dict()
311 313
312 314 # The number of characters in the last prompt rendered, not including
313 315 # colour characters.
314 316 width = Int()
315 317 txtwidth = Int() # Not including right-justification
316 318
317 319 # The number of characters in each prompt which don't contribute to width
318 320 invisible_chars = Dict()
319 321 def _invisible_chars_default(self):
320 322 return {'in': 0, 'in2': 0, 'out': 0, 'rewrite':0}
321 323
322 324 def __init__(self, shell, **kwargs):
323 325 super(PromptManager, self).__init__(shell=shell, **kwargs)
324 326
325 327 # Prepare colour scheme table
326 328 self.color_scheme_table = coloransi.ColorSchemeTable([PColNoColors,
327 329 PColLinux, PColLightBG], self.color_scheme)
328 330
329 331 self._formatter = UserNSFormatter(shell)
330 332 # Prepare templates & numbers of invisible characters
331 333 self.update_prompt('in', self.in_template)
332 334 self.update_prompt('in2', self.in2_template)
333 335 self.update_prompt('out', self.out_template)
334 336 self.update_prompt('rewrite')
335 337 self.on_trait_change(self._update_prompt_trait, ['in_template',
336 338 'in2_template', 'out_template'])
337 339
338 340 def update_prompt(self, name, new_template=None):
339 341 """This is called when a prompt template is updated. It processes
340 342 abbreviations used in the prompt template (like \#) and calculates how
341 343 many invisible characters (ANSI colour escapes) the resulting prompt
342 344 contains.
343 345
344 346 It is also called for each prompt on changing the colour scheme. In both
345 347 cases, traitlets should take care of calling this automatically.
346 348 """
347 349 if new_template is not None:
348 350 self.templates[name] = multiple_replace(prompt_abbreviations, new_template)
349 351 # We count invisible characters (colour escapes) on the last line of the
350 352 # prompt, to calculate the width for lining up subsequent prompts.
351 353 invis_chars = _lenlastline(self._render(name, color=True)) - \
352 354 _lenlastline(self._render(name, color=False))
353 355 self.invisible_chars[name] = invis_chars
354 356
355 357 def _update_prompt_trait(self, traitname, new_template):
356 358 name = traitname[:-9] # Cut off '_template'
357 359 self.update_prompt(name, new_template)
358 360
359 361 def _render(self, name, color=True, **kwargs):
360 362 """Render but don't justify, or update the width or txtwidth attributes.
361 363 """
362 364 if name == 'rewrite':
363 365 return self._render_rewrite(color=color)
364 366
365 367 if color:
366 368 scheme = self.color_scheme_table.active_colors
367 369 if name=='out':
368 370 colors = color_lists['normal']
369 371 colors.number, colors.prompt, colors.normal = \
370 372 scheme.out_number, scheme.out_prompt, scheme.normal
371 373 else:
372 374 colors = color_lists['inp']
373 375 colors.number, colors.prompt, colors.normal = \
374 376 scheme.in_number, scheme.in_prompt, scheme.in_normal
375 377 if name=='in2':
376 378 colors.prompt = scheme.in_prompt2
377 379 else:
378 380 # No color
379 381 colors = color_lists['nocolor']
380 382 colors.number, colors.prompt, colors.normal = '', '', ''
381 383
382 384 count = self.shell.execution_count # Shorthand
383 385 # Build the dictionary to be passed to string formatting
384 386 fmtargs = dict(color=colors, count=count,
385 387 dots="."*len(str(count)),
386 388 width=self.width, txtwidth=self.txtwidth )
387 389 fmtargs.update(self.lazy_evaluate_fields)
388 390 fmtargs.update(kwargs)
389 391
390 392 # Prepare the prompt
391 393 prompt = colors.prompt + self.templates[name] + colors.normal
392 394
393 395 # Fill in required fields
394 396 return self._formatter.format(prompt, **fmtargs)
395 397
396 398 def _render_rewrite(self, color=True):
397 399 """Render the ---> rewrite prompt."""
398 400 if color:
399 401 scheme = self.color_scheme_table.active_colors
400 402 # We need a non-input version of these escapes
401 403 color_prompt = scheme.in_prompt.replace("\001","").replace("\002","")
402 404 color_normal = scheme.normal
403 405 else:
404 406 color_prompt, color_normal = '', ''
405 407
406 408 return color_prompt + "-> ".rjust(self.txtwidth, "-") + color_normal
407 409
408 410 def render(self, name, color=True, just=None, **kwargs):
409 411 """
410 412 Render the selected prompt.
411 413
412 414 Parameters
413 415 ----------
414 416 name : str
415 417 Which prompt to render. One of 'in', 'in2', 'out', 'rewrite'
416 418 color : bool
417 419 If True (default), include ANSI escape sequences for a coloured prompt.
418 420 just : bool
419 421 If True, justify the prompt to the width of the last prompt. The
420 422 default is stored in self.justify.
421 423 **kwargs :
422 424 Additional arguments will be passed to the string formatting operation,
423 425 so they can override the values that would otherwise fill in the
424 426 template.
425 427
426 428 Returns
427 429 -------
428 430 A string containing the rendered prompt.
429 431 """
430 432 res = self._render(name, color=color, **kwargs)
431 433
432 434 # Handle justification of prompt
433 435 invis_chars = self.invisible_chars[name] if color else 0
434 436 self.txtwidth = _lenlastline(res) - invis_chars
435 437 just = self.justify if (just is None) else just
436 438 # If the prompt spans more than one line, don't try to justify it:
437 439 if just and name != 'in' and ('\n' not in res) and ('\r' not in res):
438 440 res = res.rjust(self.width + invis_chars)
439 441 self.width = _lenlastline(res) - invis_chars
440 442 return res
@@ -1,221 +1,224 b''
1 1 ########################## LICENCE ###############################
2 2
3 3 # Copyright (c) 2005-2012, Michele Simionato
4 4 # All rights reserved.
5 5
6 6 # Redistribution and use in source and binary forms, with or without
7 7 # modification, are permitted provided that the following conditions are
8 8 # met:
9 9
10 10 # Redistributions of source code must retain the above copyright
11 11 # notice, this list of conditions and the following disclaimer.
12 12 # Redistributions in bytecode form must reproduce the above copyright
13 13 # notice, this list of conditions and the following disclaimer in
14 14 # the documentation and/or other materials provided with the
15 15 # distribution.
16 16
17 17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 21 # HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 22 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 23 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24 24 # OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 25 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26 26 # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27 27 # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
28 28 # DAMAGE.
29 29
30 30 """
31 31 Decorator module, see http://pypi.python.org/pypi/decorator
32 32 for the documentation.
33 33 """
34 34 from __future__ import print_function
35 35
36 36 __version__ = '3.3.3'
37 37
38 38 __all__ = ["decorator", "FunctionMaker", "partial"]
39 39
40 40 import sys, re, inspect
41 41
42 42 try:
43 43 from functools import partial
44 44 except ImportError: # for Python version < 2.5
45 45 class partial(object):
46 46 "A simple replacement of functools.partial"
47 47 def __init__(self, func, *args, **kw):
48 48 self.func = func
49 49 self.args = args
50 50 self.keywords = kw
51 51 def __call__(self, *otherargs, **otherkw):
52 52 kw = self.keywords.copy()
53 53 kw.update(otherkw)
54 54 return self.func(*(self.args + otherargs), **kw)
55 55
56 56 if sys.version >= '3':
57 57 from inspect import getfullargspec
58 58 else:
59 59 class getfullargspec(object):
60 60 "A quick and dirty replacement for getfullargspec for Python 2.X"
61 61 def __init__(self, f):
62 62 self.args, self.varargs, self.varkw, self.defaults = \
63 63 inspect.getargspec(f)
64 64 self.kwonlyargs = []
65 65 self.kwonlydefaults = None
66 66 def __iter__(self):
67 67 yield self.args
68 68 yield self.varargs
69 69 yield self.varkw
70 70 yield self.defaults
71 71
72 72 DEF = re.compile('\s*def\s*([_\w][_\w\d]*)\s*\(')
73 73
74 74 # basic functionality
75 75 class FunctionMaker(object):
76 76 """
77 77 An object with the ability to create functions with a given signature.
78 78 It has attributes name, doc, module, signature, defaults, dict and
79 79 methods update and make.
80 80 """
81 81 def __init__(self, func=None, name=None, signature=None,
82 82 defaults=None, doc=None, module=None, funcdict=None):
83 83 self.shortsignature = signature
84 84 if func:
85 85 # func can be a class or a callable, but not an instance method
86 86 self.name = func.__name__
87 87 if self.name == '<lambda>': # small hack for lambda functions
88 88 self.name = '_lambda_'
89 89 self.doc = func.__doc__
90 90 self.module = func.__module__
91 91 if inspect.isfunction(func):
92 92 argspec = getfullargspec(func)
93 93 self.annotations = getattr(func, '__annotations__', {})
94 94 for a in ('args', 'varargs', 'varkw', 'defaults', 'kwonlyargs',
95 95 'kwonlydefaults'):
96 96 setattr(self, a, getattr(argspec, a))
97 97 for i, arg in enumerate(self.args):
98 98 setattr(self, 'arg%d' % i, arg)
99 99 if sys.version < '3': # easy way
100 100 self.shortsignature = self.signature = \
101 101 inspect.formatargspec(
102 102 formatvalue=lambda val: "", *argspec)[1:-1]
103 103 else: # Python 3 way
104 104 self.signature = self.shortsignature = ', '.join(self.args)
105 105 if self.varargs:
106 106 self.signature += ', *' + self.varargs
107 107 self.shortsignature += ', *' + self.varargs
108 108 if self.kwonlyargs:
109 109 for a in self.kwonlyargs:
110 110 self.signature += ', %s=None' % a
111 111 self.shortsignature += ', %s=%s' % (a, a)
112 112 if self.varkw:
113 113 self.signature += ', **' + self.varkw
114 114 self.shortsignature += ', **' + self.varkw
115 115 self.dict = func.__dict__.copy()
116 116 # func=None happens when decorating a caller
117 117 if name:
118 118 self.name = name
119 119 if signature is not None:
120 120 self.signature = signature
121 121 if defaults:
122 122 self.defaults = defaults
123 123 if doc:
124 124 self.doc = doc
125 125 if module:
126 126 self.module = module
127 127 if funcdict:
128 128 self.dict = funcdict
129 129 # check existence required attributes
130 130 assert hasattr(self, 'name')
131 131 if not hasattr(self, 'signature'):
132 132 raise TypeError('You are decorating a non function: %s' % func)
133 133
134 134 def update(self, func, **kw):
135 135 "Update the signature of func with the data in self"
136 136 func.__name__ = self.name
137 137 func.__doc__ = getattr(self, 'doc', None)
138 138 func.__dict__ = getattr(self, 'dict', {})
139 139 func.__defaults__ = getattr(self, 'defaults', ())
140 140 func.__kwdefaults__ = getattr(self, 'kwonlydefaults', None)
141 141 func.__annotations__ = getattr(self, 'annotations', None)
142 callermodule = sys._getframe(3).f_globals.get('__name__', '?')
142 try:
143 callermodule = sys._getframe(3).f_globals.get('__name__', '?')
144 except AttributeError: # IronPython _getframe only exists with FullFrames
145 callermodule = '?'
143 146 func.__module__ = getattr(self, 'module', callermodule)
144 147 func.__dict__.update(kw)
145 148
146 149 def make(self, src_templ, evaldict=None, addsource=False, **attrs):
147 150 "Make a new function from a given template and update the signature"
148 151 src = src_templ % vars(self) # expand name and signature
149 152 evaldict = evaldict or {}
150 153 mo = DEF.match(src)
151 154 if mo is None:
152 155 raise SyntaxError('not a valid function template\n%s' % src)
153 156 name = mo.group(1) # extract the function name
154 157 names = set([name] + [arg.strip(' *') for arg in
155 158 self.shortsignature.split(',')])
156 159 for n in names:
157 160 if n in ('_func_', '_call_'):
158 161 raise NameError('%s is overridden in\n%s' % (n, src))
159 162 if not src.endswith('\n'): # add a newline just for safety
160 163 src += '\n' # this is needed in old versions of Python
161 164 try:
162 165 code = compile(src, '<string>', 'single')
163 166 # print >> sys.stderr, 'Compiling %s' % src
164 167 exec(code, evaldict)
165 168 except:
166 169 print('Error in generated code:', file=sys.stderr)
167 170 print(src, file=sys.stderr)
168 171 raise
169 172 func = evaldict[name]
170 173 if addsource:
171 174 attrs['__source__'] = src
172 175 self.update(func, **attrs)
173 176 return func
174 177
175 178 @classmethod
176 179 def create(cls, obj, body, evaldict, defaults=None,
177 180 doc=None, module=None, addsource=True, **attrs):
178 181 """
179 182 Create a function from the strings name, signature and body.
180 183 evaldict is the evaluation dictionary. If addsource is true an attribute
181 184 __source__ is added to the result. The attributes attrs are added,
182 185 if any.
183 186 """
184 187 if isinstance(obj, str): # "name(signature)"
185 188 name, rest = obj.strip().split('(', 1)
186 189 signature = rest[:-1] #strip a right parens
187 190 func = None
188 191 else: # a function
189 192 name = None
190 193 signature = None
191 194 func = obj
192 195 self = cls(func, name, signature, defaults, doc, module)
193 196 ibody = '\n'.join(' ' + line for line in body.splitlines())
194 197 return self.make('def %(name)s(%(signature)s):\n' + ibody,
195 198 evaldict, addsource, **attrs)
196 199
197 200 def decorator(caller, func=None):
198 201 """
199 202 decorator(caller) converts a caller function into a decorator;
200 203 decorator(caller, func) decorates a function using a caller.
201 204 """
202 205 if func is not None: # returns a decorated function
203 206 evaldict = func.__globals__.copy()
204 207 evaldict['_call_'] = caller
205 208 evaldict['_func_'] = func
206 209 return FunctionMaker.create(
207 210 func, "return _call_(_func_, %(shortsignature)s)",
208 211 evaldict, undecorated=func, __wrapped__=func)
209 212 else: # returns a decorator
210 213 if isinstance(caller, partial):
211 214 return partial(decorator, caller)
212 215 # otherwise assume caller is a function
213 216 first = inspect.getargspec(caller)[0][0] # first arg
214 217 evaldict = caller.__globals__.copy()
215 218 evaldict['_call_'] = caller
216 219 evaldict['decorator'] = decorator
217 220 return FunctionMaker.create(
218 221 '%s(%s)' % (caller.__name__, first),
219 222 'return decorator(_call_, %s)' % first,
220 223 evaldict, undecorated=caller, __wrapped__=caller,
221 224 doc=caller.__doc__, module=caller.__module__)
@@ -1,534 +1,534 b''
1 1 # coding: utf-8
2 2 """
3 3 Inputhook management for GUI event loop integration.
4 4 """
5 5
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (C) 2008-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 try:
18 18 import ctypes
19 19 except ImportError:
20 20 ctypes = None
21 except SystemError:
21 except SystemError: # IronPython issue, 2/8/2014
22 22 ctypes = None
23 23 import os
24 24 import sys
25 25 from distutils.version import LooseVersion as V
26 26
27 27 from IPython.utils.warn import warn
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Constants
31 31 #-----------------------------------------------------------------------------
32 32
33 33 # Constants for identifying the GUI toolkits.
34 34 GUI_WX = 'wx'
35 35 GUI_QT = 'qt'
36 36 GUI_QT4 = 'qt4'
37 37 GUI_GTK = 'gtk'
38 38 GUI_TK = 'tk'
39 39 GUI_OSX = 'osx'
40 40 GUI_GLUT = 'glut'
41 41 GUI_PYGLET = 'pyglet'
42 42 GUI_GTK3 = 'gtk3'
43 43 GUI_NONE = 'none' # i.e. disable
44 44
45 45 #-----------------------------------------------------------------------------
46 46 # Utilities
47 47 #-----------------------------------------------------------------------------
48 48
49 49 def _stdin_ready_posix():
50 50 """Return True if there's something to read on stdin (posix version)."""
51 51 infds, outfds, erfds = select.select([sys.stdin],[],[],0)
52 52 return bool(infds)
53 53
54 54 def _stdin_ready_nt():
55 55 """Return True if there's something to read on stdin (nt version)."""
56 56 return msvcrt.kbhit()
57 57
58 58 def _stdin_ready_other():
59 59 """Return True, assuming there's something to read on stdin."""
60 60 return True #
61 61
62 62
63 63 def _ignore_CTRL_C_posix():
64 64 """Ignore CTRL+C (SIGINT)."""
65 65 signal.signal(signal.SIGINT, signal.SIG_IGN)
66 66
67 67 def _allow_CTRL_C_posix():
68 68 """Take CTRL+C into account (SIGINT)."""
69 69 signal.signal(signal.SIGINT, signal.default_int_handler)
70 70
71 71 def _ignore_CTRL_C_other():
72 72 """Ignore CTRL+C (not implemented)."""
73 73 pass
74 74
75 75 def _allow_CTRL_C_other():
76 76 """Take CTRL+C into account (not implemented)."""
77 77 pass
78 78
79 79 if os.name == 'posix':
80 80 import select
81 81 import signal
82 82 stdin_ready = _stdin_ready_posix
83 83 ignore_CTRL_C = _ignore_CTRL_C_posix
84 84 allow_CTRL_C = _allow_CTRL_C_posix
85 85 elif os.name == 'nt':
86 86 import msvcrt
87 87 stdin_ready = _stdin_ready_nt
88 88 ignore_CTRL_C = _ignore_CTRL_C_other
89 89 allow_CTRL_C = _allow_CTRL_C_other
90 90 else:
91 91 stdin_ready = _stdin_ready_other
92 92 ignore_CTRL_C = _ignore_CTRL_C_other
93 93 allow_CTRL_C = _allow_CTRL_C_other
94 94
95 95
96 96 #-----------------------------------------------------------------------------
97 97 # Main InputHookManager class
98 98 #-----------------------------------------------------------------------------
99 99
100 100
101 101 class InputHookManager(object):
102 102 """Manage PyOS_InputHook for different GUI toolkits.
103 103
104 104 This class installs various hooks under ``PyOSInputHook`` to handle
105 105 GUI event loop integration.
106 106 """
107 107
108 108 def __init__(self):
109 109 if ctypes is None:
110 110 warn("IPython GUI event loop requires ctypes, %gui will not be available")
111 111 return
112 112 self.PYFUNC = ctypes.PYFUNCTYPE(ctypes.c_int)
113 113 self._apps = {}
114 114 self._reset()
115 115
116 116 def _reset(self):
117 117 self._callback_pyfunctype = None
118 118 self._callback = None
119 119 self._installed = False
120 120 self._current_gui = None
121 121
122 122 def get_pyos_inputhook(self):
123 123 """Return the current PyOS_InputHook as a ctypes.c_void_p."""
124 124 return ctypes.c_void_p.in_dll(ctypes.pythonapi,"PyOS_InputHook")
125 125
126 126 def get_pyos_inputhook_as_func(self):
127 127 """Return the current PyOS_InputHook as a ctypes.PYFUNCYPE."""
128 128 return self.PYFUNC.in_dll(ctypes.pythonapi,"PyOS_InputHook")
129 129
130 130 def set_inputhook(self, callback):
131 131 """Set PyOS_InputHook to callback and return the previous one."""
132 132 # On platforms with 'readline' support, it's all too likely to
133 133 # have a KeyboardInterrupt signal delivered *even before* an
134 134 # initial ``try:`` clause in the callback can be executed, so
135 135 # we need to disable CTRL+C in this situation.
136 136 ignore_CTRL_C()
137 137 self._callback = callback
138 138 self._callback_pyfunctype = self.PYFUNC(callback)
139 139 pyos_inputhook_ptr = self.get_pyos_inputhook()
140 140 original = self.get_pyos_inputhook_as_func()
141 141 pyos_inputhook_ptr.value = \
142 142 ctypes.cast(self._callback_pyfunctype, ctypes.c_void_p).value
143 143 self._installed = True
144 144 return original
145 145
146 146 def clear_inputhook(self, app=None):
147 147 """Set PyOS_InputHook to NULL and return the previous one.
148 148
149 149 Parameters
150 150 ----------
151 151 app : optional, ignored
152 152 This parameter is allowed only so that clear_inputhook() can be
153 153 called with a similar interface as all the ``enable_*`` methods. But
154 154 the actual value of the parameter is ignored. This uniform interface
155 155 makes it easier to have user-level entry points in the main IPython
156 156 app like :meth:`enable_gui`."""
157 157 pyos_inputhook_ptr = self.get_pyos_inputhook()
158 158 original = self.get_pyos_inputhook_as_func()
159 159 pyos_inputhook_ptr.value = ctypes.c_void_p(None).value
160 160 allow_CTRL_C()
161 161 self._reset()
162 162 return original
163 163
164 164 def clear_app_refs(self, gui=None):
165 165 """Clear IPython's internal reference to an application instance.
166 166
167 167 Whenever we create an app for a user on qt4 or wx, we hold a
168 168 reference to the app. This is needed because in some cases bad things
169 169 can happen if a user doesn't hold a reference themselves. This
170 170 method is provided to clear the references we are holding.
171 171
172 172 Parameters
173 173 ----------
174 174 gui : None or str
175 175 If None, clear all app references. If ('wx', 'qt4') clear
176 176 the app for that toolkit. References are not held for gtk or tk
177 177 as those toolkits don't have the notion of an app.
178 178 """
179 179 if gui is None:
180 180 self._apps = {}
181 181 elif gui in self._apps:
182 182 del self._apps[gui]
183 183
184 184 def enable_wx(self, app=None):
185 185 """Enable event loop integration with wxPython.
186 186
187 187 Parameters
188 188 ----------
189 189 app : WX Application, optional.
190 190 Running application to use. If not given, we probe WX for an
191 191 existing application object, and create a new one if none is found.
192 192
193 193 Notes
194 194 -----
195 195 This methods sets the ``PyOS_InputHook`` for wxPython, which allows
196 196 the wxPython to integrate with terminal based applications like
197 197 IPython.
198 198
199 199 If ``app`` is not given we probe for an existing one, and return it if
200 200 found. If no existing app is found, we create an :class:`wx.App` as
201 201 follows::
202 202
203 203 import wx
204 204 app = wx.App(redirect=False, clearSigInt=False)
205 205 """
206 206 import wx
207 207
208 208 wx_version = V(wx.__version__).version
209 209
210 210 if wx_version < [2, 8]:
211 211 raise ValueError("requires wxPython >= 2.8, but you have %s" % wx.__version__)
212 212
213 213 from IPython.lib.inputhookwx import inputhook_wx
214 214 self.set_inputhook(inputhook_wx)
215 215 self._current_gui = GUI_WX
216 216 import wx
217 217 if app is None:
218 218 app = wx.GetApp()
219 219 if app is None:
220 220 app = wx.App(redirect=False, clearSigInt=False)
221 221 app._in_event_loop = True
222 222 self._apps[GUI_WX] = app
223 223 return app
224 224
225 225 def disable_wx(self):
226 226 """Disable event loop integration with wxPython.
227 227
228 228 This merely sets PyOS_InputHook to NULL.
229 229 """
230 230 if GUI_WX in self._apps:
231 231 self._apps[GUI_WX]._in_event_loop = False
232 232 self.clear_inputhook()
233 233
234 234 def enable_qt4(self, app=None):
235 235 """Enable event loop integration with PyQt4.
236 236
237 237 Parameters
238 238 ----------
239 239 app : Qt Application, optional.
240 240 Running application to use. If not given, we probe Qt for an
241 241 existing application object, and create a new one if none is found.
242 242
243 243 Notes
244 244 -----
245 245 This methods sets the PyOS_InputHook for PyQt4, which allows
246 246 the PyQt4 to integrate with terminal based applications like
247 247 IPython.
248 248
249 249 If ``app`` is not given we probe for an existing one, and return it if
250 250 found. If no existing app is found, we create an :class:`QApplication`
251 251 as follows::
252 252
253 253 from PyQt4 import QtCore
254 254 app = QtGui.QApplication(sys.argv)
255 255 """
256 256 from IPython.lib.inputhookqt4 import create_inputhook_qt4
257 257 app, inputhook_qt4 = create_inputhook_qt4(self, app)
258 258 self.set_inputhook(inputhook_qt4)
259 259
260 260 self._current_gui = GUI_QT4
261 261 app._in_event_loop = True
262 262 self._apps[GUI_QT4] = app
263 263 return app
264 264
265 265 def disable_qt4(self):
266 266 """Disable event loop integration with PyQt4.
267 267
268 268 This merely sets PyOS_InputHook to NULL.
269 269 """
270 270 if GUI_QT4 in self._apps:
271 271 self._apps[GUI_QT4]._in_event_loop = False
272 272 self.clear_inputhook()
273 273
274 274 def enable_gtk(self, app=None):
275 275 """Enable event loop integration with PyGTK.
276 276
277 277 Parameters
278 278 ----------
279 279 app : ignored
280 280 Ignored, it's only a placeholder to keep the call signature of all
281 281 gui activation methods consistent, which simplifies the logic of
282 282 supporting magics.
283 283
284 284 Notes
285 285 -----
286 286 This methods sets the PyOS_InputHook for PyGTK, which allows
287 287 the PyGTK to integrate with terminal based applications like
288 288 IPython.
289 289 """
290 290 import gtk
291 291 try:
292 292 gtk.set_interactive(True)
293 293 self._current_gui = GUI_GTK
294 294 except AttributeError:
295 295 # For older versions of gtk, use our own ctypes version
296 296 from IPython.lib.inputhookgtk import inputhook_gtk
297 297 self.set_inputhook(inputhook_gtk)
298 298 self._current_gui = GUI_GTK
299 299
300 300 def disable_gtk(self):
301 301 """Disable event loop integration with PyGTK.
302 302
303 303 This merely sets PyOS_InputHook to NULL.
304 304 """
305 305 self.clear_inputhook()
306 306
307 307 def enable_tk(self, app=None):
308 308 """Enable event loop integration with Tk.
309 309
310 310 Parameters
311 311 ----------
312 312 app : toplevel :class:`Tkinter.Tk` widget, optional.
313 313 Running toplevel widget to use. If not given, we probe Tk for an
314 314 existing one, and create a new one if none is found.
315 315
316 316 Notes
317 317 -----
318 318 If you have already created a :class:`Tkinter.Tk` object, the only
319 319 thing done by this method is to register with the
320 320 :class:`InputHookManager`, since creating that object automatically
321 321 sets ``PyOS_InputHook``.
322 322 """
323 323 self._current_gui = GUI_TK
324 324 if app is None:
325 325 try:
326 326 from tkinter import Tk # Py 3
327 327 except ImportError:
328 328 from Tkinter import Tk # Py 2
329 329 app = Tk()
330 330 app.withdraw()
331 331 self._apps[GUI_TK] = app
332 332 return app
333 333
334 334 def disable_tk(self):
335 335 """Disable event loop integration with Tkinter.
336 336
337 337 This merely sets PyOS_InputHook to NULL.
338 338 """
339 339 self.clear_inputhook()
340 340
341 341
342 342 def enable_glut(self, app=None):
343 343 """ Enable event loop integration with GLUT.
344 344
345 345 Parameters
346 346 ----------
347 347
348 348 app : ignored
349 349 Ignored, it's only a placeholder to keep the call signature of all
350 350 gui activation methods consistent, which simplifies the logic of
351 351 supporting magics.
352 352
353 353 Notes
354 354 -----
355 355
356 356 This methods sets the PyOS_InputHook for GLUT, which allows the GLUT to
357 357 integrate with terminal based applications like IPython. Due to GLUT
358 358 limitations, it is currently not possible to start the event loop
359 359 without first creating a window. You should thus not create another
360 360 window but use instead the created one. See 'gui-glut.py' in the
361 361 docs/examples/lib directory.
362 362
363 363 The default screen mode is set to:
364 364 glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH
365 365 """
366 366
367 367 import OpenGL.GLUT as glut
368 368 from IPython.lib.inputhookglut import glut_display_mode, \
369 369 glut_close, glut_display, \
370 370 glut_idle, inputhook_glut
371 371
372 372 if GUI_GLUT not in self._apps:
373 373 glut.glutInit( sys.argv )
374 374 glut.glutInitDisplayMode( glut_display_mode )
375 375 # This is specific to freeglut
376 376 if bool(glut.glutSetOption):
377 377 glut.glutSetOption( glut.GLUT_ACTION_ON_WINDOW_CLOSE,
378 378 glut.GLUT_ACTION_GLUTMAINLOOP_RETURNS )
379 379 glut.glutCreateWindow( sys.argv[0] )
380 380 glut.glutReshapeWindow( 1, 1 )
381 381 glut.glutHideWindow( )
382 382 glut.glutWMCloseFunc( glut_close )
383 383 glut.glutDisplayFunc( glut_display )
384 384 glut.glutIdleFunc( glut_idle )
385 385 else:
386 386 glut.glutWMCloseFunc( glut_close )
387 387 glut.glutDisplayFunc( glut_display )
388 388 glut.glutIdleFunc( glut_idle)
389 389 self.set_inputhook( inputhook_glut )
390 390 self._current_gui = GUI_GLUT
391 391 self._apps[GUI_GLUT] = True
392 392
393 393
394 394 def disable_glut(self):
395 395 """Disable event loop integration with glut.
396 396
397 397 This sets PyOS_InputHook to NULL and set the display function to a
398 398 dummy one and set the timer to a dummy timer that will be triggered
399 399 very far in the future.
400 400 """
401 401 import OpenGL.GLUT as glut
402 402 from glut_support import glutMainLoopEvent
403 403
404 404 glut.glutHideWindow() # This is an event to be processed below
405 405 glutMainLoopEvent()
406 406 self.clear_inputhook()
407 407
408 408 def enable_pyglet(self, app=None):
409 409 """Enable event loop integration with pyglet.
410 410
411 411 Parameters
412 412 ----------
413 413 app : ignored
414 414 Ignored, it's only a placeholder to keep the call signature of all
415 415 gui activation methods consistent, which simplifies the logic of
416 416 supporting magics.
417 417
418 418 Notes
419 419 -----
420 420 This methods sets the ``PyOS_InputHook`` for pyglet, which allows
421 421 pyglet to integrate with terminal based applications like
422 422 IPython.
423 423
424 424 """
425 425 from IPython.lib.inputhookpyglet import inputhook_pyglet
426 426 self.set_inputhook(inputhook_pyglet)
427 427 self._current_gui = GUI_PYGLET
428 428 return app
429 429
430 430 def disable_pyglet(self):
431 431 """Disable event loop integration with pyglet.
432 432
433 433 This merely sets PyOS_InputHook to NULL.
434 434 """
435 435 self.clear_inputhook()
436 436
437 437 def enable_gtk3(self, app=None):
438 438 """Enable event loop integration with Gtk3 (gir bindings).
439 439
440 440 Parameters
441 441 ----------
442 442 app : ignored
443 443 Ignored, it's only a placeholder to keep the call signature of all
444 444 gui activation methods consistent, which simplifies the logic of
445 445 supporting magics.
446 446
447 447 Notes
448 448 -----
449 449 This methods sets the PyOS_InputHook for Gtk3, which allows
450 450 the Gtk3 to integrate with terminal based applications like
451 451 IPython.
452 452 """
453 453 from IPython.lib.inputhookgtk3 import inputhook_gtk3
454 454 self.set_inputhook(inputhook_gtk3)
455 455 self._current_gui = GUI_GTK
456 456
457 457 def disable_gtk3(self):
458 458 """Disable event loop integration with PyGTK.
459 459
460 460 This merely sets PyOS_InputHook to NULL.
461 461 """
462 462 self.clear_inputhook()
463 463
464 464 def current_gui(self):
465 465 """Return a string indicating the currently active GUI or None."""
466 466 return self._current_gui
467 467
468 468 inputhook_manager = InputHookManager()
469 469
470 470 enable_wx = inputhook_manager.enable_wx
471 471 disable_wx = inputhook_manager.disable_wx
472 472 enable_qt4 = inputhook_manager.enable_qt4
473 473 disable_qt4 = inputhook_manager.disable_qt4
474 474 enable_gtk = inputhook_manager.enable_gtk
475 475 disable_gtk = inputhook_manager.disable_gtk
476 476 enable_tk = inputhook_manager.enable_tk
477 477 disable_tk = inputhook_manager.disable_tk
478 478 enable_glut = inputhook_manager.enable_glut
479 479 disable_glut = inputhook_manager.disable_glut
480 480 enable_pyglet = inputhook_manager.enable_pyglet
481 481 disable_pyglet = inputhook_manager.disable_pyglet
482 482 enable_gtk3 = inputhook_manager.enable_gtk3
483 483 disable_gtk3 = inputhook_manager.disable_gtk3
484 484 clear_inputhook = inputhook_manager.clear_inputhook
485 485 set_inputhook = inputhook_manager.set_inputhook
486 486 current_gui = inputhook_manager.current_gui
487 487 clear_app_refs = inputhook_manager.clear_app_refs
488 488
489 489 guis = {None: clear_inputhook,
490 490 GUI_NONE: clear_inputhook,
491 491 GUI_OSX: lambda app=False: None,
492 492 GUI_TK: enable_tk,
493 493 GUI_GTK: enable_gtk,
494 494 GUI_WX: enable_wx,
495 495 GUI_QT: enable_qt4, # qt3 not supported
496 496 GUI_QT4: enable_qt4,
497 497 GUI_GLUT: enable_glut,
498 498 GUI_PYGLET: enable_pyglet,
499 499 GUI_GTK3: enable_gtk3,
500 500 }
501 501
502 502
503 503 # Convenience function to switch amongst them
504 504 def enable_gui(gui=None, app=None):
505 505 """Switch amongst GUI input hooks by name.
506 506
507 507 This is just a utility wrapper around the methods of the InputHookManager
508 508 object.
509 509
510 510 Parameters
511 511 ----------
512 512 gui : optional, string or None
513 513 If None (or 'none'), clears input hook, otherwise it must be one
514 514 of the recognized GUI names (see ``GUI_*`` constants in module).
515 515
516 516 app : optional, existing application object.
517 517 For toolkits that have the concept of a global app, you can supply an
518 518 existing one. If not given, the toolkit will be probed for one, and if
519 519 none is found, a new one will be created. Note that GTK does not have
520 520 this concept, and passing an app if ``gui=="GTK"`` will raise an error.
521 521
522 522 Returns
523 523 -------
524 524 The output of the underlying gui switch routine, typically the actual
525 525 PyOS_InputHook wrapper object or the GUI toolkit app created, if there was
526 526 one.
527 527 """
528 528 try:
529 529 gui_hook = guis[gui]
530 530 except KeyError:
531 531 e = "Invalid GUI request %r, valid ones are:%s" % (gui, guis.keys())
532 532 raise ValueError(e)
533 533 return gui_hook(app)
534 534
@@ -1,61 +1,60 b''
1 1 """
2 2 cli-specific implementation of process utilities.
3 3
4 4 cli - Common Language Infrastructure for IronPython. Code
5 5 can run on any operating system. Check os.name for os-
6 6 specific settings.
7 7
8 8 This file is only meant to be imported by process.py, not by end-users.
9 9 """
10 10
11 11 # Import cli libraries:
12 12 import clr
13 13 import System
14 14
15 15 # Import Python libraries:
16 16 import os
17 17
18 18 # Import IPython libraries:
19 19 from IPython.utils import py3compat
20 20 from ._process_common import arg_split
21 21
22 22 def _find_cmd(cmd):
23 23 """Find the full path to a command using which."""
24 os_path_sep = ":" if os.name == "posix" else ";"
25 paths = System.Environment.GetEnvironmentVariable("PATH").Split(os_path_sep)
24 paths = System.Environment.GetEnvironmentVariable("PATH").Split(os.pathsep)
26 25 for path in paths:
27 26 filename = os.path.join(path, cmd)
28 27 if System.IO.File.Exists(filename):
29 28 return py3compat.bytes_to_str(filename)
30 29 raise OSError("command %r not found" % cmd)
31 30
32 31 def system(cmd):
33 32 """
34 33 system(cmd) should work in a cli environment on Mac OSX, Linux,
35 34 and Windows
36 35 """
37 36 psi = System.Diagnostics.ProcessStartInfo(cmd)
38 37 psi.RedirectStandardOutput = True
39 38 psi.RedirectStandardError = True
40 39 psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal
41 40 psi.UseShellExecute = False
42 41 # Start up process:
43 42 reg = System.Diagnostics.Process.Start(psi)
44 43
45 44 def getoutput(cmd):
46 45 """
47 46 getoutput(cmd) should work in a cli environment on Mac OSX, Linux,
48 47 and Windows
49 48 """
50 49 psi = System.Diagnostics.ProcessStartInfo(cmd)
51 50 psi.RedirectStandardOutput = True
52 51 psi.RedirectStandardError = True
53 52 psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal
54 53 psi.UseShellExecute = False
55 54 # Start up process:
56 55 reg = System.Diagnostics.Process.Start(psi)
57 56 myOutput = reg.StandardOutput
58 57 output = myOutput.ReadToEnd()
59 58 myError = reg.StandardError
60 59 error = myError.ReadToEnd()
61 60 return output
General Comments 0
You need to be logged in to leave comments. Login now