##// END OF EJS Templates
Merging upstream
Brian Granger -
r2005:7eb8a846 merge
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -0,0 +1,37 b''
1 # encoding: utf-8
2 """
3 Test the LineFrontEnd
4 """
5
6 __docformat__ = "restructuredtext en"
7
8 #-------------------------------------------------------------------------------
9 # Copyright (C) 2008 The IPython Development Team
10 #
11 # Distributed under the terms of the BSD License. The full license is
12 # in the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
14
15 from IPython.frontend.linefrontendbase import LineFrontEndBase
16 from copy import deepcopy
17 import nose.tools as nt
18
19 class ConcreteLineFrontEnd(LineFrontEndBase):
20 """ A concrete class to test the LineFrontEndBase.
21 """
22 def capture_output(self):
23 pass
24
25 def release_output(self):
26 pass
27
28
29 def test_is_complete():
30 """ Tests line completion heuristic.
31 """
32 frontend = ConcreteLineFrontEnd()
33 yield nt.assert_true, not frontend.is_complete('for x in \\')
34 yield nt.assert_true, not frontend.is_complete('for x in (1, ):')
35 yield nt.assert_true, frontend.is_complete('for x in (1, ):\n pass')
36
37
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,2322 +1,2327 b''
1 # -*- coding: iso-8859-1 -*-
1 # -*- coding: iso-8859-1 -*-
2
2
3 """
3 """
4 ``ipipe`` provides classes to be used in an interactive Python session. Doing a
4 ``ipipe`` provides classes to be used in an interactive Python session. Doing a
5 ``from ipipe import *`` is the preferred way to do this. The name of all
5 ``from ipipe import *`` is the preferred way to do this. The name of all
6 objects imported this way starts with ``i`` to minimize collisions.
6 objects imported this way starts with ``i`` to minimize collisions.
7
7
8 ``ipipe`` supports "pipeline expressions", which is something resembling Unix
8 ``ipipe`` supports "pipeline expressions", which is something resembling Unix
9 pipes. An example is::
9 pipes. An example is::
10
10
11 >>> ienv | isort("key.lower()")
11 >>> ienv | isort("key.lower()")
12
12
13 This gives a listing of all environment variables sorted by name.
13 This gives a listing of all environment variables sorted by name.
14
14
15
15
16 There are three types of objects in a pipeline expression:
16 There are three types of objects in a pipeline expression:
17
17
18 * ``Table``s: These objects produce items. Examples are ``ils`` (listing the
18 * ``Table``s: These objects produce items. Examples are ``ils`` (listing the
19 current directory, ``ienv`` (listing environment variables), ``ipwd`` (listing
19 current directory, ``ienv`` (listing environment variables), ``ipwd`` (listing
20 user accounts) and ``igrp`` (listing user groups). A ``Table`` must be the
20 user accounts) and ``igrp`` (listing user groups). A ``Table`` must be the
21 first object in a pipe expression.
21 first object in a pipe expression.
22
22
23 * ``Pipe``s: These objects sit in the middle of a pipe expression. They
23 * ``Pipe``s: These objects sit in the middle of a pipe expression. They
24 transform the input in some way (e.g. filtering or sorting it). Examples are:
24 transform the input in some way (e.g. filtering or sorting it). Examples are:
25 ``ifilter`` (which filters the input pipe), ``isort`` (which sorts the input
25 ``ifilter`` (which filters the input pipe), ``isort`` (which sorts the input
26 pipe) and ``ieval`` (which evaluates a function or expression for each object
26 pipe) and ``ieval`` (which evaluates a function or expression for each object
27 in the input pipe).
27 in the input pipe).
28
28
29 * ``Display``s: These objects can be put as the last object in a pipeline
29 * ``Display``s: These objects can be put as the last object in a pipeline
30 expression. There are responsible for displaying the result of the pipeline
30 expression. There are responsible for displaying the result of the pipeline
31 expression. If a pipeline expression doesn't end in a display object a default
31 expression. If a pipeline expression doesn't end in a display object a default
32 display objects will be used. One example is ``ibrowse`` which is a ``curses``
32 display objects will be used. One example is ``ibrowse`` which is a ``curses``
33 based browser.
33 based browser.
34
34
35
35
36 Adding support for pipeline expressions to your own objects can be done through
36 Adding support for pipeline expressions to your own objects can be done through
37 three extensions points (all of them optional):
37 three extensions points (all of them optional):
38
38
39 * An object that will be displayed as a row by a ``Display`` object should
39 * An object that will be displayed as a row by a ``Display`` object should
40 implement the method ``__xattrs__(self, mode)`` method or register an
40 implement the method ``__xattrs__(self, mode)`` method or register an
41 implementation of the generic function ``xattrs``. For more info see ``xattrs``.
41 implementation of the generic function ``xattrs``. For more info see ``xattrs``.
42
42
43 * When an object ``foo`` is displayed by a ``Display`` object, the generic
43 * When an object ``foo`` is displayed by a ``Display`` object, the generic
44 function ``xrepr`` is used.
44 function ``xrepr`` is used.
45
45
46 * Objects that can be iterated by ``Pipe``s must iterable. For special cases,
46 * Objects that can be iterated by ``Pipe``s must iterable. For special cases,
47 where iteration for display is different than the normal iteration a special
47 where iteration for display is different than the normal iteration a special
48 implementation can be registered with the generic function ``xiter``. This
48 implementation can be registered with the generic function ``xiter``. This
49 makes it possible to use dictionaries and modules in pipeline expressions,
49 makes it possible to use dictionaries and modules in pipeline expressions,
50 for example::
50 for example::
51
51
52 >>> import sys
52 >>> import sys
53 >>> sys | ifilter("isinstance(value, int)") | idump
53 >>> sys | ifilter("isinstance(value, int)") | idump
54 key |value
54 key |value
55 api_version| 1012
55 api_version| 1012
56 dllhandle | 503316480
56 dllhandle | 503316480
57 hexversion | 33817328
57 hexversion | 33817328
58 maxint |2147483647
58 maxint |2147483647
59 maxunicode | 65535
59 maxunicode | 65535
60 >>> sys.modules | ifilter("_.value is not None") | isort("_.key.lower()")
60 >>> sys.modules | ifilter("_.value is not None") | isort("_.key.lower()")
61 ...
61 ...
62
62
63 Note: The expression strings passed to ``ifilter()`` and ``isort()`` can
63 Note: The expression strings passed to ``ifilter()`` and ``isort()`` can
64 refer to the object to be filtered or sorted via the variable ``_`` and to any
64 refer to the object to be filtered or sorted via the variable ``_`` and to any
65 of the attributes of the object, i.e.::
65 of the attributes of the object, i.e.::
66
66
67 >>> sys.modules | ifilter("_.value is not None") | isort("_.key.lower()")
67 >>> sys.modules | ifilter("_.value is not None") | isort("_.key.lower()")
68
68
69 does the same as::
69 does the same as::
70
70
71 >>> sys.modules | ifilter("value is not None") | isort("key.lower()")
71 >>> sys.modules | ifilter("value is not None") | isort("key.lower()")
72
72
73 In addition to expression strings, it's possible to pass callables (taking
73 In addition to expression strings, it's possible to pass callables (taking
74 the object as an argument) to ``ifilter()``, ``isort()`` and ``ieval()``::
74 the object as an argument) to ``ifilter()``, ``isort()`` and ``ieval()``::
75
75
76 >>> sys | ifilter(lambda _:isinstance(_.value, int)) \
76 >>> sys | ifilter(lambda _:isinstance(_.value, int)) \
77 ... | ieval(lambda _: (_.key, hex(_.value))) | idump
77 ... | ieval(lambda _: (_.key, hex(_.value))) | idump
78 0 |1
78 0 |1
79 api_version|0x3f4
79 api_version|0x3f4
80 dllhandle |0x1e000000
80 dllhandle |0x1e000000
81 hexversion |0x20402f0
81 hexversion |0x20402f0
82 maxint |0x7fffffff
82 maxint |0x7fffffff
83 maxunicode |0xffff
83 maxunicode |0xffff
84 """
84 """
85
85
86 skip_doctest = True # ignore top-level docstring as a doctest.
86 skip_doctest = True # ignore top-level docstring as a doctest.
87
87
88 import sys, os, os.path, stat, glob, new, csv, datetime, types
88 import sys, os, os.path, stat, glob, new, csv, datetime, types
89 import itertools, mimetypes, StringIO
89 import itertools, mimetypes, StringIO
90
90
91 try: # Python 2.3 compatibility
91 try: # Python 2.3 compatibility
92 import collections
92 import collections
93 except ImportError:
93 except ImportError:
94 deque = list
94 deque = list
95 else:
95 else:
96 deque = collections.deque
96 deque = collections.deque
97
97
98 try: # Python 2.3 compatibility
98 try: # Python 2.3 compatibility
99 set
99 set
100 except NameError:
100 except NameError:
101 import sets
101 import sets
102 set = sets.Set
102 set = sets.Set
103
103
104 try: # Python 2.3 compatibility
104 try: # Python 2.3 compatibility
105 sorted
105 sorted
106 except NameError:
106 except NameError:
107 def sorted(iterator, key=None, reverse=False):
107 def sorted(iterator, key=None, reverse=False):
108 items = list(iterator)
108 items = list(iterator)
109 if key is not None:
109 if key is not None:
110 items.sort(lambda i1, i2: cmp(key(i1), key(i2)))
110 items.sort(lambda i1, i2: cmp(key(i1), key(i2)))
111 else:
111 else:
112 items.sort()
112 items.sort()
113 if reverse:
113 if reverse:
114 items.reverse()
114 items.reverse()
115 return items
115 return items
116
116
117 try: # Python 2.4 compatibility
118 GeneratorExit
119 except NameError:
120 GeneratorExit = SystemExit
121
117 try:
122 try:
118 import pwd
123 import pwd
119 except ImportError:
124 except ImportError:
120 pwd = None
125 pwd = None
121
126
122 try:
127 try:
123 import grp
128 import grp
124 except ImportError:
129 except ImportError:
125 grp = None
130 grp = None
126
131
127 from IPython.external import simplegeneric
132 from IPython.external import simplegeneric
128 from IPython.external import path
133 from IPython.external import path
129
134
130 try:
135 try:
131 from IPython import genutils, generics
136 from IPython import genutils, generics
132 except ImportError:
137 except ImportError:
133 genutils = None
138 genutils = None
134 generics = None
139 generics = None
135
140
136 from IPython import ipapi
141 from IPython import ipapi
137
142
138
143
139 __all__ = [
144 __all__ = [
140 "ifile", "ils", "iglob", "iwalk", "ipwdentry", "ipwd", "igrpentry", "igrp",
145 "ifile", "ils", "iglob", "iwalk", "ipwdentry", "ipwd", "igrpentry", "igrp",
141 "icsv", "ix", "ichain", "isort", "ifilter", "ieval", "ienum",
146 "icsv", "ix", "ichain", "isort", "ifilter", "ieval", "ienum",
142 "ienv", "ihist", "ialias", "icap", "idump", "iless"
147 "ienv", "ihist", "ialias", "icap", "idump", "iless"
143 ]
148 ]
144
149
145
150
146 os.stat_float_times(True) # enable microseconds
151 os.stat_float_times(True) # enable microseconds
147
152
148
153
149 class AttrNamespace(object):
154 class AttrNamespace(object):
150 """
155 """
151 Helper class that is used for providing a namespace for evaluating
156 Helper class that is used for providing a namespace for evaluating
152 expressions containing attribute names of an object.
157 expressions containing attribute names of an object.
153 """
158 """
154 def __init__(self, wrapped):
159 def __init__(self, wrapped):
155 self.wrapped = wrapped
160 self.wrapped = wrapped
156
161
157 def __getitem__(self, name):
162 def __getitem__(self, name):
158 if name == "_":
163 if name == "_":
159 return self.wrapped
164 return self.wrapped
160 try:
165 try:
161 return getattr(self.wrapped, name)
166 return getattr(self.wrapped, name)
162 except AttributeError:
167 except AttributeError:
163 raise KeyError(name)
168 raise KeyError(name)
164
169
165 # Python 2.3 compatibility
170 # Python 2.3 compatibility
166 # use eval workaround to find out which names are used in the
171 # use eval workaround to find out which names are used in the
167 # eval string and put them into the locals. This works for most
172 # eval string and put them into the locals. This works for most
168 # normal uses case, bizarre ones like accessing the locals()
173 # normal uses case, bizarre ones like accessing the locals()
169 # will fail
174 # will fail
170 try:
175 try:
171 eval("_", None, AttrNamespace(None))
176 eval("_", None, AttrNamespace(None))
172 except TypeError:
177 except TypeError:
173 real_eval = eval
178 real_eval = eval
174 def eval(codestring, _globals, _locals):
179 def eval(codestring, _globals, _locals):
175 """
180 """
176 eval(source[, globals[, locals]]) -> value
181 eval(source[, globals[, locals]]) -> value
177
182
178 Evaluate the source in the context of globals and locals.
183 Evaluate the source in the context of globals and locals.
179 The source may be a string representing a Python expression
184 The source may be a string representing a Python expression
180 or a code object as returned by compile().
185 or a code object as returned by compile().
181 The globals must be a dictionary and locals can be any mappping.
186 The globals must be a dictionary and locals can be any mappping.
182
187
183 This function is a workaround for the shortcomings of
188 This function is a workaround for the shortcomings of
184 Python 2.3's eval.
189 Python 2.3's eval.
185 """
190 """
186
191
187 if isinstance(codestring, basestring):
192 if isinstance(codestring, basestring):
188 code = compile(codestring, "_eval", "eval")
193 code = compile(codestring, "_eval", "eval")
189 else:
194 else:
190 code = codestring
195 code = codestring
191 newlocals = {}
196 newlocals = {}
192 for name in code.co_names:
197 for name in code.co_names:
193 try:
198 try:
194 newlocals[name] = _locals[name]
199 newlocals[name] = _locals[name]
195 except KeyError:
200 except KeyError:
196 pass
201 pass
197 return real_eval(code, _globals, newlocals)
202 return real_eval(code, _globals, newlocals)
198
203
199
204
200 noitem = object()
205 noitem = object()
201
206
202
207
203 def item(iterator, index, default=noitem):
208 def item(iterator, index, default=noitem):
204 """
209 """
205 Return the ``index``th item from the iterator ``iterator``.
210 Return the ``index``th item from the iterator ``iterator``.
206 ``index`` must be an integer (negative integers are relative to the
211 ``index`` must be an integer (negative integers are relative to the
207 end (i.e. the last items produced by the iterator)).
212 end (i.e. the last items produced by the iterator)).
208
213
209 If ``default`` is given, this will be the default value when
214 If ``default`` is given, this will be the default value when
210 the iterator doesn't contain an item at this position. Otherwise an
215 the iterator doesn't contain an item at this position. Otherwise an
211 ``IndexError`` will be raised.
216 ``IndexError`` will be raised.
212
217
213 Note that using this function will partially or totally exhaust the
218 Note that using this function will partially or totally exhaust the
214 iterator.
219 iterator.
215 """
220 """
216 i = index
221 i = index
217 if i>=0:
222 if i>=0:
218 for item in iterator:
223 for item in iterator:
219 if not i:
224 if not i:
220 return item
225 return item
221 i -= 1
226 i -= 1
222 else:
227 else:
223 i = -index
228 i = -index
224 cache = deque()
229 cache = deque()
225 for item in iterator:
230 for item in iterator:
226 cache.append(item)
231 cache.append(item)
227 if len(cache)>i:
232 if len(cache)>i:
228 cache.popleft()
233 cache.popleft()
229 if len(cache)==i:
234 if len(cache)==i:
230 return cache.popleft()
235 return cache.popleft()
231 if default is noitem:
236 if default is noitem:
232 raise IndexError(index)
237 raise IndexError(index)
233 else:
238 else:
234 return default
239 return default
235
240
236
241
237 def getglobals(g):
242 def getglobals(g):
238 """
243 """
239 Return the global namespace that is used for expression strings in
244 Return the global namespace that is used for expression strings in
240 ``ifilter`` and others. This is ``g`` or (if ``g`` is ``None``) IPython's
245 ``ifilter`` and others. This is ``g`` or (if ``g`` is ``None``) IPython's
241 user namespace.
246 user namespace.
242 """
247 """
243 if g is None:
248 if g is None:
244 if ipapi is not None:
249 if ipapi is not None:
245 api = ipapi.get()
250 api = ipapi.get()
246 if api is not None:
251 if api is not None:
247 return api.user_ns
252 return api.user_ns
248 return globals()
253 return globals()
249 return g
254 return g
250
255
251
256
252 class Descriptor(object):
257 class Descriptor(object):
253 """
258 """
254 A ``Descriptor`` object is used for describing the attributes of objects.
259 A ``Descriptor`` object is used for describing the attributes of objects.
255 """
260 """
256 def __hash__(self):
261 def __hash__(self):
257 return hash(self.__class__) ^ hash(self.key())
262 return hash(self.__class__) ^ hash(self.key())
258
263
259 def __eq__(self, other):
264 def __eq__(self, other):
260 return self.__class__ is other.__class__ and self.key() == other.key()
265 return self.__class__ is other.__class__ and self.key() == other.key()
261
266
262 def __ne__(self, other):
267 def __ne__(self, other):
263 return self.__class__ is not other.__class__ or self.key() != other.key()
268 return self.__class__ is not other.__class__ or self.key() != other.key()
264
269
265 def key(self):
270 def key(self):
266 pass
271 pass
267
272
268 def name(self):
273 def name(self):
269 """
274 """
270 Return the name of this attribute for display by a ``Display`` object
275 Return the name of this attribute for display by a ``Display`` object
271 (e.g. as a column title).
276 (e.g. as a column title).
272 """
277 """
273 key = self.key()
278 key = self.key()
274 if key is None:
279 if key is None:
275 return "_"
280 return "_"
276 return str(key)
281 return str(key)
277
282
278 def attrtype(self, obj):
283 def attrtype(self, obj):
279 """
284 """
280 Return the type of this attribute (i.e. something like "attribute" or
285 Return the type of this attribute (i.e. something like "attribute" or
281 "method").
286 "method").
282 """
287 """
283
288
284 def valuetype(self, obj):
289 def valuetype(self, obj):
285 """
290 """
286 Return the type of this attribute value of the object ``obj``.
291 Return the type of this attribute value of the object ``obj``.
287 """
292 """
288
293
289 def value(self, obj):
294 def value(self, obj):
290 """
295 """
291 Return the value of this attribute of the object ``obj``.
296 Return the value of this attribute of the object ``obj``.
292 """
297 """
293
298
294 def doc(self, obj):
299 def doc(self, obj):
295 """
300 """
296 Return the documentation for this attribute.
301 Return the documentation for this attribute.
297 """
302 """
298
303
299 def shortdoc(self, obj):
304 def shortdoc(self, obj):
300 """
305 """
301 Return a short documentation for this attribute (defaulting to the
306 Return a short documentation for this attribute (defaulting to the
302 first line).
307 first line).
303 """
308 """
304 doc = self.doc(obj)
309 doc = self.doc(obj)
305 if doc is not None:
310 if doc is not None:
306 doc = doc.strip().splitlines()[0].strip()
311 doc = doc.strip().splitlines()[0].strip()
307 return doc
312 return doc
308
313
309 def iter(self, obj):
314 def iter(self, obj):
310 """
315 """
311 Return an iterator for this attribute of the object ``obj``.
316 Return an iterator for this attribute of the object ``obj``.
312 """
317 """
313 return xiter(self.value(obj))
318 return xiter(self.value(obj))
314
319
315
320
316 class SelfDescriptor(Descriptor):
321 class SelfDescriptor(Descriptor):
317 """
322 """
318 A ``SelfDescriptor`` describes the object itself.
323 A ``SelfDescriptor`` describes the object itself.
319 """
324 """
320 def key(self):
325 def key(self):
321 return None
326 return None
322
327
323 def attrtype(self, obj):
328 def attrtype(self, obj):
324 return "self"
329 return "self"
325
330
326 def valuetype(self, obj):
331 def valuetype(self, obj):
327 return type(obj)
332 return type(obj)
328
333
329 def value(self, obj):
334 def value(self, obj):
330 return obj
335 return obj
331
336
332 def __repr__(self):
337 def __repr__(self):
333 return "Self"
338 return "Self"
334
339
335 selfdescriptor = SelfDescriptor() # there's no need for more than one
340 selfdescriptor = SelfDescriptor() # there's no need for more than one
336
341
337
342
338 class AttributeDescriptor(Descriptor):
343 class AttributeDescriptor(Descriptor):
339 """
344 """
340 An ``AttributeDescriptor`` describes a simple attribute of an object.
345 An ``AttributeDescriptor`` describes a simple attribute of an object.
341 """
346 """
342 __slots__ = ("_name", "_doc")
347 __slots__ = ("_name", "_doc")
343
348
344 def __init__(self, name, doc=None):
349 def __init__(self, name, doc=None):
345 self._name = name
350 self._name = name
346 self._doc = doc
351 self._doc = doc
347
352
348 def key(self):
353 def key(self):
349 return self._name
354 return self._name
350
355
351 def doc(self, obj):
356 def doc(self, obj):
352 return self._doc
357 return self._doc
353
358
354 def attrtype(self, obj):
359 def attrtype(self, obj):
355 return "attr"
360 return "attr"
356
361
357 def valuetype(self, obj):
362 def valuetype(self, obj):
358 return type(getattr(obj, self._name))
363 return type(getattr(obj, self._name))
359
364
360 def value(self, obj):
365 def value(self, obj):
361 return getattr(obj, self._name)
366 return getattr(obj, self._name)
362
367
363 def __repr__(self):
368 def __repr__(self):
364 if self._doc is None:
369 if self._doc is None:
365 return "Attribute(%r)" % self._name
370 return "Attribute(%r)" % self._name
366 else:
371 else:
367 return "Attribute(%r, %r)" % (self._name, self._doc)
372 return "Attribute(%r, %r)" % (self._name, self._doc)
368
373
369
374
370 class IndexDescriptor(Descriptor):
375 class IndexDescriptor(Descriptor):
371 """
376 """
372 An ``IndexDescriptor`` describes an "attribute" of an object that is fetched
377 An ``IndexDescriptor`` describes an "attribute" of an object that is fetched
373 via ``__getitem__``.
378 via ``__getitem__``.
374 """
379 """
375 __slots__ = ("_index",)
380 __slots__ = ("_index",)
376
381
377 def __init__(self, index):
382 def __init__(self, index):
378 self._index = index
383 self._index = index
379
384
380 def key(self):
385 def key(self):
381 return self._index
386 return self._index
382
387
383 def attrtype(self, obj):
388 def attrtype(self, obj):
384 return "item"
389 return "item"
385
390
386 def valuetype(self, obj):
391 def valuetype(self, obj):
387 return type(obj[self._index])
392 return type(obj[self._index])
388
393
389 def value(self, obj):
394 def value(self, obj):
390 return obj[self._index]
395 return obj[self._index]
391
396
392 def __repr__(self):
397 def __repr__(self):
393 return "Index(%r)" % self._index
398 return "Index(%r)" % self._index
394
399
395
400
396 class MethodDescriptor(Descriptor):
401 class MethodDescriptor(Descriptor):
397 """
402 """
398 A ``MethodDescriptor`` describes a method of an object that can be called
403 A ``MethodDescriptor`` describes a method of an object that can be called
399 without argument. Note that this method shouldn't change the object.
404 without argument. Note that this method shouldn't change the object.
400 """
405 """
401 __slots__ = ("_name", "_doc")
406 __slots__ = ("_name", "_doc")
402
407
403 def __init__(self, name, doc=None):
408 def __init__(self, name, doc=None):
404 self._name = name
409 self._name = name
405 self._doc = doc
410 self._doc = doc
406
411
407 def key(self):
412 def key(self):
408 return self._name
413 return self._name
409
414
410 def doc(self, obj):
415 def doc(self, obj):
411 if self._doc is None:
416 if self._doc is None:
412 return getattr(obj, self._name).__doc__
417 return getattr(obj, self._name).__doc__
413 return self._doc
418 return self._doc
414
419
415 def attrtype(self, obj):
420 def attrtype(self, obj):
416 return "method"
421 return "method"
417
422
418 def valuetype(self, obj):
423 def valuetype(self, obj):
419 return type(self.value(obj))
424 return type(self.value(obj))
420
425
421 def value(self, obj):
426 def value(self, obj):
422 return getattr(obj, self._name)()
427 return getattr(obj, self._name)()
423
428
424 def __repr__(self):
429 def __repr__(self):
425 if self._doc is None:
430 if self._doc is None:
426 return "Method(%r)" % self._name
431 return "Method(%r)" % self._name
427 else:
432 else:
428 return "Method(%r, %r)" % (self._name, self._doc)
433 return "Method(%r, %r)" % (self._name, self._doc)
429
434
430
435
431 class IterAttributeDescriptor(Descriptor):
436 class IterAttributeDescriptor(Descriptor):
432 """
437 """
433 An ``IterAttributeDescriptor`` works like an ``AttributeDescriptor`` but
438 An ``IterAttributeDescriptor`` works like an ``AttributeDescriptor`` but
434 doesn't return an attribute values (because this value might be e.g. a large
439 doesn't return an attribute values (because this value might be e.g. a large
435 list).
440 list).
436 """
441 """
437 __slots__ = ("_name", "_doc")
442 __slots__ = ("_name", "_doc")
438
443
439 def __init__(self, name, doc=None):
444 def __init__(self, name, doc=None):
440 self._name = name
445 self._name = name
441 self._doc = doc
446 self._doc = doc
442
447
443 def key(self):
448 def key(self):
444 return self._name
449 return self._name
445
450
446 def doc(self, obj):
451 def doc(self, obj):
447 return self._doc
452 return self._doc
448
453
449 def attrtype(self, obj):
454 def attrtype(self, obj):
450 return "iter"
455 return "iter"
451
456
452 def valuetype(self, obj):
457 def valuetype(self, obj):
453 return noitem
458 return noitem
454
459
455 def value(self, obj):
460 def value(self, obj):
456 return noitem
461 return noitem
457
462
458 def iter(self, obj):
463 def iter(self, obj):
459 return xiter(getattr(obj, self._name))
464 return xiter(getattr(obj, self._name))
460
465
461 def __repr__(self):
466 def __repr__(self):
462 if self._doc is None:
467 if self._doc is None:
463 return "IterAttribute(%r)" % self._name
468 return "IterAttribute(%r)" % self._name
464 else:
469 else:
465 return "IterAttribute(%r, %r)" % (self._name, self._doc)
470 return "IterAttribute(%r, %r)" % (self._name, self._doc)
466
471
467
472
468 class IterMethodDescriptor(Descriptor):
473 class IterMethodDescriptor(Descriptor):
469 """
474 """
470 An ``IterMethodDescriptor`` works like an ``MethodDescriptor`` but doesn't
475 An ``IterMethodDescriptor`` works like an ``MethodDescriptor`` but doesn't
471 return an attribute values (because this value might be e.g. a large list).
476 return an attribute values (because this value might be e.g. a large list).
472 """
477 """
473 __slots__ = ("_name", "_doc")
478 __slots__ = ("_name", "_doc")
474
479
475 def __init__(self, name, doc=None):
480 def __init__(self, name, doc=None):
476 self._name = name
481 self._name = name
477 self._doc = doc
482 self._doc = doc
478
483
479 def key(self):
484 def key(self):
480 return self._name
485 return self._name
481
486
482 def doc(self, obj):
487 def doc(self, obj):
483 if self._doc is None:
488 if self._doc is None:
484 return getattr(obj, self._name).__doc__
489 return getattr(obj, self._name).__doc__
485 return self._doc
490 return self._doc
486
491
487 def attrtype(self, obj):
492 def attrtype(self, obj):
488 return "itermethod"
493 return "itermethod"
489
494
490 def valuetype(self, obj):
495 def valuetype(self, obj):
491 return noitem
496 return noitem
492
497
493 def value(self, obj):
498 def value(self, obj):
494 return noitem
499 return noitem
495
500
496 def iter(self, obj):
501 def iter(self, obj):
497 return xiter(getattr(obj, self._name)())
502 return xiter(getattr(obj, self._name)())
498
503
499 def __repr__(self):
504 def __repr__(self):
500 if self._doc is None:
505 if self._doc is None:
501 return "IterMethod(%r)" % self._name
506 return "IterMethod(%r)" % self._name
502 else:
507 else:
503 return "IterMethod(%r, %r)" % (self._name, self._doc)
508 return "IterMethod(%r, %r)" % (self._name, self._doc)
504
509
505
510
506 class FunctionDescriptor(Descriptor):
511 class FunctionDescriptor(Descriptor):
507 """
512 """
508 A ``FunctionDescriptor`` turns a function into a descriptor. The function
513 A ``FunctionDescriptor`` turns a function into a descriptor. The function
509 will be called with the object to get the type and value of the attribute.
514 will be called with the object to get the type and value of the attribute.
510 """
515 """
511 __slots__ = ("_function", "_name", "_doc")
516 __slots__ = ("_function", "_name", "_doc")
512
517
513 def __init__(self, function, name=None, doc=None):
518 def __init__(self, function, name=None, doc=None):
514 self._function = function
519 self._function = function
515 self._name = name
520 self._name = name
516 self._doc = doc
521 self._doc = doc
517
522
518 def key(self):
523 def key(self):
519 return self._function
524 return self._function
520
525
521 def name(self):
526 def name(self):
522 if self._name is not None:
527 if self._name is not None:
523 return self._name
528 return self._name
524 return getattr(self._function, "__xname__", self._function.__name__)
529 return getattr(self._function, "__xname__", self._function.__name__)
525
530
526 def doc(self, obj):
531 def doc(self, obj):
527 if self._doc is None:
532 if self._doc is None:
528 return self._function.__doc__
533 return self._function.__doc__
529 return self._doc
534 return self._doc
530
535
531 def attrtype(self, obj):
536 def attrtype(self, obj):
532 return "function"
537 return "function"
533
538
534 def valuetype(self, obj):
539 def valuetype(self, obj):
535 return type(self._function(obj))
540 return type(self._function(obj))
536
541
537 def value(self, obj):
542 def value(self, obj):
538 return self._function(obj)
543 return self._function(obj)
539
544
540 def __repr__(self):
545 def __repr__(self):
541 if self._doc is None:
546 if self._doc is None:
542 return "Function(%r)" % self._name
547 return "Function(%r)" % self._name
543 else:
548 else:
544 return "Function(%r, %r)" % (self._name, self._doc)
549 return "Function(%r, %r)" % (self._name, self._doc)
545
550
546
551
547 class Table(object):
552 class Table(object):
548 """
553 """
549 A ``Table`` is an object that produces items (just like a normal Python
554 A ``Table`` is an object that produces items (just like a normal Python
550 iterator/generator does) and can be used as the first object in a pipeline
555 iterator/generator does) and can be used as the first object in a pipeline
551 expression. The displayhook will open the default browser for such an object
556 expression. The displayhook will open the default browser for such an object
552 (instead of simply printing the ``repr()`` result).
557 (instead of simply printing the ``repr()`` result).
553 """
558 """
554
559
555 # We want to support ``foo`` and ``foo()`` in pipeline expression:
560 # We want to support ``foo`` and ``foo()`` in pipeline expression:
556 # So we implement the required operators (``|`` and ``+``) in the metaclass,
561 # So we implement the required operators (``|`` and ``+``) in the metaclass,
557 # instantiate the class and forward the operator to the instance
562 # instantiate the class and forward the operator to the instance
558 class __metaclass__(type):
563 class __metaclass__(type):
559 def __iter__(self):
564 def __iter__(self):
560 return iter(self())
565 return iter(self())
561
566
562 def __or__(self, other):
567 def __or__(self, other):
563 return self() | other
568 return self() | other
564
569
565 def __add__(self, other):
570 def __add__(self, other):
566 return self() + other
571 return self() + other
567
572
568 def __radd__(self, other):
573 def __radd__(self, other):
569 return other + self()
574 return other + self()
570
575
571 def __getitem__(self, index):
576 def __getitem__(self, index):
572 return self()[index]
577 return self()[index]
573
578
574 def __getitem__(self, index):
579 def __getitem__(self, index):
575 return item(self, index)
580 return item(self, index)
576
581
577 def __contains__(self, item):
582 def __contains__(self, item):
578 for haveitem in self:
583 for haveitem in self:
579 if item == haveitem:
584 if item == haveitem:
580 return True
585 return True
581 return False
586 return False
582
587
583 def __or__(self, other):
588 def __or__(self, other):
584 # autoinstantiate right hand side
589 # autoinstantiate right hand side
585 if isinstance(other, type) and issubclass(other, (Table, Display)):
590 if isinstance(other, type) and issubclass(other, (Table, Display)):
586 other = other()
591 other = other()
587 # treat simple strings and functions as ``ieval`` instances
592 # treat simple strings and functions as ``ieval`` instances
588 elif not isinstance(other, Display) and not isinstance(other, Table):
593 elif not isinstance(other, Display) and not isinstance(other, Table):
589 other = ieval(other)
594 other = ieval(other)
590 # forward operations to the right hand side
595 # forward operations to the right hand side
591 return other.__ror__(self)
596 return other.__ror__(self)
592
597
593 def __add__(self, other):
598 def __add__(self, other):
594 # autoinstantiate right hand side
599 # autoinstantiate right hand side
595 if isinstance(other, type) and issubclass(other, Table):
600 if isinstance(other, type) and issubclass(other, Table):
596 other = other()
601 other = other()
597 return ichain(self, other)
602 return ichain(self, other)
598
603
599 def __radd__(self, other):
604 def __radd__(self, other):
600 # autoinstantiate left hand side
605 # autoinstantiate left hand side
601 if isinstance(other, type) and issubclass(other, Table):
606 if isinstance(other, type) and issubclass(other, Table):
602 other = other()
607 other = other()
603 return ichain(other, self)
608 return ichain(other, self)
604
609
605
610
606 class Pipe(Table):
611 class Pipe(Table):
607 """
612 """
608 A ``Pipe`` is an object that can be used in a pipeline expression. It
613 A ``Pipe`` is an object that can be used in a pipeline expression. It
609 processes the objects it gets from its input ``Table``/``Pipe``. Note that
614 processes the objects it gets from its input ``Table``/``Pipe``. Note that
610 a ``Pipe`` object can't be used as the first object in a pipeline
615 a ``Pipe`` object can't be used as the first object in a pipeline
611 expression, as it doesn't produces items itself.
616 expression, as it doesn't produces items itself.
612 """
617 """
613 class __metaclass__(Table.__metaclass__):
618 class __metaclass__(Table.__metaclass__):
614 def __ror__(self, input):
619 def __ror__(self, input):
615 return input | self()
620 return input | self()
616
621
617 def __ror__(self, input):
622 def __ror__(self, input):
618 # autoinstantiate left hand side
623 # autoinstantiate left hand side
619 if isinstance(input, type) and issubclass(input, Table):
624 if isinstance(input, type) and issubclass(input, Table):
620 input = input()
625 input = input()
621 self.input = input
626 self.input = input
622 return self
627 return self
623
628
624
629
625 def xrepr(item, mode="default"):
630 def xrepr(item, mode="default"):
626 """
631 """
627 Generic function that adds color output and different display modes to ``repr``.
632 Generic function that adds color output and different display modes to ``repr``.
628
633
629 The result of an ``xrepr`` call is iterable and consists of ``(style, string)``
634 The result of an ``xrepr`` call is iterable and consists of ``(style, string)``
630 tuples. The ``style`` in this tuple must be a ``Style`` object from the
635 tuples. The ``style`` in this tuple must be a ``Style`` object from the
631 ``astring`` module. To reconfigure the output the first yielded tuple can be
636 ``astring`` module. To reconfigure the output the first yielded tuple can be
632 a ``(aligment, full)`` tuple instead of a ``(style, string)`` tuple.
637 a ``(aligment, full)`` tuple instead of a ``(style, string)`` tuple.
633 ``alignment`` can be -1 for left aligned, 0 for centered and 1 for right
638 ``alignment`` can be -1 for left aligned, 0 for centered and 1 for right
634 aligned (the default is left alignment). ``full`` is a boolean that specifies
639 aligned (the default is left alignment). ``full`` is a boolean that specifies
635 whether the complete output must be displayed or the ``Display`` object is
640 whether the complete output must be displayed or the ``Display`` object is
636 allowed to stop output after enough text has been produced (e.g. a syntax
641 allowed to stop output after enough text has been produced (e.g. a syntax
637 highlighted text line would use ``True``, but for a large data structure
642 highlighted text line would use ``True``, but for a large data structure
638 (i.e. a nested list, tuple or dictionary) ``False`` would be used).
643 (i.e. a nested list, tuple or dictionary) ``False`` would be used).
639 The default is full output.
644 The default is full output.
640
645
641 There are four different possible values for ``mode`` depending on where
646 There are four different possible values for ``mode`` depending on where
642 the ``Display`` object will display ``item``:
647 the ``Display`` object will display ``item``:
643
648
644 ``"header"``
649 ``"header"``
645 ``item`` will be displayed in a header line (this is used by ``ibrowse``).
650 ``item`` will be displayed in a header line (this is used by ``ibrowse``).
646
651
647 ``"footer"``
652 ``"footer"``
648 ``item`` will be displayed in a footer line (this is used by ``ibrowse``).
653 ``item`` will be displayed in a footer line (this is used by ``ibrowse``).
649
654
650 ``"cell"``
655 ``"cell"``
651 ``item`` will be displayed in a table cell/list.
656 ``item`` will be displayed in a table cell/list.
652
657
653 ``"default"``
658 ``"default"``
654 default mode. If an ``xrepr`` implementation recursively outputs objects,
659 default mode. If an ``xrepr`` implementation recursively outputs objects,
655 ``"default"`` must be passed in the recursive calls to ``xrepr``.
660 ``"default"`` must be passed in the recursive calls to ``xrepr``.
656
661
657 If no implementation is registered for ``item``, ``xrepr`` will try the
662 If no implementation is registered for ``item``, ``xrepr`` will try the
658 ``__xrepr__`` method on ``item``. If ``item`` doesn't have an ``__xrepr__``
663 ``__xrepr__`` method on ``item``. If ``item`` doesn't have an ``__xrepr__``
659 method it falls back to ``repr``/``__repr__`` for all modes.
664 method it falls back to ``repr``/``__repr__`` for all modes.
660 """
665 """
661 try:
666 try:
662 func = item.__xrepr__
667 func = item.__xrepr__
663 except AttributeError:
668 except AttributeError:
664 yield (astyle.style_default, repr(item))
669 yield (astyle.style_default, repr(item))
665 else:
670 else:
666 try:
671 try:
667 for x in func(mode):
672 for x in func(mode):
668 yield x
673 yield x
669 except (KeyboardInterrupt, SystemExit):
674 except (KeyboardInterrupt, SystemExit, GeneratorExit):
670 raise
675 raise
671 except Exception:
676 except Exception:
672 yield (astyle.style_default, repr(item))
677 yield (astyle.style_default, repr(item))
673 xrepr = simplegeneric.generic(xrepr)
678 xrepr = simplegeneric.generic(xrepr)
674
679
675
680
676 def xrepr_none(self, mode="default"):
681 def xrepr_none(self, mode="default"):
677 yield (astyle.style_type_none, repr(self))
682 yield (astyle.style_type_none, repr(self))
678 xrepr.when_object(None)(xrepr_none)
683 xrepr.when_object(None)(xrepr_none)
679
684
680
685
681 def xrepr_noitem(self, mode="default"):
686 def xrepr_noitem(self, mode="default"):
682 yield (2, True)
687 yield (2, True)
683 yield (astyle.style_nodata, "<?>")
688 yield (astyle.style_nodata, "<?>")
684 xrepr.when_object(noitem)(xrepr_noitem)
689 xrepr.when_object(noitem)(xrepr_noitem)
685
690
686
691
687 def xrepr_bool(self, mode="default"):
692 def xrepr_bool(self, mode="default"):
688 yield (astyle.style_type_bool, repr(self))
693 yield (astyle.style_type_bool, repr(self))
689 xrepr.when_type(bool)(xrepr_bool)
694 xrepr.when_type(bool)(xrepr_bool)
690
695
691
696
692 def xrepr_str(self, mode="default"):
697 def xrepr_str(self, mode="default"):
693 if mode == "cell":
698 if mode == "cell":
694 yield (astyle.style_default, repr(self.expandtabs(tab))[1:-1])
699 yield (astyle.style_default, repr(self.expandtabs(tab))[1:-1])
695 else:
700 else:
696 yield (astyle.style_default, repr(self))
701 yield (astyle.style_default, repr(self))
697 xrepr.when_type(str)(xrepr_str)
702 xrepr.when_type(str)(xrepr_str)
698
703
699
704
700 def xrepr_unicode(self, mode="default"):
705 def xrepr_unicode(self, mode="default"):
701 if mode == "cell":
706 if mode == "cell":
702 yield (astyle.style_default, repr(self.expandtabs(tab))[2:-1])
707 yield (astyle.style_default, repr(self.expandtabs(tab))[2:-1])
703 else:
708 else:
704 yield (astyle.style_default, repr(self))
709 yield (astyle.style_default, repr(self))
705 xrepr.when_type(unicode)(xrepr_unicode)
710 xrepr.when_type(unicode)(xrepr_unicode)
706
711
707
712
708 def xrepr_number(self, mode="default"):
713 def xrepr_number(self, mode="default"):
709 yield (1, True)
714 yield (1, True)
710 yield (astyle.style_type_number, repr(self))
715 yield (astyle.style_type_number, repr(self))
711 xrepr.when_type(int)(xrepr_number)
716 xrepr.when_type(int)(xrepr_number)
712 xrepr.when_type(long)(xrepr_number)
717 xrepr.when_type(long)(xrepr_number)
713 xrepr.when_type(float)(xrepr_number)
718 xrepr.when_type(float)(xrepr_number)
714
719
715
720
716 def xrepr_complex(self, mode="default"):
721 def xrepr_complex(self, mode="default"):
717 yield (astyle.style_type_number, repr(self))
722 yield (astyle.style_type_number, repr(self))
718 xrepr.when_type(complex)(xrepr_number)
723 xrepr.when_type(complex)(xrepr_number)
719
724
720
725
721 def xrepr_datetime(self, mode="default"):
726 def xrepr_datetime(self, mode="default"):
722 if mode == "cell":
727 if mode == "cell":
723 # Don't use strftime() here, as this requires year >= 1900
728 # Don't use strftime() here, as this requires year >= 1900
724 yield (astyle.style_type_datetime,
729 yield (astyle.style_type_datetime,
725 "%04d-%02d-%02d %02d:%02d:%02d.%06d" % \
730 "%04d-%02d-%02d %02d:%02d:%02d.%06d" % \
726 (self.year, self.month, self.day,
731 (self.year, self.month, self.day,
727 self.hour, self.minute, self.second,
732 self.hour, self.minute, self.second,
728 self.microsecond),
733 self.microsecond),
729 )
734 )
730 else:
735 else:
731 yield (astyle.style_type_datetime, repr(self))
736 yield (astyle.style_type_datetime, repr(self))
732 xrepr.when_type(datetime.datetime)(xrepr_datetime)
737 xrepr.when_type(datetime.datetime)(xrepr_datetime)
733
738
734
739
735 def xrepr_date(self, mode="default"):
740 def xrepr_date(self, mode="default"):
736 if mode == "cell":
741 if mode == "cell":
737 yield (astyle.style_type_datetime,
742 yield (astyle.style_type_datetime,
738 "%04d-%02d-%02d" % (self.year, self.month, self.day))
743 "%04d-%02d-%02d" % (self.year, self.month, self.day))
739 else:
744 else:
740 yield (astyle.style_type_datetime, repr(self))
745 yield (astyle.style_type_datetime, repr(self))
741 xrepr.when_type(datetime.date)(xrepr_date)
746 xrepr.when_type(datetime.date)(xrepr_date)
742
747
743
748
744 def xrepr_time(self, mode="default"):
749 def xrepr_time(self, mode="default"):
745 if mode == "cell":
750 if mode == "cell":
746 yield (astyle.style_type_datetime,
751 yield (astyle.style_type_datetime,
747 "%02d:%02d:%02d.%06d" % \
752 "%02d:%02d:%02d.%06d" % \
748 (self.hour, self.minute, self.second, self.microsecond))
753 (self.hour, self.minute, self.second, self.microsecond))
749 else:
754 else:
750 yield (astyle.style_type_datetime, repr(self))
755 yield (astyle.style_type_datetime, repr(self))
751 xrepr.when_type(datetime.time)(xrepr_time)
756 xrepr.when_type(datetime.time)(xrepr_time)
752
757
753
758
754 def xrepr_timedelta(self, mode="default"):
759 def xrepr_timedelta(self, mode="default"):
755 yield (astyle.style_type_datetime, repr(self))
760 yield (astyle.style_type_datetime, repr(self))
756 xrepr.when_type(datetime.timedelta)(xrepr_timedelta)
761 xrepr.when_type(datetime.timedelta)(xrepr_timedelta)
757
762
758
763
759 def xrepr_type(self, mode="default"):
764 def xrepr_type(self, mode="default"):
760 if self.__module__ == "__builtin__":
765 if self.__module__ == "__builtin__":
761 yield (astyle.style_type_type, self.__name__)
766 yield (astyle.style_type_type, self.__name__)
762 else:
767 else:
763 yield (astyle.style_type_type, "%s.%s" % (self.__module__, self.__name__))
768 yield (astyle.style_type_type, "%s.%s" % (self.__module__, self.__name__))
764 xrepr.when_type(type)(xrepr_type)
769 xrepr.when_type(type)(xrepr_type)
765
770
766
771
767 def xrepr_exception(self, mode="default"):
772 def xrepr_exception(self, mode="default"):
768 if self.__class__.__module__ == "exceptions":
773 if self.__class__.__module__ == "exceptions":
769 classname = self.__class__.__name__
774 classname = self.__class__.__name__
770 else:
775 else:
771 classname = "%s.%s" % \
776 classname = "%s.%s" % \
772 (self.__class__.__module__, self.__class__.__name__)
777 (self.__class__.__module__, self.__class__.__name__)
773 if mode == "header" or mode == "footer":
778 if mode == "header" or mode == "footer":
774 yield (astyle.style_error, "%s: %s" % (classname, self))
779 yield (astyle.style_error, "%s: %s" % (classname, self))
775 else:
780 else:
776 yield (astyle.style_error, classname)
781 yield (astyle.style_error, classname)
777 xrepr.when_type(Exception)(xrepr_exception)
782 xrepr.when_type(Exception)(xrepr_exception)
778
783
779
784
780 def xrepr_listtuple(self, mode="default"):
785 def xrepr_listtuple(self, mode="default"):
781 if mode == "header" or mode == "footer":
786 if mode == "header" or mode == "footer":
782 if self.__class__.__module__ == "__builtin__":
787 if self.__class__.__module__ == "__builtin__":
783 classname = self.__class__.__name__
788 classname = self.__class__.__name__
784 else:
789 else:
785 classname = "%s.%s" % \
790 classname = "%s.%s" % \
786 (self.__class__.__module__,self.__class__.__name__)
791 (self.__class__.__module__,self.__class__.__name__)
787 yield (astyle.style_default,
792 yield (astyle.style_default,
788 "<%s object with %d items at 0x%x>" % \
793 "<%s object with %d items at 0x%x>" % \
789 (classname, len(self), id(self)))
794 (classname, len(self), id(self)))
790 else:
795 else:
791 yield (-1, False)
796 yield (-1, False)
792 if isinstance(self, list):
797 if isinstance(self, list):
793 yield (astyle.style_default, "[")
798 yield (astyle.style_default, "[")
794 end = "]"
799 end = "]"
795 else:
800 else:
796 yield (astyle.style_default, "(")
801 yield (astyle.style_default, "(")
797 end = ")"
802 end = ")"
798 for (i, subself) in enumerate(self):
803 for (i, subself) in enumerate(self):
799 if i:
804 if i:
800 yield (astyle.style_default, ", ")
805 yield (astyle.style_default, ", ")
801 for part in xrepr(subself, "default"):
806 for part in xrepr(subself, "default"):
802 yield part
807 yield part
803 yield (astyle.style_default, end)
808 yield (astyle.style_default, end)
804 xrepr.when_type(list)(xrepr_listtuple)
809 xrepr.when_type(list)(xrepr_listtuple)
805 xrepr.when_type(tuple)(xrepr_listtuple)
810 xrepr.when_type(tuple)(xrepr_listtuple)
806
811
807
812
808 def xrepr_dict(self, mode="default"):
813 def xrepr_dict(self, mode="default"):
809 if mode == "header" or mode == "footer":
814 if mode == "header" or mode == "footer":
810 if self.__class__.__module__ == "__builtin__":
815 if self.__class__.__module__ == "__builtin__":
811 classname = self.__class__.__name__
816 classname = self.__class__.__name__
812 else:
817 else:
813 classname = "%s.%s" % \
818 classname = "%s.%s" % \
814 (self.__class__.__module__,self.__class__.__name__)
819 (self.__class__.__module__,self.__class__.__name__)
815 yield (astyle.style_default,
820 yield (astyle.style_default,
816 "<%s object with %d items at 0x%x>" % \
821 "<%s object with %d items at 0x%x>" % \
817 (classname, len(self), id(self)))
822 (classname, len(self), id(self)))
818 else:
823 else:
819 yield (-1, False)
824 yield (-1, False)
820 if isinstance(self, dict):
825 if isinstance(self, dict):
821 yield (astyle.style_default, "{")
826 yield (astyle.style_default, "{")
822 end = "}"
827 end = "}"
823 else:
828 else:
824 yield (astyle.style_default, "dictproxy((")
829 yield (astyle.style_default, "dictproxy((")
825 end = "})"
830 end = "})"
826 for (i, (key, value)) in enumerate(self.iteritems()):
831 for (i, (key, value)) in enumerate(self.iteritems()):
827 if i:
832 if i:
828 yield (astyle.style_default, ", ")
833 yield (astyle.style_default, ", ")
829 for part in xrepr(key, "default"):
834 for part in xrepr(key, "default"):
830 yield part
835 yield part
831 yield (astyle.style_default, ": ")
836 yield (astyle.style_default, ": ")
832 for part in xrepr(value, "default"):
837 for part in xrepr(value, "default"):
833 yield part
838 yield part
834 yield (astyle.style_default, end)
839 yield (astyle.style_default, end)
835 xrepr.when_type(dict)(xrepr_dict)
840 xrepr.when_type(dict)(xrepr_dict)
836 xrepr.when_type(types.DictProxyType)(xrepr_dict)
841 xrepr.when_type(types.DictProxyType)(xrepr_dict)
837
842
838
843
839 def upgradexattr(attr):
844 def upgradexattr(attr):
840 """
845 """
841 Convert an attribute descriptor string to a real descriptor object.
846 Convert an attribute descriptor string to a real descriptor object.
842
847
843 If attr already is a descriptor object return if unmodified. A
848 If attr already is a descriptor object return it unmodified. A
844 ``SelfDescriptor`` will be returned if ``attr`` is ``None``. ``"foo"``
849 ``SelfDescriptor`` will be returned if ``attr`` is ``None``. ``"foo"``
845 returns an ``AttributeDescriptor`` for the attribute named ``"foo"``.
850 returns an ``AttributeDescriptor`` for the attribute named ``"foo"``.
846 ``"foo()"`` returns a ``MethodDescriptor`` for the method named ``"foo"``.
851 ``"foo()"`` returns a ``MethodDescriptor`` for the method named ``"foo"``.
847 ``"-foo"`` will return an ``IterAttributeDescriptor`` for the attribute
852 ``"-foo"`` will return an ``IterAttributeDescriptor`` for the attribute
848 named ``"foo"`` and ``"-foo()"`` will return an ``IterMethodDescriptor``
853 named ``"foo"`` and ``"-foo()"`` will return an ``IterMethodDescriptor``
849 for the method named ``"foo"``. Furthermore integer will return the appropriate
854 for the method named ``"foo"``. Furthermore integers will return the appropriate
850 ``IndexDescriptor`` and callables will return a ``FunctionDescriptor``.
855 ``IndexDescriptor`` and callables will return a ``FunctionDescriptor``.
851 """
856 """
852 if attr is None:
857 if attr is None:
853 return selfdescriptor
858 return selfdescriptor
854 elif isinstance(attr, Descriptor):
859 elif isinstance(attr, Descriptor):
855 return attr
860 return attr
856 elif isinstance(attr, str):
861 elif isinstance(attr, basestring):
857 if attr.endswith("()"):
862 if attr.endswith("()"):
858 if attr.startswith("-"):
863 if attr.startswith("-"):
859 return IterMethodDescriptor(attr[1:-2])
864 return IterMethodDescriptor(attr[1:-2])
860 else:
865 else:
861 return MethodDescriptor(attr[:-2])
866 return MethodDescriptor(attr[:-2])
862 else:
867 else:
863 if attr.startswith("-"):
868 if attr.startswith("-"):
864 return IterAttributeDescriptor(attr[1:])
869 return IterAttributeDescriptor(attr[1:])
865 else:
870 else:
866 return AttributeDescriptor(attr)
871 return AttributeDescriptor(attr)
867 elif isinstance(attr, (int, long)):
872 elif isinstance(attr, (int, long)):
868 return IndexDescriptor(attr)
873 return IndexDescriptor(attr)
869 elif callable(attr):
874 elif callable(attr):
870 return FunctionDescriptor(attr)
875 return FunctionDescriptor(attr)
871 else:
876 else:
872 raise TypeError("can't handle descriptor %r" % attr)
877 raise TypeError("can't handle descriptor %r" % attr)
873
878
874
879
875 def xattrs(item, mode="default"):
880 def xattrs(item, mode="default"):
876 """
881 """
877 Generic function that returns an iterable of attribute descriptors
882 Generic function that returns an iterable of attribute descriptors
878 to be used for displaying the attributes ob the object ``item`` in display
883 to be used for displaying the attributes ob the object ``item`` in display
879 mode ``mode``.
884 mode ``mode``.
880
885
881 There are two possible modes:
886 There are two possible modes:
882
887
883 ``"detail"``
888 ``"detail"``
884 The ``Display`` object wants to display a detailed list of the object
889 The ``Display`` object wants to display a detailed list of the object
885 attributes.
890 attributes.
886
891
887 ``"default"``
892 ``"default"``
888 The ``Display`` object wants to display the object in a list view.
893 The ``Display`` object wants to display the object in a list view.
889
894
890 If no implementation is registered for the object ``item`` ``xattrs`` falls
895 If no implementation is registered for the object ``item`` ``xattrs`` falls
891 back to trying the ``__xattrs__`` method of the object. If this doesn't
896 back to trying the ``__xattrs__`` method of the object. If this doesn't
892 exist either, ``dir(item)`` is used for ``"detail"`` mode and ``(None,)``
897 exist either, ``dir(item)`` is used for ``"detail"`` mode and ``(None,)``
893 for ``"default"`` mode.
898 for ``"default"`` mode.
894
899
895 The implementation must yield attribute descriptors (see the class
900 The implementation must yield attribute descriptors (see the class
896 ``Descriptor`` for more info). The ``__xattrs__`` method may also return
901 ``Descriptor`` for more info). The ``__xattrs__`` method may also return
897 attribute descriptor strings (and ``None``) which will be converted to real
902 attribute descriptor strings (and ``None``) which will be converted to real
898 descriptors by ``upgradexattr()``.
903 descriptors by ``upgradexattr()``.
899 """
904 """
900 try:
905 try:
901 func = item.__xattrs__
906 func = item.__xattrs__
902 except AttributeError:
907 except AttributeError:
903 if mode == "detail":
908 if mode == "detail":
904 for attrname in dir(item):
909 for attrname in dir(item):
905 yield AttributeDescriptor(attrname)
910 yield AttributeDescriptor(attrname)
906 else:
911 else:
907 yield selfdescriptor
912 yield selfdescriptor
908 else:
913 else:
909 for attr in func(mode):
914 for attr in func(mode):
910 yield upgradexattr(attr)
915 yield upgradexattr(attr)
911 xattrs = simplegeneric.generic(xattrs)
916 xattrs = simplegeneric.generic(xattrs)
912
917
913
918
914 def xattrs_complex(self, mode="default"):
919 def xattrs_complex(self, mode="default"):
915 if mode == "detail":
920 if mode == "detail":
916 return (AttributeDescriptor("real"), AttributeDescriptor("imag"))
921 return (AttributeDescriptor("real"), AttributeDescriptor("imag"))
917 return (selfdescriptor,)
922 return (selfdescriptor,)
918 xattrs.when_type(complex)(xattrs_complex)
923 xattrs.when_type(complex)(xattrs_complex)
919
924
920
925
921 def _isdict(item):
926 def _isdict(item):
922 try:
927 try:
923 itermeth = item.__class__.__iter__
928 itermeth = item.__class__.__iter__
924 except (AttributeError, TypeError):
929 except (AttributeError, TypeError):
925 return False
930 return False
926 return itermeth is dict.__iter__ or itermeth is types.DictProxyType.__iter__
931 return itermeth is dict.__iter__ or itermeth is types.DictProxyType.__iter__
927
932
928
933
929 def _isstr(item):
934 def _isstr(item):
930 if not isinstance(item, basestring):
935 if not isinstance(item, basestring):
931 return False
936 return False
932 try:
937 try:
933 itermeth = item.__class__.__iter__
938 itermeth = item.__class__.__iter__
934 except AttributeError:
939 except AttributeError:
935 return True
940 return True
936 return False # ``__iter__`` has been redefined
941 return False # ``__iter__`` has been redefined
937
942
938
943
939 def xiter(item):
944 def xiter(item):
940 """
945 """
941 Generic function that implements iteration for pipeline expression. If no
946 Generic function that implements iteration for pipeline expression. If no
942 implementation is registered for ``item`` ``xiter`` falls back to ``iter``.
947 implementation is registered for ``item`` ``xiter`` falls back to ``iter``.
943 """
948 """
944 try:
949 try:
945 func = item.__xiter__
950 func = item.__xiter__
946 except AttributeError:
951 except AttributeError:
947 if _isdict(item):
952 if _isdict(item):
948 def items(item):
953 def items(item):
949 fields = ("key", "value")
954 fields = ("key", "value")
950 for (key, value) in item.iteritems():
955 for (key, value) in item.iteritems():
951 yield Fields(fields, key=key, value=value)
956 yield Fields(fields, key=key, value=value)
952 return items(item)
957 return items(item)
953 elif isinstance(item, new.module):
958 elif isinstance(item, new.module):
954 def items(item):
959 def items(item):
955 fields = ("key", "value")
960 fields = ("key", "value")
956 for key in sorted(item.__dict__):
961 for key in sorted(item.__dict__):
957 yield Fields(fields, key=key, value=getattr(item, key))
962 yield Fields(fields, key=key, value=getattr(item, key))
958 return items(item)
963 return items(item)
959 elif _isstr(item):
964 elif _isstr(item):
960 if not item:
965 if not item:
961 raise ValueError("can't enter empty string")
966 raise ValueError("can't enter empty string")
962 lines = item.splitlines()
967 lines = item.splitlines()
963 if len(lines) == 1:
968 if len(lines) == 1:
964 def iterone(item):
969 def iterone(item):
965 yield item
970 yield item
966 return iterone(item)
971 return iterone(item)
967 else:
972 else:
968 return iter(lines)
973 return iter(lines)
969 return iter(item)
974 return iter(item)
970 else:
975 else:
971 return iter(func()) # iter() just to be safe
976 return iter(func()) # iter() just to be safe
972 xiter = simplegeneric.generic(xiter)
977 xiter = simplegeneric.generic(xiter)
973
978
974
979
975 class ichain(Pipe):
980 class ichain(Pipe):
976 """
981 """
977 Chains multiple ``Table``s into one.
982 Chains multiple ``Table``s into one.
978 """
983 """
979
984
980 def __init__(self, *iters):
985 def __init__(self, *iters):
981 self.iters = iters
986 self.iters = iters
982
987
983 def __iter__(self):
988 def __iter__(self):
984 return itertools.chain(*self.iters)
989 return itertools.chain(*self.iters)
985
990
986 def __xrepr__(self, mode="default"):
991 def __xrepr__(self, mode="default"):
987 if mode == "header" or mode == "footer":
992 if mode == "header" or mode == "footer":
988 for (i, item) in enumerate(self.iters):
993 for (i, item) in enumerate(self.iters):
989 if i:
994 if i:
990 yield (astyle.style_default, "+")
995 yield (astyle.style_default, "+")
991 if isinstance(item, Pipe):
996 if isinstance(item, Pipe):
992 yield (astyle.style_default, "(")
997 yield (astyle.style_default, "(")
993 for part in xrepr(item, mode):
998 for part in xrepr(item, mode):
994 yield part
999 yield part
995 if isinstance(item, Pipe):
1000 if isinstance(item, Pipe):
996 yield (astyle.style_default, ")")
1001 yield (astyle.style_default, ")")
997 else:
1002 else:
998 yield (astyle.style_default, repr(self))
1003 yield (astyle.style_default, repr(self))
999
1004
1000 def __repr__(self):
1005 def __repr__(self):
1001 args = ", ".join([repr(it) for it in self.iters])
1006 args = ", ".join([repr(it) for it in self.iters])
1002 return "%s.%s(%s)" % \
1007 return "%s.%s(%s)" % \
1003 (self.__class__.__module__, self.__class__.__name__, args)
1008 (self.__class__.__module__, self.__class__.__name__, args)
1004
1009
1005
1010
1006 class ifile(path.path):
1011 class ifile(path.path):
1007 """
1012 """
1008 file (or directory) object.
1013 file (or directory) object.
1009 """
1014 """
1010
1015
1011 def getmode(self):
1016 def getmode(self):
1012 return self.stat().st_mode
1017 return self.stat().st_mode
1013 mode = property(getmode, None, None, "Access mode")
1018 mode = property(getmode, None, None, "Access mode")
1014
1019
1015 def gettype(self):
1020 def gettype(self):
1016 data = [
1021 data = [
1017 (stat.S_ISREG, "file"),
1022 (stat.S_ISREG, "file"),
1018 (stat.S_ISDIR, "dir"),
1023 (stat.S_ISDIR, "dir"),
1019 (stat.S_ISCHR, "chardev"),
1024 (stat.S_ISCHR, "chardev"),
1020 (stat.S_ISBLK, "blockdev"),
1025 (stat.S_ISBLK, "blockdev"),
1021 (stat.S_ISFIFO, "fifo"),
1026 (stat.S_ISFIFO, "fifo"),
1022 (stat.S_ISLNK, "symlink"),
1027 (stat.S_ISLNK, "symlink"),
1023 (stat.S_ISSOCK,"socket"),
1028 (stat.S_ISSOCK,"socket"),
1024 ]
1029 ]
1025 lstat = self.lstat()
1030 lstat = self.lstat()
1026 if lstat is not None:
1031 if lstat is not None:
1027 types = set([text for (func, text) in data if func(lstat.st_mode)])
1032 types = set([text for (func, text) in data if func(lstat.st_mode)])
1028 else:
1033 else:
1029 types = set()
1034 types = set()
1030 m = self.mode
1035 m = self.mode
1031 types.update([text for (func, text) in data if func(m)])
1036 types.update([text for (func, text) in data if func(m)])
1032 return ", ".join(types)
1037 return ", ".join(types)
1033 type = property(gettype, None, None, "file type (file, directory, link, etc.)")
1038 type = property(gettype, None, None, "file type (file, directory, link, etc.)")
1034
1039
1035 def getmodestr(self):
1040 def getmodestr(self):
1036 m = self.mode
1041 m = self.mode
1037 data = [
1042 data = [
1038 (stat.S_IRUSR, "-r"),
1043 (stat.S_IRUSR, "-r"),
1039 (stat.S_IWUSR, "-w"),
1044 (stat.S_IWUSR, "-w"),
1040 (stat.S_IXUSR, "-x"),
1045 (stat.S_IXUSR, "-x"),
1041 (stat.S_IRGRP, "-r"),
1046 (stat.S_IRGRP, "-r"),
1042 (stat.S_IWGRP, "-w"),
1047 (stat.S_IWGRP, "-w"),
1043 (stat.S_IXGRP, "-x"),
1048 (stat.S_IXGRP, "-x"),
1044 (stat.S_IROTH, "-r"),
1049 (stat.S_IROTH, "-r"),
1045 (stat.S_IWOTH, "-w"),
1050 (stat.S_IWOTH, "-w"),
1046 (stat.S_IXOTH, "-x"),
1051 (stat.S_IXOTH, "-x"),
1047 ]
1052 ]
1048 return "".join([text[bool(m&bit)] for (bit, text) in data])
1053 return "".join([text[bool(m&bit)] for (bit, text) in data])
1049
1054
1050 modestr = property(getmodestr, None, None, "Access mode as string")
1055 modestr = property(getmodestr, None, None, "Access mode as string")
1051
1056
1052 def getblocks(self):
1057 def getblocks(self):
1053 return self.stat().st_blocks
1058 return self.stat().st_blocks
1054 blocks = property(getblocks, None, None, "File size in blocks")
1059 blocks = property(getblocks, None, None, "File size in blocks")
1055
1060
1056 def getblksize(self):
1061 def getblksize(self):
1057 return self.stat().st_blksize
1062 return self.stat().st_blksize
1058 blksize = property(getblksize, None, None, "Filesystem block size")
1063 blksize = property(getblksize, None, None, "Filesystem block size")
1059
1064
1060 def getdev(self):
1065 def getdev(self):
1061 return self.stat().st_dev
1066 return self.stat().st_dev
1062 dev = property(getdev)
1067 dev = property(getdev)
1063
1068
1064 def getnlink(self):
1069 def getnlink(self):
1065 return self.stat().st_nlink
1070 return self.stat().st_nlink
1066 nlink = property(getnlink, None, None, "Number of links")
1071 nlink = property(getnlink, None, None, "Number of links")
1067
1072
1068 def getuid(self):
1073 def getuid(self):
1069 return self.stat().st_uid
1074 return self.stat().st_uid
1070 uid = property(getuid, None, None, "User id of file owner")
1075 uid = property(getuid, None, None, "User id of file owner")
1071
1076
1072 def getgid(self):
1077 def getgid(self):
1073 return self.stat().st_gid
1078 return self.stat().st_gid
1074 gid = property(getgid, None, None, "Group id of file owner")
1079 gid = property(getgid, None, None, "Group id of file owner")
1075
1080
1076 def getowner(self):
1081 def getowner(self):
1077 stat = self.stat()
1082 stat = self.stat()
1078 try:
1083 try:
1079 return pwd.getpwuid(stat.st_uid).pw_name
1084 return pwd.getpwuid(stat.st_uid).pw_name
1080 except KeyError:
1085 except KeyError:
1081 return stat.st_uid
1086 return stat.st_uid
1082 owner = property(getowner, None, None, "Owner name (or id)")
1087 owner = property(getowner, None, None, "Owner name (or id)")
1083
1088
1084 def getgroup(self):
1089 def getgroup(self):
1085 stat = self.stat()
1090 stat = self.stat()
1086 try:
1091 try:
1087 return grp.getgrgid(stat.st_gid).gr_name
1092 return grp.getgrgid(stat.st_gid).gr_name
1088 except KeyError:
1093 except KeyError:
1089 return stat.st_gid
1094 return stat.st_gid
1090 group = property(getgroup, None, None, "Group name (or id)")
1095 group = property(getgroup, None, None, "Group name (or id)")
1091
1096
1092 def getadate(self):
1097 def getadate(self):
1093 return datetime.datetime.utcfromtimestamp(self.atime)
1098 return datetime.datetime.utcfromtimestamp(self.atime)
1094 adate = property(getadate, None, None, "Access date")
1099 adate = property(getadate, None, None, "Access date")
1095
1100
1096 def getcdate(self):
1101 def getcdate(self):
1097 return datetime.datetime.utcfromtimestamp(self.ctime)
1102 return datetime.datetime.utcfromtimestamp(self.ctime)
1098 cdate = property(getcdate, None, None, "Creation date")
1103 cdate = property(getcdate, None, None, "Creation date")
1099
1104
1100 def getmdate(self):
1105 def getmdate(self):
1101 return datetime.datetime.utcfromtimestamp(self.mtime)
1106 return datetime.datetime.utcfromtimestamp(self.mtime)
1102 mdate = property(getmdate, None, None, "Modification date")
1107 mdate = property(getmdate, None, None, "Modification date")
1103
1108
1104 def mimetype(self):
1109 def mimetype(self):
1105 """
1110 """
1106 Return MIME type guessed from the extension.
1111 Return MIME type guessed from the extension.
1107 """
1112 """
1108 return mimetypes.guess_type(self.basename())[0]
1113 return mimetypes.guess_type(self.basename())[0]
1109
1114
1110 def encoding(self):
1115 def encoding(self):
1111 """
1116 """
1112 Return guessed compression (like "compress" or "gzip").
1117 Return guessed compression (like "compress" or "gzip").
1113 """
1118 """
1114 return mimetypes.guess_type(self.basename())[1]
1119 return mimetypes.guess_type(self.basename())[1]
1115
1120
1116 def __repr__(self):
1121 def __repr__(self):
1117 return "ifile(%s)" % path._base.__repr__(self)
1122 return "ifile(%s)" % path._base.__repr__(self)
1118
1123
1119 if sys.platform == "win32":
1124 if sys.platform == "win32":
1120 defaultattrs = (None, "type", "size", "modestr", "mdate")
1125 defaultattrs = (None, "type", "size", "modestr", "mdate")
1121 else:
1126 else:
1122 defaultattrs = (None, "type", "size", "modestr", "owner", "group", "mdate")
1127 defaultattrs = (None, "type", "size", "modestr", "owner", "group", "mdate")
1123
1128
1124 def __xattrs__(self, mode="default"):
1129 def __xattrs__(self, mode="default"):
1125 if mode == "detail":
1130 if mode == "detail":
1126 return (
1131 return (
1127 "name",
1132 "name",
1128 "basename()",
1133 "basename()",
1129 "abspath()",
1134 "abspath()",
1130 "realpath()",
1135 "realpath()",
1131 "type",
1136 "type",
1132 "mode",
1137 "mode",
1133 "modestr",
1138 "modestr",
1134 "stat()",
1139 "stat()",
1135 "lstat()",
1140 "lstat()",
1136 "uid",
1141 "uid",
1137 "gid",
1142 "gid",
1138 "owner",
1143 "owner",
1139 "group",
1144 "group",
1140 "dev",
1145 "dev",
1141 "nlink",
1146 "nlink",
1142 "ctime",
1147 "ctime",
1143 "mtime",
1148 "mtime",
1144 "atime",
1149 "atime",
1145 "cdate",
1150 "cdate",
1146 "mdate",
1151 "mdate",
1147 "adate",
1152 "adate",
1148 "size",
1153 "size",
1149 "blocks",
1154 "blocks",
1150 "blksize",
1155 "blksize",
1151 "isdir()",
1156 "isdir()",
1152 "islink()",
1157 "islink()",
1153 "mimetype()",
1158 "mimetype()",
1154 "encoding()",
1159 "encoding()",
1155 "-listdir()",
1160 "-listdir()",
1156 "-dirs()",
1161 "-dirs()",
1157 "-files()",
1162 "-files()",
1158 "-walk()",
1163 "-walk()",
1159 "-walkdirs()",
1164 "-walkdirs()",
1160 "-walkfiles()",
1165 "-walkfiles()",
1161 )
1166 )
1162 else:
1167 else:
1163 return self.defaultattrs
1168 return self.defaultattrs
1164
1169
1165
1170
1166 def xiter_ifile(self):
1171 def xiter_ifile(self):
1167 if self.isdir():
1172 if self.isdir():
1168 yield (self / os.pardir).abspath()
1173 yield (self / os.pardir).abspath()
1169 for child in sorted(self.listdir()):
1174 for child in sorted(self.listdir()):
1170 yield child
1175 yield child
1171 else:
1176 else:
1172 f = self.open("rb")
1177 f = self.open("rb")
1173 for line in f:
1178 for line in f:
1174 yield line
1179 yield line
1175 f.close()
1180 f.close()
1176 xiter.when_type(ifile)(xiter_ifile)
1181 xiter.when_type(ifile)(xiter_ifile)
1177
1182
1178
1183
1179 # We need to implement ``xrepr`` for ``ifile`` as a generic function, because
1184 # We need to implement ``xrepr`` for ``ifile`` as a generic function, because
1180 # otherwise ``xrepr_str`` would kick in.
1185 # otherwise ``xrepr_str`` would kick in.
1181 def xrepr_ifile(self, mode="default"):
1186 def xrepr_ifile(self, mode="default"):
1182 try:
1187 try:
1183 if self.isdir():
1188 if self.isdir():
1184 name = "idir"
1189 name = "idir"
1185 style = astyle.style_dir
1190 style = astyle.style_dir
1186 else:
1191 else:
1187 name = "ifile"
1192 name = "ifile"
1188 style = astyle.style_file
1193 style = astyle.style_file
1189 except IOError:
1194 except IOError:
1190 name = "ifile"
1195 name = "ifile"
1191 style = astyle.style_default
1196 style = astyle.style_default
1192 if mode in ("cell", "header", "footer"):
1197 if mode in ("cell", "header", "footer"):
1193 abspath = repr(path._base(self.normpath()))
1198 abspath = repr(path._base(self.normpath()))
1194 if abspath.startswith("u"):
1199 if abspath.startswith("u"):
1195 abspath = abspath[2:-1]
1200 abspath = abspath[2:-1]
1196 else:
1201 else:
1197 abspath = abspath[1:-1]
1202 abspath = abspath[1:-1]
1198 if mode == "cell":
1203 if mode == "cell":
1199 yield (style, abspath)
1204 yield (style, abspath)
1200 else:
1205 else:
1201 yield (style, "%s(%s)" % (name, abspath))
1206 yield (style, "%s(%s)" % (name, abspath))
1202 else:
1207 else:
1203 yield (style, repr(self))
1208 yield (style, repr(self))
1204 xrepr.when_type(ifile)(xrepr_ifile)
1209 xrepr.when_type(ifile)(xrepr_ifile)
1205
1210
1206
1211
1207 class ils(Table):
1212 class ils(Table):
1208 """
1213 """
1209 List the current (or a specified) directory.
1214 List the current (or a specified) directory.
1210
1215
1211 Examples::
1216 Examples::
1212
1217
1213 >>> ils
1218 >>> ils
1214 <class 'IPython.Extensions.ipipe.ils'>
1219 <class 'IPython.Extensions.ipipe.ils'>
1215 >>> ils("/usr/local/lib/python2.4")
1220 >>> ils("/usr/local/lib/python2.4")
1216 IPython.Extensions.ipipe.ils('/usr/local/lib/python2.4')
1221 IPython.Extensions.ipipe.ils('/usr/local/lib/python2.4')
1217 >>> ils("~")
1222 >>> ils("~")
1218 IPython.Extensions.ipipe.ils('/home/fperez')
1223 IPython.Extensions.ipipe.ils('/home/fperez')
1219 # all-random
1224 # all-random
1220 """
1225 """
1221 def __init__(self, base=os.curdir, dirs=True, files=True):
1226 def __init__(self, base=os.curdir, dirs=True, files=True):
1222 self.base = os.path.expanduser(base)
1227 self.base = os.path.expanduser(base)
1223 self.dirs = dirs
1228 self.dirs = dirs
1224 self.files = files
1229 self.files = files
1225
1230
1226 def __iter__(self):
1231 def __iter__(self):
1227 base = ifile(self.base)
1232 base = ifile(self.base)
1228 yield (base / os.pardir).abspath()
1233 yield (base / os.pardir).abspath()
1229 for child in sorted(base.listdir()):
1234 for child in sorted(base.listdir()):
1230 if self.dirs:
1235 if self.dirs:
1231 if self.files:
1236 if self.files:
1232 yield child
1237 yield child
1233 else:
1238 else:
1234 if child.isdir():
1239 if child.isdir():
1235 yield child
1240 yield child
1236 elif self.files:
1241 elif self.files:
1237 if not child.isdir():
1242 if not child.isdir():
1238 yield child
1243 yield child
1239
1244
1240 def __xrepr__(self, mode="default"):
1245 def __xrepr__(self, mode="default"):
1241 return xrepr(ifile(self.base), mode)
1246 return xrepr(ifile(self.base), mode)
1242
1247
1243 def __repr__(self):
1248 def __repr__(self):
1244 return "%s.%s(%r)" % \
1249 return "%s.%s(%r)" % \
1245 (self.__class__.__module__, self.__class__.__name__, self.base)
1250 (self.__class__.__module__, self.__class__.__name__, self.base)
1246
1251
1247
1252
1248 class iglob(Table):
1253 class iglob(Table):
1249 """
1254 """
1250 List all files and directories matching a specified pattern.
1255 List all files and directories matching a specified pattern.
1251 (See ``glob.glob()`` for more info.).
1256 (See ``glob.glob()`` for more info.).
1252
1257
1253 Examples::
1258 Examples::
1254
1259
1255 >>> iglob("*.py")
1260 >>> iglob("*.py")
1256 IPython.Extensions.ipipe.iglob('*.py')
1261 IPython.Extensions.ipipe.iglob('*.py')
1257 """
1262 """
1258 def __init__(self, glob):
1263 def __init__(self, glob):
1259 self.glob = glob
1264 self.glob = glob
1260
1265
1261 def __iter__(self):
1266 def __iter__(self):
1262 for name in glob.glob(self.glob):
1267 for name in glob.glob(self.glob):
1263 yield ifile(name)
1268 yield ifile(name)
1264
1269
1265 def __xrepr__(self, mode="default"):
1270 def __xrepr__(self, mode="default"):
1266 if mode == "header" or mode == "footer" or mode == "cell":
1271 if mode == "header" or mode == "footer" or mode == "cell":
1267 yield (astyle.style_default,
1272 yield (astyle.style_default,
1268 "%s(%r)" % (self.__class__.__name__, self.glob))
1273 "%s(%r)" % (self.__class__.__name__, self.glob))
1269 else:
1274 else:
1270 yield (astyle.style_default, repr(self))
1275 yield (astyle.style_default, repr(self))
1271
1276
1272 def __repr__(self):
1277 def __repr__(self):
1273 return "%s.%s(%r)" % \
1278 return "%s.%s(%r)" % \
1274 (self.__class__.__module__, self.__class__.__name__, self.glob)
1279 (self.__class__.__module__, self.__class__.__name__, self.glob)
1275
1280
1276
1281
1277 class iwalk(Table):
1282 class iwalk(Table):
1278 """
1283 """
1279 List all files and directories in a directory and it's subdirectory::
1284 List all files and directories in a directory and it's subdirectory::
1280
1285
1281 >>> iwalk
1286 >>> iwalk
1282 <class 'IPython.Extensions.ipipe.iwalk'>
1287 <class 'IPython.Extensions.ipipe.iwalk'>
1283 >>> iwalk("/usr/lib")
1288 >>> iwalk("/usr/lib")
1284 IPython.Extensions.ipipe.iwalk('/usr/lib')
1289 IPython.Extensions.ipipe.iwalk('/usr/lib')
1285 >>> iwalk("~")
1290 >>> iwalk("~")
1286 IPython.Extensions.ipipe.iwalk('/home/fperez') # random
1291 IPython.Extensions.ipipe.iwalk('/home/fperez') # random
1287
1292
1288 """
1293 """
1289 def __init__(self, base=os.curdir, dirs=True, files=True):
1294 def __init__(self, base=os.curdir, dirs=True, files=True):
1290 self.base = os.path.expanduser(base)
1295 self.base = os.path.expanduser(base)
1291 self.dirs = dirs
1296 self.dirs = dirs
1292 self.files = files
1297 self.files = files
1293
1298
1294 def __iter__(self):
1299 def __iter__(self):
1295 for (dirpath, dirnames, filenames) in os.walk(self.base):
1300 for (dirpath, dirnames, filenames) in os.walk(self.base):
1296 if self.dirs:
1301 if self.dirs:
1297 for name in sorted(dirnames):
1302 for name in sorted(dirnames):
1298 yield ifile(os.path.join(dirpath, name))
1303 yield ifile(os.path.join(dirpath, name))
1299 if self.files:
1304 if self.files:
1300 for name in sorted(filenames):
1305 for name in sorted(filenames):
1301 yield ifile(os.path.join(dirpath, name))
1306 yield ifile(os.path.join(dirpath, name))
1302
1307
1303 def __xrepr__(self, mode="default"):
1308 def __xrepr__(self, mode="default"):
1304 if mode == "header" or mode == "footer" or mode == "cell":
1309 if mode == "header" or mode == "footer" or mode == "cell":
1305 yield (astyle.style_default,
1310 yield (astyle.style_default,
1306 "%s(%r)" % (self.__class__.__name__, self.base))
1311 "%s(%r)" % (self.__class__.__name__, self.base))
1307 else:
1312 else:
1308 yield (astyle.style_default, repr(self))
1313 yield (astyle.style_default, repr(self))
1309
1314
1310 def __repr__(self):
1315 def __repr__(self):
1311 return "%s.%s(%r)" % \
1316 return "%s.%s(%r)" % \
1312 (self.__class__.__module__, self.__class__.__name__, self.base)
1317 (self.__class__.__module__, self.__class__.__name__, self.base)
1313
1318
1314
1319
1315 class ipwdentry(object):
1320 class ipwdentry(object):
1316 """
1321 """
1317 ``ipwdentry`` objects encapsulate entries in the Unix user account and
1322 ``ipwdentry`` objects encapsulate entries in the Unix user account and
1318 password database.
1323 password database.
1319 """
1324 """
1320 def __init__(self, id):
1325 def __init__(self, id):
1321 self._id = id
1326 self._id = id
1322 self._entry = None
1327 self._entry = None
1323
1328
1324 def __eq__(self, other):
1329 def __eq__(self, other):
1325 return self.__class__ is other.__class__ and self._id == other._id
1330 return self.__class__ is other.__class__ and self._id == other._id
1326
1331
1327 def __ne__(self, other):
1332 def __ne__(self, other):
1328 return self.__class__ is not other.__class__ or self._id != other._id
1333 return self.__class__ is not other.__class__ or self._id != other._id
1329
1334
1330 def _getentry(self):
1335 def _getentry(self):
1331 if self._entry is None:
1336 if self._entry is None:
1332 if isinstance(self._id, basestring):
1337 if isinstance(self._id, basestring):
1333 self._entry = pwd.getpwnam(self._id)
1338 self._entry = pwd.getpwnam(self._id)
1334 else:
1339 else:
1335 self._entry = pwd.getpwuid(self._id)
1340 self._entry = pwd.getpwuid(self._id)
1336 return self._entry
1341 return self._entry
1337
1342
1338 def getname(self):
1343 def getname(self):
1339 if isinstance(self._id, basestring):
1344 if isinstance(self._id, basestring):
1340 return self._id
1345 return self._id
1341 else:
1346 else:
1342 return self._getentry().pw_name
1347 return self._getentry().pw_name
1343 name = property(getname, None, None, "User name")
1348 name = property(getname, None, None, "User name")
1344
1349
1345 def getpasswd(self):
1350 def getpasswd(self):
1346 return self._getentry().pw_passwd
1351 return self._getentry().pw_passwd
1347 passwd = property(getpasswd, None, None, "Password")
1352 passwd = property(getpasswd, None, None, "Password")
1348
1353
1349 def getuid(self):
1354 def getuid(self):
1350 if isinstance(self._id, basestring):
1355 if isinstance(self._id, basestring):
1351 return self._getentry().pw_uid
1356 return self._getentry().pw_uid
1352 else:
1357 else:
1353 return self._id
1358 return self._id
1354 uid = property(getuid, None, None, "User id")
1359 uid = property(getuid, None, None, "User id")
1355
1360
1356 def getgid(self):
1361 def getgid(self):
1357 return self._getentry().pw_gid
1362 return self._getentry().pw_gid
1358 gid = property(getgid, None, None, "Primary group id")
1363 gid = property(getgid, None, None, "Primary group id")
1359
1364
1360 def getgroup(self):
1365 def getgroup(self):
1361 return igrpentry(self.gid)
1366 return igrpentry(self.gid)
1362 group = property(getgroup, None, None, "Group")
1367 group = property(getgroup, None, None, "Group")
1363
1368
1364 def getgecos(self):
1369 def getgecos(self):
1365 return self._getentry().pw_gecos
1370 return self._getentry().pw_gecos
1366 gecos = property(getgecos, None, None, "Information (e.g. full user name)")
1371 gecos = property(getgecos, None, None, "Information (e.g. full user name)")
1367
1372
1368 def getdir(self):
1373 def getdir(self):
1369 return self._getentry().pw_dir
1374 return self._getentry().pw_dir
1370 dir = property(getdir, None, None, "$HOME directory")
1375 dir = property(getdir, None, None, "$HOME directory")
1371
1376
1372 def getshell(self):
1377 def getshell(self):
1373 return self._getentry().pw_shell
1378 return self._getentry().pw_shell
1374 shell = property(getshell, None, None, "Login shell")
1379 shell = property(getshell, None, None, "Login shell")
1375
1380
1376 def __xattrs__(self, mode="default"):
1381 def __xattrs__(self, mode="default"):
1377 return ("name", "passwd", "uid", "gid", "gecos", "dir", "shell")
1382 return ("name", "passwd", "uid", "gid", "gecos", "dir", "shell")
1378
1383
1379 def __repr__(self):
1384 def __repr__(self):
1380 return "%s.%s(%r)" % \
1385 return "%s.%s(%r)" % \
1381 (self.__class__.__module__, self.__class__.__name__, self._id)
1386 (self.__class__.__module__, self.__class__.__name__, self._id)
1382
1387
1383
1388
1384 class ipwd(Table):
1389 class ipwd(Table):
1385 """
1390 """
1386 List all entries in the Unix user account and password database.
1391 List all entries in the Unix user account and password database.
1387
1392
1388 Example::
1393 Example::
1389
1394
1390 >>> ipwd | isort("uid")
1395 >>> ipwd | isort("uid")
1391 <IPython.Extensions.ipipe.isort key='uid' reverse=False at 0x849efec>
1396 <IPython.Extensions.ipipe.isort key='uid' reverse=False at 0x849efec>
1392 # random
1397 # random
1393 """
1398 """
1394 def __iter__(self):
1399 def __iter__(self):
1395 for entry in pwd.getpwall():
1400 for entry in pwd.getpwall():
1396 yield ipwdentry(entry.pw_name)
1401 yield ipwdentry(entry.pw_name)
1397
1402
1398 def __xrepr__(self, mode="default"):
1403 def __xrepr__(self, mode="default"):
1399 if mode == "header" or mode == "footer" or mode == "cell":
1404 if mode == "header" or mode == "footer" or mode == "cell":
1400 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1405 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1401 else:
1406 else:
1402 yield (astyle.style_default, repr(self))
1407 yield (astyle.style_default, repr(self))
1403
1408
1404
1409
1405 class igrpentry(object):
1410 class igrpentry(object):
1406 """
1411 """
1407 ``igrpentry`` objects encapsulate entries in the Unix group database.
1412 ``igrpentry`` objects encapsulate entries in the Unix group database.
1408 """
1413 """
1409 def __init__(self, id):
1414 def __init__(self, id):
1410 self._id = id
1415 self._id = id
1411 self._entry = None
1416 self._entry = None
1412
1417
1413 def __eq__(self, other):
1418 def __eq__(self, other):
1414 return self.__class__ is other.__class__ and self._id == other._id
1419 return self.__class__ is other.__class__ and self._id == other._id
1415
1420
1416 def __ne__(self, other):
1421 def __ne__(self, other):
1417 return self.__class__ is not other.__class__ or self._id != other._id
1422 return self.__class__ is not other.__class__ or self._id != other._id
1418
1423
1419 def _getentry(self):
1424 def _getentry(self):
1420 if self._entry is None:
1425 if self._entry is None:
1421 if isinstance(self._id, basestring):
1426 if isinstance(self._id, basestring):
1422 self._entry = grp.getgrnam(self._id)
1427 self._entry = grp.getgrnam(self._id)
1423 else:
1428 else:
1424 self._entry = grp.getgrgid(self._id)
1429 self._entry = grp.getgrgid(self._id)
1425 return self._entry
1430 return self._entry
1426
1431
1427 def getname(self):
1432 def getname(self):
1428 if isinstance(self._id, basestring):
1433 if isinstance(self._id, basestring):
1429 return self._id
1434 return self._id
1430 else:
1435 else:
1431 return self._getentry().gr_name
1436 return self._getentry().gr_name
1432 name = property(getname, None, None, "Group name")
1437 name = property(getname, None, None, "Group name")
1433
1438
1434 def getpasswd(self):
1439 def getpasswd(self):
1435 return self._getentry().gr_passwd
1440 return self._getentry().gr_passwd
1436 passwd = property(getpasswd, None, None, "Password")
1441 passwd = property(getpasswd, None, None, "Password")
1437
1442
1438 def getgid(self):
1443 def getgid(self):
1439 if isinstance(self._id, basestring):
1444 if isinstance(self._id, basestring):
1440 return self._getentry().gr_gid
1445 return self._getentry().gr_gid
1441 else:
1446 else:
1442 return self._id
1447 return self._id
1443 gid = property(getgid, None, None, "Group id")
1448 gid = property(getgid, None, None, "Group id")
1444
1449
1445 def getmem(self):
1450 def getmem(self):
1446 return self._getentry().gr_mem
1451 return self._getentry().gr_mem
1447 mem = property(getmem, None, None, "Members")
1452 mem = property(getmem, None, None, "Members")
1448
1453
1449 def __xattrs__(self, mode="default"):
1454 def __xattrs__(self, mode="default"):
1450 return ("name", "passwd", "gid", "mem")
1455 return ("name", "passwd", "gid", "mem")
1451
1456
1452 def __xrepr__(self, mode="default"):
1457 def __xrepr__(self, mode="default"):
1453 if mode == "header" or mode == "footer" or mode == "cell":
1458 if mode == "header" or mode == "footer" or mode == "cell":
1454 yield (astyle.style_default, "group ")
1459 yield (astyle.style_default, "group ")
1455 try:
1460 try:
1456 yield (astyle.style_default, self.name)
1461 yield (astyle.style_default, self.name)
1457 except KeyError:
1462 except KeyError:
1458 if isinstance(self._id, basestring):
1463 if isinstance(self._id, basestring):
1459 yield (astyle.style_default, self.name_id)
1464 yield (astyle.style_default, self.name_id)
1460 else:
1465 else:
1461 yield (astyle.style_type_number, str(self._id))
1466 yield (astyle.style_type_number, str(self._id))
1462 else:
1467 else:
1463 yield (astyle.style_default, repr(self))
1468 yield (astyle.style_default, repr(self))
1464
1469
1465 def __iter__(self):
1470 def __iter__(self):
1466 for member in self.mem:
1471 for member in self.mem:
1467 yield ipwdentry(member)
1472 yield ipwdentry(member)
1468
1473
1469 def __repr__(self):
1474 def __repr__(self):
1470 return "%s.%s(%r)" % \
1475 return "%s.%s(%r)" % \
1471 (self.__class__.__module__, self.__class__.__name__, self._id)
1476 (self.__class__.__module__, self.__class__.__name__, self._id)
1472
1477
1473
1478
1474 class igrp(Table):
1479 class igrp(Table):
1475 """
1480 """
1476 This ``Table`` lists all entries in the Unix group database.
1481 This ``Table`` lists all entries in the Unix group database.
1477 """
1482 """
1478 def __iter__(self):
1483 def __iter__(self):
1479 for entry in grp.getgrall():
1484 for entry in grp.getgrall():
1480 yield igrpentry(entry.gr_name)
1485 yield igrpentry(entry.gr_name)
1481
1486
1482 def __xrepr__(self, mode="default"):
1487 def __xrepr__(self, mode="default"):
1483 if mode == "header" or mode == "footer":
1488 if mode == "header" or mode == "footer":
1484 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1489 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1485 else:
1490 else:
1486 yield (astyle.style_default, repr(self))
1491 yield (astyle.style_default, repr(self))
1487
1492
1488
1493
1489 class Fields(object):
1494 class Fields(object):
1490 def __init__(self, fieldnames, **fields):
1495 def __init__(self, fieldnames, **fields):
1491 self.__fieldnames = [upgradexattr(fieldname) for fieldname in fieldnames]
1496 self.__fieldnames = [upgradexattr(fieldname) for fieldname in fieldnames]
1492 for (key, value) in fields.iteritems():
1497 for (key, value) in fields.iteritems():
1493 setattr(self, key, value)
1498 setattr(self, key, value)
1494
1499
1495 def __xattrs__(self, mode="default"):
1500 def __xattrs__(self, mode="default"):
1496 return self.__fieldnames
1501 return self.__fieldnames
1497
1502
1498 def __xrepr__(self, mode="default"):
1503 def __xrepr__(self, mode="default"):
1499 yield (-1, False)
1504 yield (-1, False)
1500 if mode == "header" or mode == "cell":
1505 if mode == "header" or mode == "cell":
1501 yield (astyle.style_default, self.__class__.__name__)
1506 yield (astyle.style_default, self.__class__.__name__)
1502 yield (astyle.style_default, "(")
1507 yield (astyle.style_default, "(")
1503 for (i, f) in enumerate(self.__fieldnames):
1508 for (i, f) in enumerate(self.__fieldnames):
1504 if i:
1509 if i:
1505 yield (astyle.style_default, ", ")
1510 yield (astyle.style_default, ", ")
1506 yield (astyle.style_default, f.name())
1511 yield (astyle.style_default, f.name())
1507 yield (astyle.style_default, "=")
1512 yield (astyle.style_default, "=")
1508 for part in xrepr(getattr(self, f), "default"):
1513 for part in xrepr(getattr(self, f), "default"):
1509 yield part
1514 yield part
1510 yield (astyle.style_default, ")")
1515 yield (astyle.style_default, ")")
1511 elif mode == "footer":
1516 elif mode == "footer":
1512 yield (astyle.style_default, self.__class__.__name__)
1517 yield (astyle.style_default, self.__class__.__name__)
1513 yield (astyle.style_default, "(")
1518 yield (astyle.style_default, "(")
1514 for (i, f) in enumerate(self.__fieldnames):
1519 for (i, f) in enumerate(self.__fieldnames):
1515 if i:
1520 if i:
1516 yield (astyle.style_default, ", ")
1521 yield (astyle.style_default, ", ")
1517 yield (astyle.style_default, f.name())
1522 yield (astyle.style_default, f.name())
1518 yield (astyle.style_default, ")")
1523 yield (astyle.style_default, ")")
1519 else:
1524 else:
1520 yield (astyle.style_default, repr(self))
1525 yield (astyle.style_default, repr(self))
1521
1526
1522
1527
1523 class FieldTable(Table, list):
1528 class FieldTable(Table, list):
1524 def __init__(self, *fields):
1529 def __init__(self, *fields):
1525 Table.__init__(self)
1530 Table.__init__(self)
1526 list.__init__(self)
1531 list.__init__(self)
1527 self.fields = fields
1532 self.fields = fields
1528
1533
1529 def add(self, **fields):
1534 def add(self, **fields):
1530 self.append(Fields(self.fields, **fields))
1535 self.append(Fields(self.fields, **fields))
1531
1536
1532 def __xrepr__(self, mode="default"):
1537 def __xrepr__(self, mode="default"):
1533 yield (-1, False)
1538 yield (-1, False)
1534 if mode == "header" or mode == "footer":
1539 if mode == "header" or mode == "footer":
1535 yield (astyle.style_default, self.__class__.__name__)
1540 yield (astyle.style_default, self.__class__.__name__)
1536 yield (astyle.style_default, "(")
1541 yield (astyle.style_default, "(")
1537 for (i, f) in enumerate(self.__fieldnames):
1542 for (i, f) in enumerate(self.__fieldnames):
1538 if i:
1543 if i:
1539 yield (astyle.style_default, ", ")
1544 yield (astyle.style_default, ", ")
1540 yield (astyle.style_default, f)
1545 yield (astyle.style_default, f)
1541 yield (astyle.style_default, ")")
1546 yield (astyle.style_default, ")")
1542 else:
1547 else:
1543 yield (astyle.style_default, repr(self))
1548 yield (astyle.style_default, repr(self))
1544
1549
1545 def __repr__(self):
1550 def __repr__(self):
1546 return "<%s.%s object with fields=%r at 0x%x>" % \
1551 return "<%s.%s object with fields=%r at 0x%x>" % \
1547 (self.__class__.__module__, self.__class__.__name__,
1552 (self.__class__.__module__, self.__class__.__name__,
1548 ", ".join(map(repr, self.fields)), id(self))
1553 ", ".join(map(repr, self.fields)), id(self))
1549
1554
1550
1555
1551 class List(list):
1556 class List(list):
1552 def __xattrs__(self, mode="default"):
1557 def __xattrs__(self, mode="default"):
1553 return xrange(len(self))
1558 return xrange(len(self))
1554
1559
1555 def __xrepr__(self, mode="default"):
1560 def __xrepr__(self, mode="default"):
1556 yield (-1, False)
1561 yield (-1, False)
1557 if mode == "header" or mode == "cell" or mode == "footer" or mode == "default":
1562 if mode == "header" or mode == "cell" or mode == "footer" or mode == "default":
1558 yield (astyle.style_default, self.__class__.__name__)
1563 yield (astyle.style_default, self.__class__.__name__)
1559 yield (astyle.style_default, "(")
1564 yield (astyle.style_default, "(")
1560 for (i, item) in enumerate(self):
1565 for (i, item) in enumerate(self):
1561 if i:
1566 if i:
1562 yield (astyle.style_default, ", ")
1567 yield (astyle.style_default, ", ")
1563 for part in xrepr(item, "default"):
1568 for part in xrepr(item, "default"):
1564 yield part
1569 yield part
1565 yield (astyle.style_default, ")")
1570 yield (astyle.style_default, ")")
1566 else:
1571 else:
1567 yield (astyle.style_default, repr(self))
1572 yield (astyle.style_default, repr(self))
1568
1573
1569
1574
1570 class ienv(Table):
1575 class ienv(Table):
1571 """
1576 """
1572 List environment variables.
1577 List environment variables.
1573
1578
1574 Example::
1579 Example::
1575
1580
1576 >>> ienv
1581 >>> ienv
1577 <class 'IPython.Extensions.ipipe.ienv'>
1582 <class 'IPython.Extensions.ipipe.ienv'>
1578 """
1583 """
1579
1584
1580 def __iter__(self):
1585 def __iter__(self):
1581 fields = ("key", "value")
1586 fields = ("key", "value")
1582 for (key, value) in os.environ.iteritems():
1587 for (key, value) in os.environ.iteritems():
1583 yield Fields(fields, key=key, value=value)
1588 yield Fields(fields, key=key, value=value)
1584
1589
1585 def __xrepr__(self, mode="default"):
1590 def __xrepr__(self, mode="default"):
1586 if mode == "header" or mode == "cell":
1591 if mode == "header" or mode == "cell":
1587 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1592 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1588 else:
1593 else:
1589 yield (astyle.style_default, repr(self))
1594 yield (astyle.style_default, repr(self))
1590
1595
1591
1596
1592 class ihist(Table):
1597 class ihist(Table):
1593 """
1598 """
1594 IPython input history
1599 IPython input history
1595
1600
1596 Example::
1601 Example::
1597
1602
1598 >>> ihist
1603 >>> ihist
1599 <class 'IPython.Extensions.ipipe.ihist'>
1604 <class 'IPython.Extensions.ipipe.ihist'>
1600 >>> ihist(True) # raw mode
1605 >>> ihist(True) # raw mode
1601 <IPython.Extensions.ipipe.ihist object at 0x849602c> # random
1606 <IPython.Extensions.ipipe.ihist object at 0x849602c> # random
1602 """
1607 """
1603 def __init__(self, raw=True):
1608 def __init__(self, raw=True):
1604 self.raw = raw
1609 self.raw = raw
1605
1610
1606 def __iter__(self):
1611 def __iter__(self):
1607 api = ipapi.get()
1612 api = ipapi.get()
1608 if self.raw:
1613 if self.raw:
1609 for line in api.IP.input_hist_raw:
1614 for line in api.IP.input_hist_raw:
1610 yield line.rstrip("\n")
1615 yield line.rstrip("\n")
1611 else:
1616 else:
1612 for line in api.IP.input_hist:
1617 for line in api.IP.input_hist:
1613 yield line.rstrip("\n")
1618 yield line.rstrip("\n")
1614
1619
1615
1620
1616 class Alias(object):
1621 class Alias(object):
1617 """
1622 """
1618 Entry in the alias table
1623 Entry in the alias table
1619 """
1624 """
1620 def __init__(self, name, args, command):
1625 def __init__(self, name, args, command):
1621 self.name = name
1626 self.name = name
1622 self.args = args
1627 self.args = args
1623 self.command = command
1628 self.command = command
1624
1629
1625 def __xattrs__(self, mode="default"):
1630 def __xattrs__(self, mode="default"):
1626 return ("name", "args", "command")
1631 return ("name", "args", "command")
1627
1632
1628
1633
1629 class ialias(Table):
1634 class ialias(Table):
1630 """
1635 """
1631 IPython alias list
1636 IPython alias list
1632
1637
1633 Example::
1638 Example::
1634
1639
1635 >>> ialias
1640 >>> ialias
1636 <class 'IPython.Extensions.ipipe.ialias'>
1641 <class 'IPython.Extensions.ipipe.ialias'>
1637 """
1642 """
1638 def __iter__(self):
1643 def __iter__(self):
1639 api = ipapi.get()
1644 api = ipapi.get()
1640
1645
1641 for (name, (args, command)) in api.IP.alias_table.iteritems():
1646 for (name, (args, command)) in api.IP.alias_table.iteritems():
1642 yield Alias(name, args, command)
1647 yield Alias(name, args, command)
1643
1648
1644
1649
1645 class icsv(Pipe):
1650 class icsv(Pipe):
1646 """
1651 """
1647 This ``Pipe`` turns the input (with must be a pipe outputting lines
1652 This ``Pipe`` turns the input (with must be a pipe outputting lines
1648 or an ``ifile``) into lines of CVS columns.
1653 or an ``ifile``) into lines of CVS columns.
1649 """
1654 """
1650 def __init__(self, **csvargs):
1655 def __init__(self, **csvargs):
1651 """
1656 """
1652 Create an ``icsv`` object. ``cvsargs`` will be passed through as
1657 Create an ``icsv`` object. ``cvsargs`` will be passed through as
1653 keyword arguments to ``cvs.reader()``.
1658 keyword arguments to ``cvs.reader()``.
1654 """
1659 """
1655 self.csvargs = csvargs
1660 self.csvargs = csvargs
1656
1661
1657 def __iter__(self):
1662 def __iter__(self):
1658 input = self.input
1663 input = self.input
1659 if isinstance(input, ifile):
1664 if isinstance(input, ifile):
1660 input = input.open("rb")
1665 input = input.open("rb")
1661 reader = csv.reader(input, **self.csvargs)
1666 reader = csv.reader(input, **self.csvargs)
1662 for line in reader:
1667 for line in reader:
1663 yield List(line)
1668 yield List(line)
1664
1669
1665 def __xrepr__(self, mode="default"):
1670 def __xrepr__(self, mode="default"):
1666 yield (-1, False)
1671 yield (-1, False)
1667 if mode == "header" or mode == "footer":
1672 if mode == "header" or mode == "footer":
1668 input = getattr(self, "input", None)
1673 input = getattr(self, "input", None)
1669 if input is not None:
1674 if input is not None:
1670 for part in xrepr(input, mode):
1675 for part in xrepr(input, mode):
1671 yield part
1676 yield part
1672 yield (astyle.style_default, " | ")
1677 yield (astyle.style_default, " | ")
1673 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1678 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1674 for (i, (name, value)) in enumerate(self.csvargs.iteritems()):
1679 for (i, (name, value)) in enumerate(self.csvargs.iteritems()):
1675 if i:
1680 if i:
1676 yield (astyle.style_default, ", ")
1681 yield (astyle.style_default, ", ")
1677 yield (astyle.style_default, name)
1682 yield (astyle.style_default, name)
1678 yield (astyle.style_default, "=")
1683 yield (astyle.style_default, "=")
1679 for part in xrepr(value, "default"):
1684 for part in xrepr(value, "default"):
1680 yield part
1685 yield part
1681 yield (astyle.style_default, ")")
1686 yield (astyle.style_default, ")")
1682 else:
1687 else:
1683 yield (astyle.style_default, repr(self))
1688 yield (astyle.style_default, repr(self))
1684
1689
1685 def __repr__(self):
1690 def __repr__(self):
1686 args = ", ".join(["%s=%r" % item for item in self.csvargs.iteritems()])
1691 args = ", ".join(["%s=%r" % item for item in self.csvargs.iteritems()])
1687 return "<%s.%s %s at 0x%x>" % \
1692 return "<%s.%s %s at 0x%x>" % \
1688 (self.__class__.__module__, self.__class__.__name__, args, id(self))
1693 (self.__class__.__module__, self.__class__.__name__, args, id(self))
1689
1694
1690
1695
1691 class ix(Table):
1696 class ix(Table):
1692 """
1697 """
1693 Execute a system command and list its output as lines
1698 Execute a system command and list its output as lines
1694 (similar to ``os.popen()``).
1699 (similar to ``os.popen()``).
1695
1700
1696 Examples::
1701 Examples::
1697
1702
1698 >>> ix("ps x")
1703 >>> ix("ps x")
1699 IPython.Extensions.ipipe.ix('ps x')
1704 IPython.Extensions.ipipe.ix('ps x')
1700
1705
1701 >>> ix("find .") | ifile
1706 >>> ix("find .") | ifile
1702 <IPython.Extensions.ipipe.ieval expr=<class 'IPython.Extensions.ipipe.ifile'> at 0x8509d2c>
1707 <IPython.Extensions.ipipe.ieval expr=<class 'IPython.Extensions.ipipe.ifile'> at 0x8509d2c>
1703 # random
1708 # random
1704 """
1709 """
1705 def __init__(self, cmd):
1710 def __init__(self, cmd):
1706 self.cmd = cmd
1711 self.cmd = cmd
1707 self._pipeout = None
1712 self._pipeout = None
1708
1713
1709 def __iter__(self):
1714 def __iter__(self):
1710 (_pipein, self._pipeout) = os.popen4(self.cmd)
1715 (_pipein, self._pipeout) = os.popen4(self.cmd)
1711 _pipein.close()
1716 _pipein.close()
1712 for l in self._pipeout:
1717 for l in self._pipeout:
1713 yield l.rstrip("\r\n")
1718 yield l.rstrip("\r\n")
1714 self._pipeout.close()
1719 self._pipeout.close()
1715 self._pipeout = None
1720 self._pipeout = None
1716
1721
1717 def __del__(self):
1722 def __del__(self):
1718 if self._pipeout is not None and not self._pipeout.closed:
1723 if self._pipeout is not None and not self._pipeout.closed:
1719 self._pipeout.close()
1724 self._pipeout.close()
1720 self._pipeout = None
1725 self._pipeout = None
1721
1726
1722 def __xrepr__(self, mode="default"):
1727 def __xrepr__(self, mode="default"):
1723 if mode == "header" or mode == "footer":
1728 if mode == "header" or mode == "footer":
1724 yield (astyle.style_default,
1729 yield (astyle.style_default,
1725 "%s(%r)" % (self.__class__.__name__, self.cmd))
1730 "%s(%r)" % (self.__class__.__name__, self.cmd))
1726 else:
1731 else:
1727 yield (astyle.style_default, repr(self))
1732 yield (astyle.style_default, repr(self))
1728
1733
1729 def __repr__(self):
1734 def __repr__(self):
1730 return "%s.%s(%r)" % \
1735 return "%s.%s(%r)" % \
1731 (self.__class__.__module__, self.__class__.__name__, self.cmd)
1736 (self.__class__.__module__, self.__class__.__name__, self.cmd)
1732
1737
1733
1738
1734 class ifilter(Pipe):
1739 class ifilter(Pipe):
1735 """
1740 """
1736 Filter an input pipe. Only objects where an expression evaluates to true
1741 Filter an input pipe. Only objects where an expression evaluates to true
1737 (and doesn't raise an exception) are listed.
1742 (and doesn't raise an exception) are listed.
1738
1743
1739 Examples::
1744 Examples::
1740
1745
1741 >>> ils | ifilter("_.isfile() and size>1000")
1746 >>> ils | ifilter("_.isfile() and size>1000")
1742 >>> igrp | ifilter("len(mem)")
1747 >>> igrp | ifilter("len(mem)")
1743 >>> sys.modules | ifilter(lambda _:_.value is not None)
1748 >>> sys.modules | ifilter(lambda _:_.value is not None)
1744 # all-random
1749 # all-random
1745 """
1750 """
1746
1751
1747 def __init__(self, expr, globals=None, errors="raiseifallfail"):
1752 def __init__(self, expr, globals=None, errors="raiseifallfail"):
1748 """
1753 """
1749 Create an ``ifilter`` object. ``expr`` can be a callable or a string
1754 Create an ``ifilter`` object. ``expr`` can be a callable or a string
1750 containing an expression. ``globals`` will be used as the global
1755 containing an expression. ``globals`` will be used as the global
1751 namespace for calling string expressions (defaulting to IPython's
1756 namespace for calling string expressions (defaulting to IPython's
1752 user namespace). ``errors`` specifies how exception during evaluation
1757 user namespace). ``errors`` specifies how exception during evaluation
1753 of ``expr`` are handled:
1758 of ``expr`` are handled:
1754
1759
1755 ``"drop"``
1760 ``"drop"``
1756 drop all items that have errors;
1761 drop all items that have errors;
1757
1762
1758 ``"keep"``
1763 ``"keep"``
1759 keep all items that have errors;
1764 keep all items that have errors;
1760
1765
1761 ``"keeperror"``
1766 ``"keeperror"``
1762 keep the exception of all items that have errors;
1767 keep the exception of all items that have errors;
1763
1768
1764 ``"raise"``
1769 ``"raise"``
1765 raise the exception;
1770 raise the exception;
1766
1771
1767 ``"raiseifallfail"``
1772 ``"raiseifallfail"``
1768 raise the first exception if all items have errors; otherwise drop
1773 raise the first exception if all items have errors; otherwise drop
1769 those with errors (this is the default).
1774 those with errors (this is the default).
1770 """
1775 """
1771 self.expr = expr
1776 self.expr = expr
1772 self.globals = globals
1777 self.globals = globals
1773 self.errors = errors
1778 self.errors = errors
1774
1779
1775 def __iter__(self):
1780 def __iter__(self):
1776 if callable(self.expr):
1781 if callable(self.expr):
1777 test = self.expr
1782 test = self.expr
1778 else:
1783 else:
1779 g = getglobals(self.globals)
1784 g = getglobals(self.globals)
1780 expr = compile(self.expr, "ipipe-expression", "eval")
1785 expr = compile(self.expr, "ipipe-expression", "eval")
1781 def test(item):
1786 def test(item):
1782 return eval(expr, g, AttrNamespace(item))
1787 return eval(expr, g, AttrNamespace(item))
1783
1788
1784 ok = 0
1789 ok = 0
1785 exc_info = None
1790 exc_info = None
1786 for item in xiter(self.input):
1791 for item in xiter(self.input):
1787 try:
1792 try:
1788 if test(item):
1793 if test(item):
1789 yield item
1794 yield item
1790 ok += 1
1795 ok += 1
1791 except (KeyboardInterrupt, SystemExit):
1796 except (KeyboardInterrupt, SystemExit):
1792 raise
1797 raise
1793 except Exception, exc:
1798 except Exception, exc:
1794 if self.errors == "drop":
1799 if self.errors == "drop":
1795 pass # Ignore errors
1800 pass # Ignore errors
1796 elif self.errors == "keep":
1801 elif self.errors == "keep":
1797 yield item
1802 yield item
1798 elif self.errors == "keeperror":
1803 elif self.errors == "keeperror":
1799 yield exc
1804 yield exc
1800 elif self.errors == "raise":
1805 elif self.errors == "raise":
1801 raise
1806 raise
1802 elif self.errors == "raiseifallfail":
1807 elif self.errors == "raiseifallfail":
1803 if exc_info is None:
1808 if exc_info is None:
1804 exc_info = sys.exc_info()
1809 exc_info = sys.exc_info()
1805 if not ok and exc_info is not None:
1810 if not ok and exc_info is not None:
1806 raise exc_info[0], exc_info[1], exc_info[2]
1811 raise exc_info[0], exc_info[1], exc_info[2]
1807
1812
1808 def __xrepr__(self, mode="default"):
1813 def __xrepr__(self, mode="default"):
1809 if mode == "header" or mode == "footer":
1814 if mode == "header" or mode == "footer":
1810 input = getattr(self, "input", None)
1815 input = getattr(self, "input", None)
1811 if input is not None:
1816 if input is not None:
1812 for part in xrepr(input, mode):
1817 for part in xrepr(input, mode):
1813 yield part
1818 yield part
1814 yield (astyle.style_default, " | ")
1819 yield (astyle.style_default, " | ")
1815 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1820 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1816 for part in xrepr(self.expr, "default"):
1821 for part in xrepr(self.expr, "default"):
1817 yield part
1822 yield part
1818 yield (astyle.style_default, ")")
1823 yield (astyle.style_default, ")")
1819 else:
1824 else:
1820 yield (astyle.style_default, repr(self))
1825 yield (astyle.style_default, repr(self))
1821
1826
1822 def __repr__(self):
1827 def __repr__(self):
1823 return "<%s.%s expr=%r at 0x%x>" % \
1828 return "<%s.%s expr=%r at 0x%x>" % \
1824 (self.__class__.__module__, self.__class__.__name__,
1829 (self.__class__.__module__, self.__class__.__name__,
1825 self.expr, id(self))
1830 self.expr, id(self))
1826
1831
1827
1832
1828 class ieval(Pipe):
1833 class ieval(Pipe):
1829 """
1834 """
1830 Evaluate an expression for each object in the input pipe.
1835 Evaluate an expression for each object in the input pipe.
1831
1836
1832 Examples::
1837 Examples::
1833
1838
1834 >>> ils | ieval("_.abspath()")
1839 >>> ils | ieval("_.abspath()")
1835 # random
1840 # random
1836 >>> sys.path | ieval(ifile)
1841 >>> sys.path | ieval(ifile)
1837 # random
1842 # random
1838 """
1843 """
1839
1844
1840 def __init__(self, expr, globals=None, errors="raiseifallfail"):
1845 def __init__(self, expr, globals=None, errors="raiseifallfail"):
1841 """
1846 """
1842 Create an ``ieval`` object. ``expr`` can be a callable or a string
1847 Create an ``ieval`` object. ``expr`` can be a callable or a string
1843 containing an expression. For the meaning of ``globals`` and
1848 containing an expression. For the meaning of ``globals`` and
1844 ``errors`` see ``ifilter``.
1849 ``errors`` see ``ifilter``.
1845 """
1850 """
1846 self.expr = expr
1851 self.expr = expr
1847 self.globals = globals
1852 self.globals = globals
1848 self.errors = errors
1853 self.errors = errors
1849
1854
1850 def __iter__(self):
1855 def __iter__(self):
1851 if callable(self.expr):
1856 if callable(self.expr):
1852 do = self.expr
1857 do = self.expr
1853 else:
1858 else:
1854 g = getglobals(self.globals)
1859 g = getglobals(self.globals)
1855 expr = compile(self.expr, "ipipe-expression", "eval")
1860 expr = compile(self.expr, "ipipe-expression", "eval")
1856 def do(item):
1861 def do(item):
1857 return eval(expr, g, AttrNamespace(item))
1862 return eval(expr, g, AttrNamespace(item))
1858
1863
1859 ok = 0
1864 ok = 0
1860 exc_info = None
1865 exc_info = None
1861 for item in xiter(self.input):
1866 for item in xiter(self.input):
1862 try:
1867 try:
1863 yield do(item)
1868 yield do(item)
1864 except (KeyboardInterrupt, SystemExit):
1869 except (KeyboardInterrupt, SystemExit):
1865 raise
1870 raise
1866 except Exception, exc:
1871 except Exception, exc:
1867 if self.errors == "drop":
1872 if self.errors == "drop":
1868 pass # Ignore errors
1873 pass # Ignore errors
1869 elif self.errors == "keep":
1874 elif self.errors == "keep":
1870 yield item
1875 yield item
1871 elif self.errors == "keeperror":
1876 elif self.errors == "keeperror":
1872 yield exc
1877 yield exc
1873 elif self.errors == "raise":
1878 elif self.errors == "raise":
1874 raise
1879 raise
1875 elif self.errors == "raiseifallfail":
1880 elif self.errors == "raiseifallfail":
1876 if exc_info is None:
1881 if exc_info is None:
1877 exc_info = sys.exc_info()
1882 exc_info = sys.exc_info()
1878 if not ok and exc_info is not None:
1883 if not ok and exc_info is not None:
1879 raise exc_info[0], exc_info[1], exc_info[2]
1884 raise exc_info[0], exc_info[1], exc_info[2]
1880
1885
1881 def __xrepr__(self, mode="default"):
1886 def __xrepr__(self, mode="default"):
1882 if mode == "header" or mode == "footer":
1887 if mode == "header" or mode == "footer":
1883 input = getattr(self, "input", None)
1888 input = getattr(self, "input", None)
1884 if input is not None:
1889 if input is not None:
1885 for part in xrepr(input, mode):
1890 for part in xrepr(input, mode):
1886 yield part
1891 yield part
1887 yield (astyle.style_default, " | ")
1892 yield (astyle.style_default, " | ")
1888 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1893 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1889 for part in xrepr(self.expr, "default"):
1894 for part in xrepr(self.expr, "default"):
1890 yield part
1895 yield part
1891 yield (astyle.style_default, ")")
1896 yield (astyle.style_default, ")")
1892 else:
1897 else:
1893 yield (astyle.style_default, repr(self))
1898 yield (astyle.style_default, repr(self))
1894
1899
1895 def __repr__(self):
1900 def __repr__(self):
1896 return "<%s.%s expr=%r at 0x%x>" % \
1901 return "<%s.%s expr=%r at 0x%x>" % \
1897 (self.__class__.__module__, self.__class__.__name__,
1902 (self.__class__.__module__, self.__class__.__name__,
1898 self.expr, id(self))
1903 self.expr, id(self))
1899
1904
1900
1905
1901 class ienum(Pipe):
1906 class ienum(Pipe):
1902 """
1907 """
1903 Enumerate the input pipe (i.e. wrap each input object in an object
1908 Enumerate the input pipe (i.e. wrap each input object in an object
1904 with ``index`` and ``object`` attributes).
1909 with ``index`` and ``object`` attributes).
1905
1910
1906 Examples::
1911 Examples::
1907
1912
1908 >>> xrange(20) | ieval("_,_*_") | ienum | ifilter("index % 2 == 0") | ieval("object")
1913 >>> xrange(20) | ieval("_,_*_") | ienum | ifilter("index % 2 == 0") | ieval("object")
1909 """
1914 """
1910 skip_doctest = True
1915 skip_doctest = True
1911
1916
1912 def __iter__(self):
1917 def __iter__(self):
1913 fields = ("index", "object")
1918 fields = ("index", "object")
1914 for (index, object) in enumerate(xiter(self.input)):
1919 for (index, object) in enumerate(xiter(self.input)):
1915 yield Fields(fields, index=index, object=object)
1920 yield Fields(fields, index=index, object=object)
1916
1921
1917
1922
1918 class isort(Pipe):
1923 class isort(Pipe):
1919 """
1924 """
1920 Sorts the input pipe.
1925 Sorts the input pipe.
1921
1926
1922 Examples::
1927 Examples::
1923
1928
1924 >>> ils | isort("size")
1929 >>> ils | isort("size")
1925 <IPython.Extensions.ipipe.isort key='size' reverse=False at 0x849ec2c>
1930 <IPython.Extensions.ipipe.isort key='size' reverse=False at 0x849ec2c>
1926 >>> ils | isort("_.isdir(), _.lower()", reverse=True)
1931 >>> ils | isort("_.isdir(), _.lower()", reverse=True)
1927 <IPython.Extensions.ipipe.isort key='_.isdir(), _.lower()' reverse=True at 0x849eacc>
1932 <IPython.Extensions.ipipe.isort key='_.isdir(), _.lower()' reverse=True at 0x849eacc>
1928 # all-random
1933 # all-random
1929 """
1934 """
1930
1935
1931 def __init__(self, key=None, globals=None, reverse=False):
1936 def __init__(self, key=None, globals=None, reverse=False):
1932 """
1937 """
1933 Create an ``isort`` object. ``key`` can be a callable or a string
1938 Create an ``isort`` object. ``key`` can be a callable or a string
1934 containing an expression (or ``None`` in which case the items
1939 containing an expression (or ``None`` in which case the items
1935 themselves will be sorted). If ``reverse`` is true the sort order
1940 themselves will be sorted). If ``reverse`` is true the sort order
1936 will be reversed. For the meaning of ``globals`` see ``ifilter``.
1941 will be reversed. For the meaning of ``globals`` see ``ifilter``.
1937 """
1942 """
1938 self.key = key
1943 self.key = key
1939 self.globals = globals
1944 self.globals = globals
1940 self.reverse = reverse
1945 self.reverse = reverse
1941
1946
1942 def __iter__(self):
1947 def __iter__(self):
1943 if self.key is None:
1948 if self.key is None:
1944 items = sorted(xiter(self.input), reverse=self.reverse)
1949 items = sorted(xiter(self.input), reverse=self.reverse)
1945 elif callable(self.key):
1950 elif callable(self.key):
1946 items = sorted(xiter(self.input), key=self.key, reverse=self.reverse)
1951 items = sorted(xiter(self.input), key=self.key, reverse=self.reverse)
1947 else:
1952 else:
1948 g = getglobals(self.globals)
1953 g = getglobals(self.globals)
1949 key = compile(self.key, "ipipe-expression", "eval")
1954 key = compile(self.key, "ipipe-expression", "eval")
1950 def realkey(item):
1955 def realkey(item):
1951 return eval(key, g, AttrNamespace(item))
1956 return eval(key, g, AttrNamespace(item))
1952 items = sorted(xiter(self.input), key=realkey, reverse=self.reverse)
1957 items = sorted(xiter(self.input), key=realkey, reverse=self.reverse)
1953 for item in items:
1958 for item in items:
1954 yield item
1959 yield item
1955
1960
1956 def __xrepr__(self, mode="default"):
1961 def __xrepr__(self, mode="default"):
1957 if mode == "header" or mode == "footer":
1962 if mode == "header" or mode == "footer":
1958 input = getattr(self, "input", None)
1963 input = getattr(self, "input", None)
1959 if input is not None:
1964 if input is not None:
1960 for part in xrepr(input, mode):
1965 for part in xrepr(input, mode):
1961 yield part
1966 yield part
1962 yield (astyle.style_default, " | ")
1967 yield (astyle.style_default, " | ")
1963 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1968 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1964 for part in xrepr(self.key, "default"):
1969 for part in xrepr(self.key, "default"):
1965 yield part
1970 yield part
1966 if self.reverse:
1971 if self.reverse:
1967 yield (astyle.style_default, ", ")
1972 yield (astyle.style_default, ", ")
1968 for part in xrepr(True, "default"):
1973 for part in xrepr(True, "default"):
1969 yield part
1974 yield part
1970 yield (astyle.style_default, ")")
1975 yield (astyle.style_default, ")")
1971 else:
1976 else:
1972 yield (astyle.style_default, repr(self))
1977 yield (astyle.style_default, repr(self))
1973
1978
1974 def __repr__(self):
1979 def __repr__(self):
1975 return "<%s.%s key=%r reverse=%r at 0x%x>" % \
1980 return "<%s.%s key=%r reverse=%r at 0x%x>" % \
1976 (self.__class__.__module__, self.__class__.__name__,
1981 (self.__class__.__module__, self.__class__.__name__,
1977 self.key, self.reverse, id(self))
1982 self.key, self.reverse, id(self))
1978
1983
1979
1984
1980 tab = 3 # for expandtabs()
1985 tab = 3 # for expandtabs()
1981
1986
1982 def _format(field):
1987 def _format(field):
1983 if isinstance(field, str):
1988 if isinstance(field, str):
1984 text = repr(field.expandtabs(tab))[1:-1]
1989 text = repr(field.expandtabs(tab))[1:-1]
1985 elif isinstance(field, unicode):
1990 elif isinstance(field, unicode):
1986 text = repr(field.expandtabs(tab))[2:-1]
1991 text = repr(field.expandtabs(tab))[2:-1]
1987 elif isinstance(field, datetime.datetime):
1992 elif isinstance(field, datetime.datetime):
1988 # Don't use strftime() here, as this requires year >= 1900
1993 # Don't use strftime() here, as this requires year >= 1900
1989 text = "%04d-%02d-%02d %02d:%02d:%02d.%06d" % \
1994 text = "%04d-%02d-%02d %02d:%02d:%02d.%06d" % \
1990 (field.year, field.month, field.day,
1995 (field.year, field.month, field.day,
1991 field.hour, field.minute, field.second, field.microsecond)
1996 field.hour, field.minute, field.second, field.microsecond)
1992 elif isinstance(field, datetime.date):
1997 elif isinstance(field, datetime.date):
1993 text = "%04d-%02d-%02d" % (field.year, field.month, field.day)
1998 text = "%04d-%02d-%02d" % (field.year, field.month, field.day)
1994 else:
1999 else:
1995 text = repr(field)
2000 text = repr(field)
1996 return text
2001 return text
1997
2002
1998
2003
1999 class Display(object):
2004 class Display(object):
2000 class __metaclass__(type):
2005 class __metaclass__(type):
2001 def __ror__(self, input):
2006 def __ror__(self, input):
2002 return input | self()
2007 return input | self()
2003
2008
2004 def __init__(self, input=None):
2009 def __init__(self, input=None):
2005 self.input = input
2010 self.input = input
2006
2011
2007 def __ror__(self, input):
2012 def __ror__(self, input):
2008 self.input = input
2013 self.input = input
2009 return self
2014 return self
2010
2015
2011 def display(self):
2016 def display(self):
2012 pass
2017 pass
2013
2018
2014
2019
2015 class iless(Display):
2020 class iless(Display):
2016 cmd = "less --quit-if-one-screen --LONG-PROMPT --LINE-NUMBERS --chop-long-lines --shift=8 --RAW-CONTROL-CHARS"
2021 cmd = "less --quit-if-one-screen --LONG-PROMPT --LINE-NUMBERS --chop-long-lines --shift=8 --RAW-CONTROL-CHARS"
2017
2022
2018 def display(self):
2023 def display(self):
2019 try:
2024 try:
2020 pager = os.popen(self.cmd, "w")
2025 pager = os.popen(self.cmd, "w")
2021 try:
2026 try:
2022 for item in xiter(self.input):
2027 for item in xiter(self.input):
2023 first = False
2028 first = False
2024 for attr in xattrs(item, "default"):
2029 for attr in xattrs(item, "default"):
2025 if first:
2030 if first:
2026 first = False
2031 first = False
2027 else:
2032 else:
2028 pager.write(" ")
2033 pager.write(" ")
2029 attr = upgradexattr(attr)
2034 attr = upgradexattr(attr)
2030 if not isinstance(attr, SelfDescriptor):
2035 if not isinstance(attr, SelfDescriptor):
2031 pager.write(attr.name())
2036 pager.write(attr.name())
2032 pager.write("=")
2037 pager.write("=")
2033 pager.write(str(attr.value(item)))
2038 pager.write(str(attr.value(item)))
2034 pager.write("\n")
2039 pager.write("\n")
2035 finally:
2040 finally:
2036 pager.close()
2041 pager.close()
2037 except Exception, exc:
2042 except Exception, exc:
2038 print "%s: %s" % (exc.__class__.__name__, str(exc))
2043 print "%s: %s" % (exc.__class__.__name__, str(exc))
2039
2044
2040
2045
2041 class _RedirectIO(object):
2046 class _RedirectIO(object):
2042 def __init__(self,*args,**kwargs):
2047 def __init__(self,*args,**kwargs):
2043 """
2048 """
2044 Map the system output streams to self.
2049 Map the system output streams to self.
2045 """
2050 """
2046 self.stream = StringIO.StringIO()
2051 self.stream = StringIO.StringIO()
2047 self.stdout = sys.stdout
2052 self.stdout = sys.stdout
2048 sys.stdout = self
2053 sys.stdout = self
2049 self.stderr = sys.stderr
2054 self.stderr = sys.stderr
2050 sys.stderr = self
2055 sys.stderr = self
2051
2056
2052 def write(self, text):
2057 def write(self, text):
2053 """
2058 """
2054 Write both to screen and to self.
2059 Write both to screen and to self.
2055 """
2060 """
2056 self.stream.write(text)
2061 self.stream.write(text)
2057 self.stdout.write(text)
2062 self.stdout.write(text)
2058 if "\n" in text:
2063 if "\n" in text:
2059 self.stdout.flush()
2064 self.stdout.flush()
2060
2065
2061 def writelines(self, lines):
2066 def writelines(self, lines):
2062 """
2067 """
2063 Write lines both to screen and to self.
2068 Write lines both to screen and to self.
2064 """
2069 """
2065 self.stream.writelines(lines)
2070 self.stream.writelines(lines)
2066 self.stdout.writelines(lines)
2071 self.stdout.writelines(lines)
2067 self.stdout.flush()
2072 self.stdout.flush()
2068
2073
2069 def restore(self):
2074 def restore(self):
2070 """
2075 """
2071 Restore the default system streams.
2076 Restore the default system streams.
2072 """
2077 """
2073 self.stdout.flush()
2078 self.stdout.flush()
2074 self.stderr.flush()
2079 self.stderr.flush()
2075 sys.stdout = self.stdout
2080 sys.stdout = self.stdout
2076 sys.stderr = self.stderr
2081 sys.stderr = self.stderr
2077
2082
2078
2083
2079 class icap(Table):
2084 class icap(Table):
2080 """
2085 """
2081 Execute a python string and capture any output to stderr/stdout.
2086 Execute a python string and capture any output to stderr/stdout.
2082
2087
2083 Examples::
2088 Examples::
2084
2089
2085 >>> import time
2090 >>> import time
2086 >>> icap("for i in range(10): print i, time.sleep(0.1)")
2091 >>> icap("for i in range(10): print i, time.sleep(0.1)")
2087
2092
2088 """
2093 """
2089 skip_doctest = True
2094 skip_doctest = True
2090
2095
2091 def __init__(self, expr, globals=None):
2096 def __init__(self, expr, globals=None):
2092 self.expr = expr
2097 self.expr = expr
2093 self.globals = globals
2098 self.globals = globals
2094 log = _RedirectIO()
2099 log = _RedirectIO()
2095 try:
2100 try:
2096 exec(expr, getglobals(globals))
2101 exec(expr, getglobals(globals))
2097 finally:
2102 finally:
2098 log.restore()
2103 log.restore()
2099 self.stream = log.stream
2104 self.stream = log.stream
2100
2105
2101 def __iter__(self):
2106 def __iter__(self):
2102 self.stream.seek(0)
2107 self.stream.seek(0)
2103 for line in self.stream:
2108 for line in self.stream:
2104 yield line.rstrip("\r\n")
2109 yield line.rstrip("\r\n")
2105
2110
2106 def __xrepr__(self, mode="default"):
2111 def __xrepr__(self, mode="default"):
2107 if mode == "header" or mode == "footer":
2112 if mode == "header" or mode == "footer":
2108 yield (astyle.style_default,
2113 yield (astyle.style_default,
2109 "%s(%r)" % (self.__class__.__name__, self.expr))
2114 "%s(%r)" % (self.__class__.__name__, self.expr))
2110 else:
2115 else:
2111 yield (astyle.style_default, repr(self))
2116 yield (astyle.style_default, repr(self))
2112
2117
2113 def __repr__(self):
2118 def __repr__(self):
2114 return "%s.%s(%r)" % \
2119 return "%s.%s(%r)" % \
2115 (self.__class__.__module__, self.__class__.__name__, self.expr)
2120 (self.__class__.__module__, self.__class__.__name__, self.expr)
2116
2121
2117
2122
2118 def xformat(value, mode, maxlength):
2123 def xformat(value, mode, maxlength):
2119 align = None
2124 align = None
2120 full = True
2125 full = True
2121 width = 0
2126 width = 0
2122 text = astyle.Text()
2127 text = astyle.Text()
2123 for (style, part) in xrepr(value, mode):
2128 for (style, part) in xrepr(value, mode):
2124 # only consider the first result
2129 # only consider the first result
2125 if align is None:
2130 if align is None:
2126 if isinstance(style, int):
2131 if isinstance(style, int):
2127 # (style, text) really is (alignment, stop)
2132 # (style, text) really is (alignment, stop)
2128 align = style
2133 align = style
2129 full = part
2134 full = part
2130 continue
2135 continue
2131 else:
2136 else:
2132 align = -1
2137 align = -1
2133 full = True
2138 full = True
2134 if not isinstance(style, int):
2139 if not isinstance(style, int):
2135 text.append((style, part))
2140 text.append((style, part))
2136 width += len(part)
2141 width += len(part)
2137 if width >= maxlength and not full:
2142 if width >= maxlength and not full:
2138 text.append((astyle.style_ellisis, "..."))
2143 text.append((astyle.style_ellisis, "..."))
2139 width += 3
2144 width += 3
2140 break
2145 break
2141 if align is None: # default to left alignment
2146 if align is None: # default to left alignment
2142 align = -1
2147 align = -1
2143 return (align, width, text)
2148 return (align, width, text)
2144
2149
2145
2150
2146
2151
2147 import astyle
2152 import astyle
2148
2153
2149 class idump(Display):
2154 class idump(Display):
2150 # The approximate maximum length of a column entry
2155 # The approximate maximum length of a column entry
2151 maxattrlength = 200
2156 maxattrlength = 200
2152
2157
2153 # Style for column names
2158 # Style for column names
2154 style_header = astyle.Style.fromstr("white:black:bold")
2159 style_header = astyle.Style.fromstr("white:black:bold")
2155
2160
2156 def __init__(self, input=None, *attrs):
2161 def __init__(self, input=None, *attrs):
2157 Display.__init__(self, input)
2162 Display.__init__(self, input)
2158 self.attrs = [upgradexattr(attr) for attr in attrs]
2163 self.attrs = [upgradexattr(attr) for attr in attrs]
2159 self.headerpadchar = " "
2164 self.headerpadchar = " "
2160 self.headersepchar = "|"
2165 self.headersepchar = "|"
2161 self.datapadchar = " "
2166 self.datapadchar = " "
2162 self.datasepchar = "|"
2167 self.datasepchar = "|"
2163
2168
2164 def display(self):
2169 def display(self):
2165 stream = genutils.Term.cout
2170 stream = genutils.Term.cout
2166 allattrs = []
2171 allattrs = []
2167 attrset = set()
2172 attrset = set()
2168 colwidths = {}
2173 colwidths = {}
2169 rows = []
2174 rows = []
2170 for item in xiter(self.input):
2175 for item in xiter(self.input):
2171 row = {}
2176 row = {}
2172 attrs = self.attrs
2177 attrs = self.attrs
2173 if not attrs:
2178 if not attrs:
2174 attrs = xattrs(item, "default")
2179 attrs = xattrs(item, "default")
2175 for attr in attrs:
2180 for attr in attrs:
2176 if attr not in attrset:
2181 if attr not in attrset:
2177 allattrs.append(attr)
2182 allattrs.append(attr)
2178 attrset.add(attr)
2183 attrset.add(attr)
2179 colwidths[attr] = len(attr.name())
2184 colwidths[attr] = len(attr.name())
2180 try:
2185 try:
2181 value = attr.value(item)
2186 value = attr.value(item)
2182 except (KeyboardInterrupt, SystemExit):
2187 except (KeyboardInterrupt, SystemExit):
2183 raise
2188 raise
2184 except Exception, exc:
2189 except Exception, exc:
2185 value = exc
2190 value = exc
2186 (align, width, text) = xformat(value, "cell", self.maxattrlength)
2191 (align, width, text) = xformat(value, "cell", self.maxattrlength)
2187 colwidths[attr] = max(colwidths[attr], width)
2192 colwidths[attr] = max(colwidths[attr], width)
2188 # remember alignment, length and colored parts
2193 # remember alignment, length and colored parts
2189 row[attr] = (align, width, text)
2194 row[attr] = (align, width, text)
2190 rows.append(row)
2195 rows.append(row)
2191
2196
2192 stream.write("\n")
2197 stream.write("\n")
2193 for (i, attr) in enumerate(allattrs):
2198 for (i, attr) in enumerate(allattrs):
2194 attrname = attr.name()
2199 attrname = attr.name()
2195 self.style_header(attrname).write(stream)
2200 self.style_header(attrname).write(stream)
2196 spc = colwidths[attr] - len(attrname)
2201 spc = colwidths[attr] - len(attrname)
2197 if i < len(colwidths)-1:
2202 if i < len(colwidths)-1:
2198 stream.write(self.headerpadchar*spc)
2203 stream.write(self.headerpadchar*spc)
2199 stream.write(self.headersepchar)
2204 stream.write(self.headersepchar)
2200 stream.write("\n")
2205 stream.write("\n")
2201
2206
2202 for row in rows:
2207 for row in rows:
2203 for (i, attr) in enumerate(allattrs):
2208 for (i, attr) in enumerate(allattrs):
2204 (align, width, text) = row[attr]
2209 (align, width, text) = row[attr]
2205 spc = colwidths[attr] - width
2210 spc = colwidths[attr] - width
2206 if align == -1:
2211 if align == -1:
2207 text.write(stream)
2212 text.write(stream)
2208 if i < len(colwidths)-1:
2213 if i < len(colwidths)-1:
2209 stream.write(self.datapadchar*spc)
2214 stream.write(self.datapadchar*spc)
2210 elif align == 0:
2215 elif align == 0:
2211 spc = colwidths[attr] - width
2216 spc = colwidths[attr] - width
2212 spc1 = spc//2
2217 spc1 = spc//2
2213 spc2 = spc-spc1
2218 spc2 = spc-spc1
2214 stream.write(self.datapadchar*spc1)
2219 stream.write(self.datapadchar*spc1)
2215 text.write(stream)
2220 text.write(stream)
2216 if i < len(colwidths)-1:
2221 if i < len(colwidths)-1:
2217 stream.write(self.datapadchar*spc2)
2222 stream.write(self.datapadchar*spc2)
2218 else:
2223 else:
2219 stream.write(self.datapadchar*spc)
2224 stream.write(self.datapadchar*spc)
2220 text.write(stream)
2225 text.write(stream)
2221 if i < len(colwidths)-1:
2226 if i < len(colwidths)-1:
2222 stream.write(self.datasepchar)
2227 stream.write(self.datasepchar)
2223 stream.write("\n")
2228 stream.write("\n")
2224
2229
2225
2230
2226 class AttributeDetail(Table):
2231 class AttributeDetail(Table):
2227 """
2232 """
2228 ``AttributeDetail`` objects are use for displaying a detailed list of object
2233 ``AttributeDetail`` objects are use for displaying a detailed list of object
2229 attributes.
2234 attributes.
2230 """
2235 """
2231 def __init__(self, object, descriptor):
2236 def __init__(self, object, descriptor):
2232 self.object = object
2237 self.object = object
2233 self.descriptor = descriptor
2238 self.descriptor = descriptor
2234
2239
2235 def __iter__(self):
2240 def __iter__(self):
2236 return self.descriptor.iter(self.object)
2241 return self.descriptor.iter(self.object)
2237
2242
2238 def name(self):
2243 def name(self):
2239 return self.descriptor.name()
2244 return self.descriptor.name()
2240
2245
2241 def attrtype(self):
2246 def attrtype(self):
2242 return self.descriptor.attrtype(self.object)
2247 return self.descriptor.attrtype(self.object)
2243
2248
2244 def valuetype(self):
2249 def valuetype(self):
2245 return self.descriptor.valuetype(self.object)
2250 return self.descriptor.valuetype(self.object)
2246
2251
2247 def doc(self):
2252 def doc(self):
2248 return self.descriptor.doc(self.object)
2253 return self.descriptor.doc(self.object)
2249
2254
2250 def shortdoc(self):
2255 def shortdoc(self):
2251 return self.descriptor.shortdoc(self.object)
2256 return self.descriptor.shortdoc(self.object)
2252
2257
2253 def value(self):
2258 def value(self):
2254 return self.descriptor.value(self.object)
2259 return self.descriptor.value(self.object)
2255
2260
2256 def __xattrs__(self, mode="default"):
2261 def __xattrs__(self, mode="default"):
2257 attrs = ("name()", "attrtype()", "valuetype()", "value()", "shortdoc()")
2262 attrs = ("name()", "attrtype()", "valuetype()", "value()", "shortdoc()")
2258 if mode == "detail":
2263 if mode == "detail":
2259 attrs += ("doc()",)
2264 attrs += ("doc()",)
2260 return attrs
2265 return attrs
2261
2266
2262 def __xrepr__(self, mode="default"):
2267 def __xrepr__(self, mode="default"):
2263 yield (-1, True)
2268 yield (-1, True)
2264 valuetype = self.valuetype()
2269 valuetype = self.valuetype()
2265 if valuetype is not noitem:
2270 if valuetype is not noitem:
2266 for part in xrepr(valuetype):
2271 for part in xrepr(valuetype):
2267 yield part
2272 yield part
2268 yield (astyle.style_default, " ")
2273 yield (astyle.style_default, " ")
2269 yield (astyle.style_default, self.attrtype())
2274 yield (astyle.style_default, self.attrtype())
2270 yield (astyle.style_default, " ")
2275 yield (astyle.style_default, " ")
2271 yield (astyle.style_default, self.name())
2276 yield (astyle.style_default, self.name())
2272 yield (astyle.style_default, " of ")
2277 yield (astyle.style_default, " of ")
2273 for part in xrepr(self.object):
2278 for part in xrepr(self.object):
2274 yield part
2279 yield part
2275
2280
2276
2281
2277 try:
2282 try:
2278 from ibrowse import ibrowse
2283 from ibrowse import ibrowse
2279 except ImportError:
2284 except ImportError:
2280 # No curses (probably Windows) => try igrid
2285 # No curses (probably Windows) => try igrid
2281 try:
2286 try:
2282 from igrid import igrid
2287 from igrid import igrid
2283 except ImportError:
2288 except ImportError:
2284 # no wx either => use ``idump`` as the default display.
2289 # no wx either => use ``idump`` as the default display.
2285 defaultdisplay = idump
2290 defaultdisplay = idump
2286 else:
2291 else:
2287 defaultdisplay = igrid
2292 defaultdisplay = igrid
2288 __all__.append("igrid")
2293 __all__.append("igrid")
2289 else:
2294 else:
2290 defaultdisplay = ibrowse
2295 defaultdisplay = ibrowse
2291 __all__.append("ibrowse")
2296 __all__.append("ibrowse")
2292
2297
2293
2298
2294 # If we're running under IPython, register our objects with IPython's
2299 # If we're running under IPython, register our objects with IPython's
2295 # generic function ``result_display``, else install a displayhook
2300 # generic function ``result_display``, else install a displayhook
2296 # directly as sys.displayhook
2301 # directly as sys.displayhook
2297 if generics is not None:
2302 if generics is not None:
2298 def display_display(obj):
2303 def display_display(obj):
2299 return obj.display()
2304 return obj.display()
2300 generics.result_display.when_type(Display)(display_display)
2305 generics.result_display.when_type(Display)(display_display)
2301
2306
2302 def display_tableobject(obj):
2307 def display_tableobject(obj):
2303 return display_display(defaultdisplay(obj))
2308 return display_display(defaultdisplay(obj))
2304 generics.result_display.when_type(Table)(display_tableobject)
2309 generics.result_display.when_type(Table)(display_tableobject)
2305
2310
2306 def display_tableclass(obj):
2311 def display_tableclass(obj):
2307 return display_tableobject(obj())
2312 return display_tableobject(obj())
2308 generics.result_display.when_type(Table.__metaclass__)(display_tableclass)
2313 generics.result_display.when_type(Table.__metaclass__)(display_tableclass)
2309 else:
2314 else:
2310 def installdisplayhook():
2315 def installdisplayhook():
2311 _originalhook = sys.displayhook
2316 _originalhook = sys.displayhook
2312 def displayhook(obj):
2317 def displayhook(obj):
2313 if isinstance(obj, type) and issubclass(obj, Table):
2318 if isinstance(obj, type) and issubclass(obj, Table):
2314 obj = obj()
2319 obj = obj()
2315 if isinstance(obj, Table):
2320 if isinstance(obj, Table):
2316 obj = defaultdisplay(obj)
2321 obj = defaultdisplay(obj)
2317 if isinstance(obj, Display):
2322 if isinstance(obj, Display):
2318 return obj.display()
2323 return obj.display()
2319 else:
2324 else:
2320 _originalhook(obj)
2325 _originalhook(obj)
2321 sys.displayhook = displayhook
2326 sys.displayhook = displayhook
2322 installdisplayhook()
2327 installdisplayhook()
@@ -1,75 +1,75 b''
1 """ Greedy completer extension for IPython
1 """ Greedy completer extension for IPython
2
2
3 Normal tab completer refuses to evaluate nonsafe stuff. This will evaluate
3 Normal tab completer refuses to evaluate nonsafe stuff. This will evaluate
4 everything, so you need to consider the consequences of pressing tab
4 everything, so you need to consider the consequences of pressing tab
5 yourself!
5 yourself!
6
6
7 Note that this extension simplifies readline interaction by setting
7 Note that this extension simplifies readline interaction by setting
8 only whitespace as completer delimiter. If this works well, we will
8 only whitespace as completer delimiter. If this works well, we will
9 do the same in default completer.
9 do the same in default completer.
10
10
11 """
11 """
12 from IPython import generics,ipapi
12 from IPython import generics,ipapi
13 from IPython.genutils import dir2
13 from IPython.genutils import dir2
14
14
15 def attr_matches(self, text):
15 def attr_matches(self, text):
16 """Compute matches when text contains a dot.
16 """Compute matches when text contains a dot.
17
17
18 MONKEYPATCHED VERSION (ipy_greedycompleter.py)
18 MONKEYPATCHED VERSION (ipy_greedycompleter.py)
19
19
20 Assuming the text is of the form NAME.NAME....[NAME], and is
20 Assuming the text is of the form NAME.NAME....[NAME], and is
21 evaluatable in self.namespace or self.global_namespace, it will be
21 evaluatable in self.namespace or self.global_namespace, it will be
22 evaluated and its attributes (as revealed by dir()) are used as
22 evaluated and its attributes (as revealed by dir()) are used as
23 possible completions. (For class instances, class members are are
23 possible completions. (For class instances, class members are are
24 also considered.)
24 also considered.)
25
25
26 WARNING: this can still invoke arbitrary C code, if an object
26 WARNING: this can still invoke arbitrary C code, if an object
27 with a __getattr__ hook is evaluated.
27 with a __getattr__ hook is evaluated.
28
28
29 """
29 """
30 import re
30 import re
31
31
32 force_complete = 1
32 force_complete = 1
33 # Another option, seems to work great. Catches things like ''.<tab>
33 # Another option, seems to work great. Catches things like ''.<tab>
34 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
34 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
35
35
36 if m:
36 if m:
37 expr, attr = m.group(1, 3)
37 expr, attr = m.group(1, 3)
38 else:
38 else:
39 # force match - eval anything that ends with colon
39 # force match - eval anything that ends with colon
40 if not force_complete:
40 if not force_complete:
41 return []
41 return []
42
42
43 m2 = re.match(r"(.+)\.(\w*)$", self.lbuf)
43 m2 = re.match(r"(.+)\.(\w*)$", self.lbuf)
44 if not m2:
44 if not m2:
45 return []
45 return []
46 expr, attr = m2.group(1,2)
46 expr, attr = m2.group(1,2)
47
47
48
48
49 try:
49 try:
50 obj = eval(expr, self.namespace)
50 obj = eval(expr, self.namespace)
51 except:
51 except:
52 try:
52 try:
53 obj = eval(expr, self.global_namespace)
53 obj = eval(expr, self.global_namespace)
54 except:
54 except:
55 return []
55 return []
56
56
57 words = dir2(obj)
57 words = dir2(obj)
58
58
59 try:
59 try:
60 words = generics.complete_object(obj, words)
60 words = generics.complete_object(obj, words)
61 except ipapi.TryNext:
61 except ipapi.TryNext:
62 pass
62 pass
63 # Build match list to return
63 # Build match list to return
64 n = len(attr)
64 n = len(attr)
65 res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ]
65 res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ]
66 return res
66 return res
67
67
68 def main():
68 def main():
69 import readline
69 import IPython.rlineimpl as readline
70 readline.set_completer_delims(" \n\t")
70 readline.set_completer_delims(" \n\t")
71 # monkeypatch - the code will be folded to normal completer later on
71 # monkeypatch - the code will be folded to normal completer later on
72 import IPython.completer
72 import IPython.completer
73 IPython.completer.Completer.attr_matches = attr_matches
73 IPython.completer.Completer.attr_matches = attr_matches
74
74
75 main() No newline at end of file
75 main()
@@ -1,42 +1,66 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Class which mimics a module.
3 Class which mimics a module.
4
4
5 Needed to allow pickle to correctly resolve namespaces during IPython
5 Needed to allow pickle to correctly resolve namespaces during IPython
6 sessions.
6 sessions.
7 """
7 """
8
8
9 #*****************************************************************************
9 #*****************************************************************************
10 # Copyright (C) 2002-2004 Fernando Perez. <fperez@colorado.edu>
10 # Copyright (C) 2002-2004 Fernando Perez. <fperez@colorado.edu>
11 #
11 #
12 # Distributed under the terms of the BSD License. The full license is in
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
14 #*****************************************************************************
14 #*****************************************************************************
15
15
16 import types
16 import types
17
17
18 def init_fakemod_dict(fm,adict=None):
19 """Initialize a FakeModule instance __dict__.
20
21 Kept as a standalone function and not a method so the FakeModule API can
22 remain basically empty.
23
24 This should be considered for private IPython use, used in managing
25 namespaces for %run.
26
27 Parameters
28 ----------
29
30 fm : FakeModule instance
31
32 adict : dict, optional
33 """
34
35 dct = {}
36 # It seems pydoc (and perhaps others) needs any module instance to
37 # implement a __nonzero__ method, so we add it if missing:
38 dct.setdefault('__nonzero__',lambda : True)
39 dct.setdefault('__file__',__file__)
40
41 if adict is not None:
42 dct.update(adict)
43
44 # Hard assignment of the object's __dict__. This is nasty but deliberate.
45 fm.__dict__.clear()
46 fm.__dict__.update(dct)
47
48
18 class FakeModule(types.ModuleType):
49 class FakeModule(types.ModuleType):
19 """Simple class with attribute access to fake a module.
50 """Simple class with attribute access to fake a module.
20
51
21 This is not meant to replace a module, but to allow inserting a fake
52 This is not meant to replace a module, but to allow inserting a fake
22 module in sys.modules so that systems which rely on run-time module
53 module in sys.modules so that systems which rely on run-time module
23 importing (like shelve and pickle) work correctly in interactive IPython
54 importing (like shelve and pickle) work correctly in interactive IPython
24 sessions.
55 sessions.
25
56
26 Do NOT use this code for anything other than this IPython private hack."""
57 Do NOT use this code for anything other than this IPython private hack."""
27
58
28 def __init__(self,adict=None):
59 def __init__(self,adict=None):
29
60
30 # tmp to force __dict__ instance creation, else self.__dict__ fails
61 # tmp to force __dict__ instance creation, else self.__dict__ fails
31 self.__iptmp = None
62 self.__iptmp = None
32
33 # It seems pydoc (and perhaps others) needs any module instance to
34 # implement a __nonzero__ method, so we add it if missing:
35 self.__dict__.setdefault('__nonzero__',lambda : True)
36 self.__dict__.setdefault('__file__',__file__)
37
38 # cleanup our temp trick
63 # cleanup our temp trick
39 del self.__iptmp
64 del self.__iptmp
40
65 # Now, initialize the actual data in the instance dict.
41 if adict is not None:
66 init_fakemod_dict(self,adict)
42 self.__dict__.update(adict)
@@ -1,3425 +1,3456 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Magic functions for InteractiveShell.
2 """Magic functions for InteractiveShell.
3 """
3 """
4
4
5 #*****************************************************************************
5 #*****************************************************************************
6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
7 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
7 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #*****************************************************************************
11 #*****************************************************************************
12
12
13 #****************************************************************************
13 #****************************************************************************
14 # Modules and globals
14 # Modules and globals
15
15
16 # Python standard modules
16 # Python standard modules
17 import __builtin__
17 import __builtin__
18 import bdb
18 import bdb
19 import inspect
19 import inspect
20 import os
20 import os
21 import pdb
21 import pdb
22 import pydoc
22 import pydoc
23 import sys
23 import sys
24 import re
24 import re
25 import tempfile
25 import tempfile
26 import time
26 import time
27 import cPickle as pickle
27 import cPickle as pickle
28 import textwrap
28 import textwrap
29 from cStringIO import StringIO
29 from cStringIO import StringIO
30 from getopt import getopt,GetoptError
30 from getopt import getopt,GetoptError
31 from pprint import pprint, pformat
31 from pprint import pprint, pformat
32
32
33 # cProfile was added in Python2.5
33 # cProfile was added in Python2.5
34 try:
34 try:
35 import cProfile as profile
35 import cProfile as profile
36 import pstats
36 import pstats
37 except ImportError:
37 except ImportError:
38 # profile isn't bundled by default in Debian for license reasons
38 # profile isn't bundled by default in Debian for license reasons
39 try:
39 try:
40 import profile,pstats
40 import profile,pstats
41 except ImportError:
41 except ImportError:
42 profile = pstats = None
42 profile = pstats = None
43
43
44 # Homebrewed
44 # Homebrewed
45 import IPython
45 import IPython
46 from IPython import Debugger, OInspect, wildcard
46 from IPython import Debugger, OInspect, wildcard
47 from IPython.FakeModule import FakeModule
47 from IPython.FakeModule import FakeModule
48 from IPython.Itpl import Itpl, itpl, printpl,itplns
48 from IPython.Itpl import Itpl, itpl, printpl,itplns
49 from IPython.PyColorize import Parser
49 from IPython.PyColorize import Parser
50 from IPython.ipstruct import Struct
50 from IPython.ipstruct import Struct
51 from IPython.macro import Macro
51 from IPython.macro import Macro
52 from IPython.genutils import *
52 from IPython.genutils import *
53 from IPython import platutils
53 from IPython import platutils
54 import IPython.generics
54 import IPython.generics
55 import IPython.ipapi
55 import IPython.ipapi
56 from IPython.ipapi import UsageError
56 from IPython.ipapi import UsageError
57 from IPython.testing import decorators as testdec
57 from IPython.testing import decorators as testdec
58
58
59 #***************************************************************************
59 #***************************************************************************
60 # Utility functions
60 # Utility functions
61 def on_off(tag):
61 def on_off(tag):
62 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
62 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
63 return ['OFF','ON'][tag]
63 return ['OFF','ON'][tag]
64
64
65 class Bunch: pass
65 class Bunch: pass
66
66
67 def compress_dhist(dh):
67 def compress_dhist(dh):
68 head, tail = dh[:-10], dh[-10:]
68 head, tail = dh[:-10], dh[-10:]
69
69
70 newhead = []
70 newhead = []
71 done = set()
71 done = set()
72 for h in head:
72 for h in head:
73 if h in done:
73 if h in done:
74 continue
74 continue
75 newhead.append(h)
75 newhead.append(h)
76 done.add(h)
76 done.add(h)
77
77
78 return newhead + tail
78 return newhead + tail
79
79
80
80
81 #***************************************************************************
81 #***************************************************************************
82 # Main class implementing Magic functionality
82 # Main class implementing Magic functionality
83 class Magic:
83 class Magic:
84 """Magic functions for InteractiveShell.
84 """Magic functions for InteractiveShell.
85
85
86 Shell functions which can be reached as %function_name. All magic
86 Shell functions which can be reached as %function_name. All magic
87 functions should accept a string, which they can parse for their own
87 functions should accept a string, which they can parse for their own
88 needs. This can make some functions easier to type, eg `%cd ../`
88 needs. This can make some functions easier to type, eg `%cd ../`
89 vs. `%cd("../")`
89 vs. `%cd("../")`
90
90
91 ALL definitions MUST begin with the prefix magic_. The user won't need it
91 ALL definitions MUST begin with the prefix magic_. The user won't need it
92 at the command line, but it is is needed in the definition. """
92 at the command line, but it is is needed in the definition. """
93
93
94 # class globals
94 # class globals
95 auto_status = ['Automagic is OFF, % prefix IS needed for magic functions.',
95 auto_status = ['Automagic is OFF, % prefix IS needed for magic functions.',
96 'Automagic is ON, % prefix NOT needed for magic functions.']
96 'Automagic is ON, % prefix NOT needed for magic functions.']
97
97
98 #......................................................................
98 #......................................................................
99 # some utility functions
99 # some utility functions
100
100
101 def __init__(self,shell):
101 def __init__(self,shell):
102
102
103 self.options_table = {}
103 self.options_table = {}
104 if profile is None:
104 if profile is None:
105 self.magic_prun = self.profile_missing_notice
105 self.magic_prun = self.profile_missing_notice
106 self.shell = shell
106 self.shell = shell
107
107
108 # namespace for holding state we may need
108 # namespace for holding state we may need
109 self._magic_state = Bunch()
109 self._magic_state = Bunch()
110
110
111 def profile_missing_notice(self, *args, **kwargs):
111 def profile_missing_notice(self, *args, **kwargs):
112 error("""\
112 error("""\
113 The profile module could not be found. It has been removed from the standard
113 The profile module could not be found. It has been removed from the standard
114 python packages because of its non-free license. To use profiling, install the
114 python packages because of its non-free license. To use profiling, install the
115 python-profiler package from non-free.""")
115 python-profiler package from non-free.""")
116
116
117 def default_option(self,fn,optstr):
117 def default_option(self,fn,optstr):
118 """Make an entry in the options_table for fn, with value optstr"""
118 """Make an entry in the options_table for fn, with value optstr"""
119
119
120 if fn not in self.lsmagic():
120 if fn not in self.lsmagic():
121 error("%s is not a magic function" % fn)
121 error("%s is not a magic function" % fn)
122 self.options_table[fn] = optstr
122 self.options_table[fn] = optstr
123
123
124 def lsmagic(self):
124 def lsmagic(self):
125 """Return a list of currently available magic functions.
125 """Return a list of currently available magic functions.
126
126
127 Gives a list of the bare names after mangling (['ls','cd', ...], not
127 Gives a list of the bare names after mangling (['ls','cd', ...], not
128 ['magic_ls','magic_cd',...]"""
128 ['magic_ls','magic_cd',...]"""
129
129
130 # FIXME. This needs a cleanup, in the way the magics list is built.
130 # FIXME. This needs a cleanup, in the way the magics list is built.
131
131
132 # magics in class definition
132 # magics in class definition
133 class_magic = lambda fn: fn.startswith('magic_') and \
133 class_magic = lambda fn: fn.startswith('magic_') and \
134 callable(Magic.__dict__[fn])
134 callable(Magic.__dict__[fn])
135 # in instance namespace (run-time user additions)
135 # in instance namespace (run-time user additions)
136 inst_magic = lambda fn: fn.startswith('magic_') and \
136 inst_magic = lambda fn: fn.startswith('magic_') and \
137 callable(self.__dict__[fn])
137 callable(self.__dict__[fn])
138 # and bound magics by user (so they can access self):
138 # and bound magics by user (so they can access self):
139 inst_bound_magic = lambda fn: fn.startswith('magic_') and \
139 inst_bound_magic = lambda fn: fn.startswith('magic_') and \
140 callable(self.__class__.__dict__[fn])
140 callable(self.__class__.__dict__[fn])
141 magics = filter(class_magic,Magic.__dict__.keys()) + \
141 magics = filter(class_magic,Magic.__dict__.keys()) + \
142 filter(inst_magic,self.__dict__.keys()) + \
142 filter(inst_magic,self.__dict__.keys()) + \
143 filter(inst_bound_magic,self.__class__.__dict__.keys())
143 filter(inst_bound_magic,self.__class__.__dict__.keys())
144 out = []
144 out = []
145 for fn in set(magics):
145 for fn in set(magics):
146 out.append(fn.replace('magic_','',1))
146 out.append(fn.replace('magic_','',1))
147 out.sort()
147 out.sort()
148 return out
148 return out
149
149
150 def extract_input_slices(self,slices,raw=False):
150 def extract_input_slices(self,slices,raw=False):
151 """Return as a string a set of input history slices.
151 """Return as a string a set of input history slices.
152
152
153 Inputs:
153 Inputs:
154
154
155 - slices: the set of slices is given as a list of strings (like
155 - slices: the set of slices is given as a list of strings (like
156 ['1','4:8','9'], since this function is for use by magic functions
156 ['1','4:8','9'], since this function is for use by magic functions
157 which get their arguments as strings.
157 which get their arguments as strings.
158
158
159 Optional inputs:
159 Optional inputs:
160
160
161 - raw(False): by default, the processed input is used. If this is
161 - raw(False): by default, the processed input is used. If this is
162 true, the raw input history is used instead.
162 true, the raw input history is used instead.
163
163
164 Note that slices can be called with two notations:
164 Note that slices can be called with two notations:
165
165
166 N:M -> standard python form, means including items N...(M-1).
166 N:M -> standard python form, means including items N...(M-1).
167
167
168 N-M -> include items N..M (closed endpoint)."""
168 N-M -> include items N..M (closed endpoint)."""
169
169
170 if raw:
170 if raw:
171 hist = self.shell.input_hist_raw
171 hist = self.shell.input_hist_raw
172 else:
172 else:
173 hist = self.shell.input_hist
173 hist = self.shell.input_hist
174
174
175 cmds = []
175 cmds = []
176 for chunk in slices:
176 for chunk in slices:
177 if ':' in chunk:
177 if ':' in chunk:
178 ini,fin = map(int,chunk.split(':'))
178 ini,fin = map(int,chunk.split(':'))
179 elif '-' in chunk:
179 elif '-' in chunk:
180 ini,fin = map(int,chunk.split('-'))
180 ini,fin = map(int,chunk.split('-'))
181 fin += 1
181 fin += 1
182 else:
182 else:
183 ini = int(chunk)
183 ini = int(chunk)
184 fin = ini+1
184 fin = ini+1
185 cmds.append(hist[ini:fin])
185 cmds.append(hist[ini:fin])
186 return cmds
186 return cmds
187
187
188 def _ofind(self, oname, namespaces=None):
188 def _ofind(self, oname, namespaces=None):
189 """Find an object in the available namespaces.
189 """Find an object in the available namespaces.
190
190
191 self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
191 self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
192
192
193 Has special code to detect magic functions.
193 Has special code to detect magic functions.
194 """
194 """
195
195
196 oname = oname.strip()
196 oname = oname.strip()
197
197
198 alias_ns = None
198 alias_ns = None
199 if namespaces is None:
199 if namespaces is None:
200 # Namespaces to search in:
200 # Namespaces to search in:
201 # Put them in a list. The order is important so that we
201 # Put them in a list. The order is important so that we
202 # find things in the same order that Python finds them.
202 # find things in the same order that Python finds them.
203 namespaces = [ ('Interactive', self.shell.user_ns),
203 namespaces = [ ('Interactive', self.shell.user_ns),
204 ('IPython internal', self.shell.internal_ns),
204 ('IPython internal', self.shell.internal_ns),
205 ('Python builtin', __builtin__.__dict__),
205 ('Python builtin', __builtin__.__dict__),
206 ('Alias', self.shell.alias_table),
206 ('Alias', self.shell.alias_table),
207 ]
207 ]
208 alias_ns = self.shell.alias_table
208 alias_ns = self.shell.alias_table
209
209
210 # initialize results to 'null'
210 # initialize results to 'null'
211 found = 0; obj = None; ospace = None; ds = None;
211 found = 0; obj = None; ospace = None; ds = None;
212 ismagic = 0; isalias = 0; parent = None
212 ismagic = 0; isalias = 0; parent = None
213
213
214 # Look for the given name by splitting it in parts. If the head is
214 # Look for the given name by splitting it in parts. If the head is
215 # found, then we look for all the remaining parts as members, and only
215 # found, then we look for all the remaining parts as members, and only
216 # declare success if we can find them all.
216 # declare success if we can find them all.
217 oname_parts = oname.split('.')
217 oname_parts = oname.split('.')
218 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
218 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
219 for nsname,ns in namespaces:
219 for nsname,ns in namespaces:
220 try:
220 try:
221 obj = ns[oname_head]
221 obj = ns[oname_head]
222 except KeyError:
222 except KeyError:
223 continue
223 continue
224 else:
224 else:
225 #print 'oname_rest:', oname_rest # dbg
225 #print 'oname_rest:', oname_rest # dbg
226 for part in oname_rest:
226 for part in oname_rest:
227 try:
227 try:
228 parent = obj
228 parent = obj
229 obj = getattr(obj,part)
229 obj = getattr(obj,part)
230 except:
230 except:
231 # Blanket except b/c some badly implemented objects
231 # Blanket except b/c some badly implemented objects
232 # allow __getattr__ to raise exceptions other than
232 # allow __getattr__ to raise exceptions other than
233 # AttributeError, which then crashes IPython.
233 # AttributeError, which then crashes IPython.
234 break
234 break
235 else:
235 else:
236 # If we finish the for loop (no break), we got all members
236 # If we finish the for loop (no break), we got all members
237 found = 1
237 found = 1
238 ospace = nsname
238 ospace = nsname
239 if ns == alias_ns:
239 if ns == alias_ns:
240 isalias = 1
240 isalias = 1
241 break # namespace loop
241 break # namespace loop
242
242
243 # Try to see if it's magic
243 # Try to see if it's magic
244 if not found:
244 if not found:
245 if oname.startswith(self.shell.ESC_MAGIC):
245 if oname.startswith(self.shell.ESC_MAGIC):
246 oname = oname[1:]
246 oname = oname[1:]
247 obj = getattr(self,'magic_'+oname,None)
247 obj = getattr(self,'magic_'+oname,None)
248 if obj is not None:
248 if obj is not None:
249 found = 1
249 found = 1
250 ospace = 'IPython internal'
250 ospace = 'IPython internal'
251 ismagic = 1
251 ismagic = 1
252
252
253 # Last try: special-case some literals like '', [], {}, etc:
253 # Last try: special-case some literals like '', [], {}, etc:
254 if not found and oname_head in ["''",'""','[]','{}','()']:
254 if not found and oname_head in ["''",'""','[]','{}','()']:
255 obj = eval(oname_head)
255 obj = eval(oname_head)
256 found = 1
256 found = 1
257 ospace = 'Interactive'
257 ospace = 'Interactive'
258
258
259 return {'found':found, 'obj':obj, 'namespace':ospace,
259 return {'found':found, 'obj':obj, 'namespace':ospace,
260 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
260 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
261
261
262 def arg_err(self,func):
262 def arg_err(self,func):
263 """Print docstring if incorrect arguments were passed"""
263 """Print docstring if incorrect arguments were passed"""
264 print 'Error in arguments:'
264 print 'Error in arguments:'
265 print OInspect.getdoc(func)
265 print OInspect.getdoc(func)
266
266
267 def format_latex(self,strng):
267 def format_latex(self,strng):
268 """Format a string for latex inclusion."""
268 """Format a string for latex inclusion."""
269
269
270 # Characters that need to be escaped for latex:
270 # Characters that need to be escaped for latex:
271 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
271 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
272 # Magic command names as headers:
272 # Magic command names as headers:
273 cmd_name_re = re.compile(r'^(%s.*?):' % self.shell.ESC_MAGIC,
273 cmd_name_re = re.compile(r'^(%s.*?):' % self.shell.ESC_MAGIC,
274 re.MULTILINE)
274 re.MULTILINE)
275 # Magic commands
275 # Magic commands
276 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % self.shell.ESC_MAGIC,
276 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % self.shell.ESC_MAGIC,
277 re.MULTILINE)
277 re.MULTILINE)
278 # Paragraph continue
278 # Paragraph continue
279 par_re = re.compile(r'\\$',re.MULTILINE)
279 par_re = re.compile(r'\\$',re.MULTILINE)
280
280
281 # The "\n" symbol
281 # The "\n" symbol
282 newline_re = re.compile(r'\\n')
282 newline_re = re.compile(r'\\n')
283
283
284 # Now build the string for output:
284 # Now build the string for output:
285 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
285 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
286 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
286 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
287 strng)
287 strng)
288 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
288 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
289 strng = par_re.sub(r'\\\\',strng)
289 strng = par_re.sub(r'\\\\',strng)
290 strng = escape_re.sub(r'\\\1',strng)
290 strng = escape_re.sub(r'\\\1',strng)
291 strng = newline_re.sub(r'\\textbackslash{}n',strng)
291 strng = newline_re.sub(r'\\textbackslash{}n',strng)
292 return strng
292 return strng
293
293
294 def format_screen(self,strng):
294 def format_screen(self,strng):
295 """Format a string for screen printing.
295 """Format a string for screen printing.
296
296
297 This removes some latex-type format codes."""
297 This removes some latex-type format codes."""
298 # Paragraph continue
298 # Paragraph continue
299 par_re = re.compile(r'\\$',re.MULTILINE)
299 par_re = re.compile(r'\\$',re.MULTILINE)
300 strng = par_re.sub('',strng)
300 strng = par_re.sub('',strng)
301 return strng
301 return strng
302
302
303 def parse_options(self,arg_str,opt_str,*long_opts,**kw):
303 def parse_options(self,arg_str,opt_str,*long_opts,**kw):
304 """Parse options passed to an argument string.
304 """Parse options passed to an argument string.
305
305
306 The interface is similar to that of getopt(), but it returns back a
306 The interface is similar to that of getopt(), but it returns back a
307 Struct with the options as keys and the stripped argument string still
307 Struct with the options as keys and the stripped argument string still
308 as a string.
308 as a string.
309
309
310 arg_str is quoted as a true sys.argv vector by using shlex.split.
310 arg_str is quoted as a true sys.argv vector by using shlex.split.
311 This allows us to easily expand variables, glob files, quote
311 This allows us to easily expand variables, glob files, quote
312 arguments, etc.
312 arguments, etc.
313
313
314 Options:
314 Options:
315 -mode: default 'string'. If given as 'list', the argument string is
315 -mode: default 'string'. If given as 'list', the argument string is
316 returned as a list (split on whitespace) instead of a string.
316 returned as a list (split on whitespace) instead of a string.
317
317
318 -list_all: put all option values in lists. Normally only options
318 -list_all: put all option values in lists. Normally only options
319 appearing more than once are put in a list.
319 appearing more than once are put in a list.
320
320
321 -posix (True): whether to split the input line in POSIX mode or not,
321 -posix (True): whether to split the input line in POSIX mode or not,
322 as per the conventions outlined in the shlex module from the
322 as per the conventions outlined in the shlex module from the
323 standard library."""
323 standard library."""
324
324
325 # inject default options at the beginning of the input line
325 # inject default options at the beginning of the input line
326 caller = sys._getframe(1).f_code.co_name.replace('magic_','')
326 caller = sys._getframe(1).f_code.co_name.replace('magic_','')
327 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
327 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
328
328
329 mode = kw.get('mode','string')
329 mode = kw.get('mode','string')
330 if mode not in ['string','list']:
330 if mode not in ['string','list']:
331 raise ValueError,'incorrect mode given: %s' % mode
331 raise ValueError,'incorrect mode given: %s' % mode
332 # Get options
332 # Get options
333 list_all = kw.get('list_all',0)
333 list_all = kw.get('list_all',0)
334 posix = kw.get('posix',True)
334 posix = kw.get('posix',True)
335
335
336 # Check if we have more than one argument to warrant extra processing:
336 # Check if we have more than one argument to warrant extra processing:
337 odict = {} # Dictionary with options
337 odict = {} # Dictionary with options
338 args = arg_str.split()
338 args = arg_str.split()
339 if len(args) >= 1:
339 if len(args) >= 1:
340 # If the list of inputs only has 0 or 1 thing in it, there's no
340 # If the list of inputs only has 0 or 1 thing in it, there's no
341 # need to look for options
341 # need to look for options
342 argv = arg_split(arg_str,posix)
342 argv = arg_split(arg_str,posix)
343 # Do regular option processing
343 # Do regular option processing
344 try:
344 try:
345 opts,args = getopt(argv,opt_str,*long_opts)
345 opts,args = getopt(argv,opt_str,*long_opts)
346 except GetoptError,e:
346 except GetoptError,e:
347 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
347 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
348 " ".join(long_opts)))
348 " ".join(long_opts)))
349 for o,a in opts:
349 for o,a in opts:
350 if o.startswith('--'):
350 if o.startswith('--'):
351 o = o[2:]
351 o = o[2:]
352 else:
352 else:
353 o = o[1:]
353 o = o[1:]
354 try:
354 try:
355 odict[o].append(a)
355 odict[o].append(a)
356 except AttributeError:
356 except AttributeError:
357 odict[o] = [odict[o],a]
357 odict[o] = [odict[o],a]
358 except KeyError:
358 except KeyError:
359 if list_all:
359 if list_all:
360 odict[o] = [a]
360 odict[o] = [a]
361 else:
361 else:
362 odict[o] = a
362 odict[o] = a
363
363
364 # Prepare opts,args for return
364 # Prepare opts,args for return
365 opts = Struct(odict)
365 opts = Struct(odict)
366 if mode == 'string':
366 if mode == 'string':
367 args = ' '.join(args)
367 args = ' '.join(args)
368
368
369 return opts,args
369 return opts,args
370
370
371 #......................................................................
371 #......................................................................
372 # And now the actual magic functions
372 # And now the actual magic functions
373
373
374 # Functions for IPython shell work (vars,funcs, config, etc)
374 # Functions for IPython shell work (vars,funcs, config, etc)
375 def magic_lsmagic(self, parameter_s = ''):
375 def magic_lsmagic(self, parameter_s = ''):
376 """List currently available magic functions."""
376 """List currently available magic functions."""
377 mesc = self.shell.ESC_MAGIC
377 mesc = self.shell.ESC_MAGIC
378 print 'Available magic functions:\n'+mesc+\
378 print 'Available magic functions:\n'+mesc+\
379 (' '+mesc).join(self.lsmagic())
379 (' '+mesc).join(self.lsmagic())
380 print '\n' + Magic.auto_status[self.shell.rc.automagic]
380 print '\n' + Magic.auto_status[self.shell.rc.automagic]
381 return None
381 return None
382
382
383 def magic_magic(self, parameter_s = ''):
383 def magic_magic(self, parameter_s = ''):
384 """Print information about the magic function system.
384 """Print information about the magic function system.
385
385
386 Supported formats: -latex, -brief, -rest
386 Supported formats: -latex, -brief, -rest
387 """
387 """
388
388
389 mode = ''
389 mode = ''
390 try:
390 try:
391 if parameter_s.split()[0] == '-latex':
391 if parameter_s.split()[0] == '-latex':
392 mode = 'latex'
392 mode = 'latex'
393 if parameter_s.split()[0] == '-brief':
393 if parameter_s.split()[0] == '-brief':
394 mode = 'brief'
394 mode = 'brief'
395 if parameter_s.split()[0] == '-rest':
395 if parameter_s.split()[0] == '-rest':
396 mode = 'rest'
396 mode = 'rest'
397 rest_docs = []
397 rest_docs = []
398 except:
398 except:
399 pass
399 pass
400
400
401 magic_docs = []
401 magic_docs = []
402 for fname in self.lsmagic():
402 for fname in self.lsmagic():
403 mname = 'magic_' + fname
403 mname = 'magic_' + fname
404 for space in (Magic,self,self.__class__):
404 for space in (Magic,self,self.__class__):
405 try:
405 try:
406 fn = space.__dict__[mname]
406 fn = space.__dict__[mname]
407 except KeyError:
407 except KeyError:
408 pass
408 pass
409 else:
409 else:
410 break
410 break
411 if mode == 'brief':
411 if mode == 'brief':
412 # only first line
412 # only first line
413 if fn.__doc__:
413 if fn.__doc__:
414 fndoc = fn.__doc__.split('\n',1)[0]
414 fndoc = fn.__doc__.split('\n',1)[0]
415 else:
415 else:
416 fndoc = 'No documentation'
416 fndoc = 'No documentation'
417 else:
417 else:
418 if fn.__doc__:
418 if fn.__doc__:
419 fndoc = fn.__doc__.rstrip()
419 fndoc = fn.__doc__.rstrip()
420 else:
420 else:
421 fndoc = 'No documentation'
421 fndoc = 'No documentation'
422
422
423
423
424 if mode == 'rest':
424 if mode == 'rest':
425 rest_docs.append('**%s%s**::\n\n\t%s\n\n' %(self.shell.ESC_MAGIC,
425 rest_docs.append('**%s%s**::\n\n\t%s\n\n' %(self.shell.ESC_MAGIC,
426 fname,fndoc))
426 fname,fndoc))
427
427
428 else:
428 else:
429 magic_docs.append('%s%s:\n\t%s\n' %(self.shell.ESC_MAGIC,
429 magic_docs.append('%s%s:\n\t%s\n' %(self.shell.ESC_MAGIC,
430 fname,fndoc))
430 fname,fndoc))
431
431
432 magic_docs = ''.join(magic_docs)
432 magic_docs = ''.join(magic_docs)
433
433
434 if mode == 'rest':
434 if mode == 'rest':
435 return "".join(rest_docs)
435 return "".join(rest_docs)
436
436
437 if mode == 'latex':
437 if mode == 'latex':
438 print self.format_latex(magic_docs)
438 print self.format_latex(magic_docs)
439 return
439 return
440 else:
440 else:
441 magic_docs = self.format_screen(magic_docs)
441 magic_docs = self.format_screen(magic_docs)
442 if mode == 'brief':
442 if mode == 'brief':
443 return magic_docs
443 return magic_docs
444
444
445 outmsg = """
445 outmsg = """
446 IPython's 'magic' functions
446 IPython's 'magic' functions
447 ===========================
447 ===========================
448
448
449 The magic function system provides a series of functions which allow you to
449 The magic function system provides a series of functions which allow you to
450 control the behavior of IPython itself, plus a lot of system-type
450 control the behavior of IPython itself, plus a lot of system-type
451 features. All these functions are prefixed with a % character, but parameters
451 features. All these functions are prefixed with a % character, but parameters
452 are given without parentheses or quotes.
452 are given without parentheses or quotes.
453
453
454 NOTE: If you have 'automagic' enabled (via the command line option or with the
454 NOTE: If you have 'automagic' enabled (via the command line option or with the
455 %automagic function), you don't need to type in the % explicitly. By default,
455 %automagic function), you don't need to type in the % explicitly. By default,
456 IPython ships with automagic on, so you should only rarely need the % escape.
456 IPython ships with automagic on, so you should only rarely need the % escape.
457
457
458 Example: typing '%cd mydir' (without the quotes) changes you working directory
458 Example: typing '%cd mydir' (without the quotes) changes you working directory
459 to 'mydir', if it exists.
459 to 'mydir', if it exists.
460
460
461 You can define your own magic functions to extend the system. See the supplied
461 You can define your own magic functions to extend the system. See the supplied
462 ipythonrc and example-magic.py files for details (in your ipython
462 ipythonrc and example-magic.py files for details (in your ipython
463 configuration directory, typically $HOME/.ipython/).
463 configuration directory, typically $HOME/.ipython/).
464
464
465 You can also define your own aliased names for magic functions. In your
465 You can also define your own aliased names for magic functions. In your
466 ipythonrc file, placing a line like:
466 ipythonrc file, placing a line like:
467
467
468 execute __IPYTHON__.magic_pf = __IPYTHON__.magic_profile
468 execute __IPYTHON__.magic_pf = __IPYTHON__.magic_profile
469
469
470 will define %pf as a new name for %profile.
470 will define %pf as a new name for %profile.
471
471
472 You can also call magics in code using the ipmagic() function, which IPython
472 You can also call magics in code using the ipmagic() function, which IPython
473 automatically adds to the builtin namespace. Type 'ipmagic?' for details.
473 automatically adds to the builtin namespace. Type 'ipmagic?' for details.
474
474
475 For a list of the available magic functions, use %lsmagic. For a description
475 For a list of the available magic functions, use %lsmagic. For a description
476 of any of them, type %magic_name?, e.g. '%cd?'.
476 of any of them, type %magic_name?, e.g. '%cd?'.
477
477
478 Currently the magic system has the following functions:\n"""
478 Currently the magic system has the following functions:\n"""
479
479
480 mesc = self.shell.ESC_MAGIC
480 mesc = self.shell.ESC_MAGIC
481 outmsg = ("%s\n%s\n\nSummary of magic functions (from %slsmagic):"
481 outmsg = ("%s\n%s\n\nSummary of magic functions (from %slsmagic):"
482 "\n\n%s%s\n\n%s" % (outmsg,
482 "\n\n%s%s\n\n%s" % (outmsg,
483 magic_docs,mesc,mesc,
483 magic_docs,mesc,mesc,
484 (' '+mesc).join(self.lsmagic()),
484 (' '+mesc).join(self.lsmagic()),
485 Magic.auto_status[self.shell.rc.automagic] ) )
485 Magic.auto_status[self.shell.rc.automagic] ) )
486
486
487 page(outmsg,screen_lines=self.shell.rc.screen_length)
487 page(outmsg,screen_lines=self.shell.rc.screen_length)
488
488
489
489
490 def magic_autoindent(self, parameter_s = ''):
490 def magic_autoindent(self, parameter_s = ''):
491 """Toggle autoindent on/off (if available)."""
491 """Toggle autoindent on/off (if available)."""
492
492
493 self.shell.set_autoindent()
493 self.shell.set_autoindent()
494 print "Automatic indentation is:",['OFF','ON'][self.shell.autoindent]
494 print "Automatic indentation is:",['OFF','ON'][self.shell.autoindent]
495
495
496
496
497 def magic_automagic(self, parameter_s = ''):
497 def magic_automagic(self, parameter_s = ''):
498 """Make magic functions callable without having to type the initial %.
498 """Make magic functions callable without having to type the initial %.
499
499
500 Without argumentsl toggles on/off (when off, you must call it as
500 Without argumentsl toggles on/off (when off, you must call it as
501 %automagic, of course). With arguments it sets the value, and you can
501 %automagic, of course). With arguments it sets the value, and you can
502 use any of (case insensitive):
502 use any of (case insensitive):
503
503
504 - on,1,True: to activate
504 - on,1,True: to activate
505
505
506 - off,0,False: to deactivate.
506 - off,0,False: to deactivate.
507
507
508 Note that magic functions have lowest priority, so if there's a
508 Note that magic functions have lowest priority, so if there's a
509 variable whose name collides with that of a magic fn, automagic won't
509 variable whose name collides with that of a magic fn, automagic won't
510 work for that function (you get the variable instead). However, if you
510 work for that function (you get the variable instead). However, if you
511 delete the variable (del var), the previously shadowed magic function
511 delete the variable (del var), the previously shadowed magic function
512 becomes visible to automagic again."""
512 becomes visible to automagic again."""
513
513
514 rc = self.shell.rc
514 rc = self.shell.rc
515 arg = parameter_s.lower()
515 arg = parameter_s.lower()
516 if parameter_s in ('on','1','true'):
516 if parameter_s in ('on','1','true'):
517 rc.automagic = True
517 rc.automagic = True
518 elif parameter_s in ('off','0','false'):
518 elif parameter_s in ('off','0','false'):
519 rc.automagic = False
519 rc.automagic = False
520 else:
520 else:
521 rc.automagic = not rc.automagic
521 rc.automagic = not rc.automagic
522 print '\n' + Magic.auto_status[rc.automagic]
522 print '\n' + Magic.auto_status[rc.automagic]
523
523
524 @testdec.skip_doctest
524 @testdec.skip_doctest
525 def magic_autocall(self, parameter_s = ''):
525 def magic_autocall(self, parameter_s = ''):
526 """Make functions callable without having to type parentheses.
526 """Make functions callable without having to type parentheses.
527
527
528 Usage:
528 Usage:
529
529
530 %autocall [mode]
530 %autocall [mode]
531
531
532 The mode can be one of: 0->Off, 1->Smart, 2->Full. If not given, the
532 The mode can be one of: 0->Off, 1->Smart, 2->Full. If not given, the
533 value is toggled on and off (remembering the previous state).
533 value is toggled on and off (remembering the previous state).
534
534
535 In more detail, these values mean:
535 In more detail, these values mean:
536
536
537 0 -> fully disabled
537 0 -> fully disabled
538
538
539 1 -> active, but do not apply if there are no arguments on the line.
539 1 -> active, but do not apply if there are no arguments on the line.
540
540
541 In this mode, you get:
541 In this mode, you get:
542
542
543 In [1]: callable
543 In [1]: callable
544 Out[1]: <built-in function callable>
544 Out[1]: <built-in function callable>
545
545
546 In [2]: callable 'hello'
546 In [2]: callable 'hello'
547 ------> callable('hello')
547 ------> callable('hello')
548 Out[2]: False
548 Out[2]: False
549
549
550 2 -> Active always. Even if no arguments are present, the callable
550 2 -> Active always. Even if no arguments are present, the callable
551 object is called:
551 object is called:
552
552
553 In [2]: float
553 In [2]: float
554 ------> float()
554 ------> float()
555 Out[2]: 0.0
555 Out[2]: 0.0
556
556
557 Note that even with autocall off, you can still use '/' at the start of
557 Note that even with autocall off, you can still use '/' at the start of
558 a line to treat the first argument on the command line as a function
558 a line to treat the first argument on the command line as a function
559 and add parentheses to it:
559 and add parentheses to it:
560
560
561 In [8]: /str 43
561 In [8]: /str 43
562 ------> str(43)
562 ------> str(43)
563 Out[8]: '43'
563 Out[8]: '43'
564
564
565 # all-random (note for auto-testing)
565 # all-random (note for auto-testing)
566 """
566 """
567
567
568 rc = self.shell.rc
568 rc = self.shell.rc
569
569
570 if parameter_s:
570 if parameter_s:
571 arg = int(parameter_s)
571 arg = int(parameter_s)
572 else:
572 else:
573 arg = 'toggle'
573 arg = 'toggle'
574
574
575 if not arg in (0,1,2,'toggle'):
575 if not arg in (0,1,2,'toggle'):
576 error('Valid modes: (0->Off, 1->Smart, 2->Full')
576 error('Valid modes: (0->Off, 1->Smart, 2->Full')
577 return
577 return
578
578
579 if arg in (0,1,2):
579 if arg in (0,1,2):
580 rc.autocall = arg
580 rc.autocall = arg
581 else: # toggle
581 else: # toggle
582 if rc.autocall:
582 if rc.autocall:
583 self._magic_state.autocall_save = rc.autocall
583 self._magic_state.autocall_save = rc.autocall
584 rc.autocall = 0
584 rc.autocall = 0
585 else:
585 else:
586 try:
586 try:
587 rc.autocall = self._magic_state.autocall_save
587 rc.autocall = self._magic_state.autocall_save
588 except AttributeError:
588 except AttributeError:
589 rc.autocall = self._magic_state.autocall_save = 1
589 rc.autocall = self._magic_state.autocall_save = 1
590
590
591 print "Automatic calling is:",['OFF','Smart','Full'][rc.autocall]
591 print "Automatic calling is:",['OFF','Smart','Full'][rc.autocall]
592
592
593 def magic_system_verbose(self, parameter_s = ''):
593 def magic_system_verbose(self, parameter_s = ''):
594 """Set verbose printing of system calls.
594 """Set verbose printing of system calls.
595
595
596 If called without an argument, act as a toggle"""
596 If called without an argument, act as a toggle"""
597
597
598 if parameter_s:
598 if parameter_s:
599 val = bool(eval(parameter_s))
599 val = bool(eval(parameter_s))
600 else:
600 else:
601 val = None
601 val = None
602
602
603 self.shell.rc_set_toggle('system_verbose',val)
603 self.shell.rc_set_toggle('system_verbose',val)
604 print "System verbose printing is:",\
604 print "System verbose printing is:",\
605 ['OFF','ON'][self.shell.rc.system_verbose]
605 ['OFF','ON'][self.shell.rc.system_verbose]
606
606
607
607
608 def magic_page(self, parameter_s=''):
608 def magic_page(self, parameter_s=''):
609 """Pretty print the object and display it through a pager.
609 """Pretty print the object and display it through a pager.
610
610
611 %page [options] OBJECT
611 %page [options] OBJECT
612
612
613 If no object is given, use _ (last output).
613 If no object is given, use _ (last output).
614
614
615 Options:
615 Options:
616
616
617 -r: page str(object), don't pretty-print it."""
617 -r: page str(object), don't pretty-print it."""
618
618
619 # After a function contributed by Olivier Aubert, slightly modified.
619 # After a function contributed by Olivier Aubert, slightly modified.
620
620
621 # Process options/args
621 # Process options/args
622 opts,args = self.parse_options(parameter_s,'r')
622 opts,args = self.parse_options(parameter_s,'r')
623 raw = 'r' in opts
623 raw = 'r' in opts
624
624
625 oname = args and args or '_'
625 oname = args and args or '_'
626 info = self._ofind(oname)
626 info = self._ofind(oname)
627 if info['found']:
627 if info['found']:
628 txt = (raw and str or pformat)( info['obj'] )
628 txt = (raw and str or pformat)( info['obj'] )
629 page(txt)
629 page(txt)
630 else:
630 else:
631 print 'Object `%s` not found' % oname
631 print 'Object `%s` not found' % oname
632
632
633 def magic_profile(self, parameter_s=''):
633 def magic_profile(self, parameter_s=''):
634 """Print your currently active IPyhton profile."""
634 """Print your currently active IPyhton profile."""
635 if self.shell.rc.profile:
635 if self.shell.rc.profile:
636 printpl('Current IPython profile: $self.shell.rc.profile.')
636 printpl('Current IPython profile: $self.shell.rc.profile.')
637 else:
637 else:
638 print 'No profile active.'
638 print 'No profile active.'
639
639
640 def magic_pinfo(self, parameter_s='', namespaces=None):
640 def magic_pinfo(self, parameter_s='', namespaces=None):
641 """Provide detailed information about an object.
641 """Provide detailed information about an object.
642
642
643 '%pinfo object' is just a synonym for object? or ?object."""
643 '%pinfo object' is just a synonym for object? or ?object."""
644
644
645 #print 'pinfo par: <%s>' % parameter_s # dbg
645 #print 'pinfo par: <%s>' % parameter_s # dbg
646
646
647
647
648 # detail_level: 0 -> obj? , 1 -> obj??
648 # detail_level: 0 -> obj? , 1 -> obj??
649 detail_level = 0
649 detail_level = 0
650 # We need to detect if we got called as 'pinfo pinfo foo', which can
650 # We need to detect if we got called as 'pinfo pinfo foo', which can
651 # happen if the user types 'pinfo foo?' at the cmd line.
651 # happen if the user types 'pinfo foo?' at the cmd line.
652 pinfo,qmark1,oname,qmark2 = \
652 pinfo,qmark1,oname,qmark2 = \
653 re.match('(pinfo )?(\?*)(.*?)(\??$)',parameter_s).groups()
653 re.match('(pinfo )?(\?*)(.*?)(\??$)',parameter_s).groups()
654 if pinfo or qmark1 or qmark2:
654 if pinfo or qmark1 or qmark2:
655 detail_level = 1
655 detail_level = 1
656 if "*" in oname:
656 if "*" in oname:
657 self.magic_psearch(oname)
657 self.magic_psearch(oname)
658 else:
658 else:
659 self._inspect('pinfo', oname, detail_level=detail_level,
659 self._inspect('pinfo', oname, detail_level=detail_level,
660 namespaces=namespaces)
660 namespaces=namespaces)
661
661
662 def magic_pdef(self, parameter_s='', namespaces=None):
662 def magic_pdef(self, parameter_s='', namespaces=None):
663 """Print the definition header for any callable object.
663 """Print the definition header for any callable object.
664
664
665 If the object is a class, print the constructor information."""
665 If the object is a class, print the constructor information."""
666 self._inspect('pdef',parameter_s, namespaces)
666 self._inspect('pdef',parameter_s, namespaces)
667
667
668 def magic_pdoc(self, parameter_s='', namespaces=None):
668 def magic_pdoc(self, parameter_s='', namespaces=None):
669 """Print the docstring for an object.
669 """Print the docstring for an object.
670
670
671 If the given object is a class, it will print both the class and the
671 If the given object is a class, it will print both the class and the
672 constructor docstrings."""
672 constructor docstrings."""
673 self._inspect('pdoc',parameter_s, namespaces)
673 self._inspect('pdoc',parameter_s, namespaces)
674
674
675 def magic_psource(self, parameter_s='', namespaces=None):
675 def magic_psource(self, parameter_s='', namespaces=None):
676 """Print (or run through pager) the source code for an object."""
676 """Print (or run through pager) the source code for an object."""
677 self._inspect('psource',parameter_s, namespaces)
677 self._inspect('psource',parameter_s, namespaces)
678
678
679 def magic_pfile(self, parameter_s=''):
679 def magic_pfile(self, parameter_s=''):
680 """Print (or run through pager) the file where an object is defined.
680 """Print (or run through pager) the file where an object is defined.
681
681
682 The file opens at the line where the object definition begins. IPython
682 The file opens at the line where the object definition begins. IPython
683 will honor the environment variable PAGER if set, and otherwise will
683 will honor the environment variable PAGER if set, and otherwise will
684 do its best to print the file in a convenient form.
684 do its best to print the file in a convenient form.
685
685
686 If the given argument is not an object currently defined, IPython will
686 If the given argument is not an object currently defined, IPython will
687 try to interpret it as a filename (automatically adding a .py extension
687 try to interpret it as a filename (automatically adding a .py extension
688 if needed). You can thus use %pfile as a syntax highlighting code
688 if needed). You can thus use %pfile as a syntax highlighting code
689 viewer."""
689 viewer."""
690
690
691 # first interpret argument as an object name
691 # first interpret argument as an object name
692 out = self._inspect('pfile',parameter_s)
692 out = self._inspect('pfile',parameter_s)
693 # if not, try the input as a filename
693 # if not, try the input as a filename
694 if out == 'not found':
694 if out == 'not found':
695 try:
695 try:
696 filename = get_py_filename(parameter_s)
696 filename = get_py_filename(parameter_s)
697 except IOError,msg:
697 except IOError,msg:
698 print msg
698 print msg
699 return
699 return
700 page(self.shell.inspector.format(file(filename).read()))
700 page(self.shell.inspector.format(file(filename).read()))
701
701
702 def _inspect(self,meth,oname,namespaces=None,**kw):
702 def _inspect(self,meth,oname,namespaces=None,**kw):
703 """Generic interface to the inspector system.
703 """Generic interface to the inspector system.
704
704
705 This function is meant to be called by pdef, pdoc & friends."""
705 This function is meant to be called by pdef, pdoc & friends."""
706
706
707 #oname = oname.strip()
707 #oname = oname.strip()
708 #print '1- oname: <%r>' % oname # dbg
708 #print '1- oname: <%r>' % oname # dbg
709 try:
709 try:
710 oname = oname.strip().encode('ascii')
710 oname = oname.strip().encode('ascii')
711 #print '2- oname: <%r>' % oname # dbg
711 #print '2- oname: <%r>' % oname # dbg
712 except UnicodeEncodeError:
712 except UnicodeEncodeError:
713 print 'Python identifiers can only contain ascii characters.'
713 print 'Python identifiers can only contain ascii characters.'
714 return 'not found'
714 return 'not found'
715
715
716 info = Struct(self._ofind(oname, namespaces))
716 info = Struct(self._ofind(oname, namespaces))
717
717
718 if info.found:
718 if info.found:
719 try:
719 try:
720 IPython.generics.inspect_object(info.obj)
720 IPython.generics.inspect_object(info.obj)
721 return
721 return
722 except IPython.ipapi.TryNext:
722 except IPython.ipapi.TryNext:
723 pass
723 pass
724 # Get the docstring of the class property if it exists.
724 # Get the docstring of the class property if it exists.
725 path = oname.split('.')
725 path = oname.split('.')
726 root = '.'.join(path[:-1])
726 root = '.'.join(path[:-1])
727 if info.parent is not None:
727 if info.parent is not None:
728 try:
728 try:
729 target = getattr(info.parent, '__class__')
729 target = getattr(info.parent, '__class__')
730 # The object belongs to a class instance.
730 # The object belongs to a class instance.
731 try:
731 try:
732 target = getattr(target, path[-1])
732 target = getattr(target, path[-1])
733 # The class defines the object.
733 # The class defines the object.
734 if isinstance(target, property):
734 if isinstance(target, property):
735 oname = root + '.__class__.' + path[-1]
735 oname = root + '.__class__.' + path[-1]
736 info = Struct(self._ofind(oname))
736 info = Struct(self._ofind(oname))
737 except AttributeError: pass
737 except AttributeError: pass
738 except AttributeError: pass
738 except AttributeError: pass
739
739
740 pmethod = getattr(self.shell.inspector,meth)
740 pmethod = getattr(self.shell.inspector,meth)
741 formatter = info.ismagic and self.format_screen or None
741 formatter = info.ismagic and self.format_screen or None
742 if meth == 'pdoc':
742 if meth == 'pdoc':
743 pmethod(info.obj,oname,formatter)
743 pmethod(info.obj,oname,formatter)
744 elif meth == 'pinfo':
744 elif meth == 'pinfo':
745 pmethod(info.obj,oname,formatter,info,**kw)
745 pmethod(info.obj,oname,formatter,info,**kw)
746 else:
746 else:
747 pmethod(info.obj,oname)
747 pmethod(info.obj,oname)
748 else:
748 else:
749 print 'Object `%s` not found.' % oname
749 print 'Object `%s` not found.' % oname
750 return 'not found' # so callers can take other action
750 return 'not found' # so callers can take other action
751
751
752 def magic_psearch(self, parameter_s=''):
752 def magic_psearch(self, parameter_s=''):
753 """Search for object in namespaces by wildcard.
753 """Search for object in namespaces by wildcard.
754
754
755 %psearch [options] PATTERN [OBJECT TYPE]
755 %psearch [options] PATTERN [OBJECT TYPE]
756
756
757 Note: ? can be used as a synonym for %psearch, at the beginning or at
757 Note: ? can be used as a synonym for %psearch, at the beginning or at
758 the end: both a*? and ?a* are equivalent to '%psearch a*'. Still, the
758 the end: both a*? and ?a* are equivalent to '%psearch a*'. Still, the
759 rest of the command line must be unchanged (options come first), so
759 rest of the command line must be unchanged (options come first), so
760 for example the following forms are equivalent
760 for example the following forms are equivalent
761
761
762 %psearch -i a* function
762 %psearch -i a* function
763 -i a* function?
763 -i a* function?
764 ?-i a* function
764 ?-i a* function
765
765
766 Arguments:
766 Arguments:
767
767
768 PATTERN
768 PATTERN
769
769
770 where PATTERN is a string containing * as a wildcard similar to its
770 where PATTERN is a string containing * as a wildcard similar to its
771 use in a shell. The pattern is matched in all namespaces on the
771 use in a shell. The pattern is matched in all namespaces on the
772 search path. By default objects starting with a single _ are not
772 search path. By default objects starting with a single _ are not
773 matched, many IPython generated objects have a single
773 matched, many IPython generated objects have a single
774 underscore. The default is case insensitive matching. Matching is
774 underscore. The default is case insensitive matching. Matching is
775 also done on the attributes of objects and not only on the objects
775 also done on the attributes of objects and not only on the objects
776 in a module.
776 in a module.
777
777
778 [OBJECT TYPE]
778 [OBJECT TYPE]
779
779
780 Is the name of a python type from the types module. The name is
780 Is the name of a python type from the types module. The name is
781 given in lowercase without the ending type, ex. StringType is
781 given in lowercase without the ending type, ex. StringType is
782 written string. By adding a type here only objects matching the
782 written string. By adding a type here only objects matching the
783 given type are matched. Using all here makes the pattern match all
783 given type are matched. Using all here makes the pattern match all
784 types (this is the default).
784 types (this is the default).
785
785
786 Options:
786 Options:
787
787
788 -a: makes the pattern match even objects whose names start with a
788 -a: makes the pattern match even objects whose names start with a
789 single underscore. These names are normally ommitted from the
789 single underscore. These names are normally ommitted from the
790 search.
790 search.
791
791
792 -i/-c: make the pattern case insensitive/sensitive. If neither of
792 -i/-c: make the pattern case insensitive/sensitive. If neither of
793 these options is given, the default is read from your ipythonrc
793 these options is given, the default is read from your ipythonrc
794 file. The option name which sets this value is
794 file. The option name which sets this value is
795 'wildcards_case_sensitive'. If this option is not specified in your
795 'wildcards_case_sensitive'. If this option is not specified in your
796 ipythonrc file, IPython's internal default is to do a case sensitive
796 ipythonrc file, IPython's internal default is to do a case sensitive
797 search.
797 search.
798
798
799 -e/-s NAMESPACE: exclude/search a given namespace. The pattern you
799 -e/-s NAMESPACE: exclude/search a given namespace. The pattern you
800 specifiy can be searched in any of the following namespaces:
800 specifiy can be searched in any of the following namespaces:
801 'builtin', 'user', 'user_global','internal', 'alias', where
801 'builtin', 'user', 'user_global','internal', 'alias', where
802 'builtin' and 'user' are the search defaults. Note that you should
802 'builtin' and 'user' are the search defaults. Note that you should
803 not use quotes when specifying namespaces.
803 not use quotes when specifying namespaces.
804
804
805 'Builtin' contains the python module builtin, 'user' contains all
805 'Builtin' contains the python module builtin, 'user' contains all
806 user data, 'alias' only contain the shell aliases and no python
806 user data, 'alias' only contain the shell aliases and no python
807 objects, 'internal' contains objects used by IPython. The
807 objects, 'internal' contains objects used by IPython. The
808 'user_global' namespace is only used by embedded IPython instances,
808 'user_global' namespace is only used by embedded IPython instances,
809 and it contains module-level globals. You can add namespaces to the
809 and it contains module-level globals. You can add namespaces to the
810 search with -s or exclude them with -e (these options can be given
810 search with -s or exclude them with -e (these options can be given
811 more than once).
811 more than once).
812
812
813 Examples:
813 Examples:
814
814
815 %psearch a* -> objects beginning with an a
815 %psearch a* -> objects beginning with an a
816 %psearch -e builtin a* -> objects NOT in the builtin space starting in a
816 %psearch -e builtin a* -> objects NOT in the builtin space starting in a
817 %psearch a* function -> all functions beginning with an a
817 %psearch a* function -> all functions beginning with an a
818 %psearch re.e* -> objects beginning with an e in module re
818 %psearch re.e* -> objects beginning with an e in module re
819 %psearch r*.e* -> objects that start with e in modules starting in r
819 %psearch r*.e* -> objects that start with e in modules starting in r
820 %psearch r*.* string -> all strings in modules beginning with r
820 %psearch r*.* string -> all strings in modules beginning with r
821
821
822 Case sensitve search:
822 Case sensitve search:
823
823
824 %psearch -c a* list all object beginning with lower case a
824 %psearch -c a* list all object beginning with lower case a
825
825
826 Show objects beginning with a single _:
826 Show objects beginning with a single _:
827
827
828 %psearch -a _* list objects beginning with a single underscore"""
828 %psearch -a _* list objects beginning with a single underscore"""
829 try:
829 try:
830 parameter_s = parameter_s.encode('ascii')
830 parameter_s = parameter_s.encode('ascii')
831 except UnicodeEncodeError:
831 except UnicodeEncodeError:
832 print 'Python identifiers can only contain ascii characters.'
832 print 'Python identifiers can only contain ascii characters.'
833 return
833 return
834
834
835 # default namespaces to be searched
835 # default namespaces to be searched
836 def_search = ['user','builtin']
836 def_search = ['user','builtin']
837
837
838 # Process options/args
838 # Process options/args
839 opts,args = self.parse_options(parameter_s,'cias:e:',list_all=True)
839 opts,args = self.parse_options(parameter_s,'cias:e:',list_all=True)
840 opt = opts.get
840 opt = opts.get
841 shell = self.shell
841 shell = self.shell
842 psearch = shell.inspector.psearch
842 psearch = shell.inspector.psearch
843
843
844 # select case options
844 # select case options
845 if opts.has_key('i'):
845 if opts.has_key('i'):
846 ignore_case = True
846 ignore_case = True
847 elif opts.has_key('c'):
847 elif opts.has_key('c'):
848 ignore_case = False
848 ignore_case = False
849 else:
849 else:
850 ignore_case = not shell.rc.wildcards_case_sensitive
850 ignore_case = not shell.rc.wildcards_case_sensitive
851
851
852 # Build list of namespaces to search from user options
852 # Build list of namespaces to search from user options
853 def_search.extend(opt('s',[]))
853 def_search.extend(opt('s',[]))
854 ns_exclude = ns_exclude=opt('e',[])
854 ns_exclude = ns_exclude=opt('e',[])
855 ns_search = [nm for nm in def_search if nm not in ns_exclude]
855 ns_search = [nm for nm in def_search if nm not in ns_exclude]
856
856
857 # Call the actual search
857 # Call the actual search
858 try:
858 try:
859 psearch(args,shell.ns_table,ns_search,
859 psearch(args,shell.ns_table,ns_search,
860 show_all=opt('a'),ignore_case=ignore_case)
860 show_all=opt('a'),ignore_case=ignore_case)
861 except:
861 except:
862 shell.showtraceback()
862 shell.showtraceback()
863
863
864 def magic_who_ls(self, parameter_s=''):
864 def magic_who_ls(self, parameter_s=''):
865 """Return a sorted list of all interactive variables.
865 """Return a sorted list of all interactive variables.
866
866
867 If arguments are given, only variables of types matching these
867 If arguments are given, only variables of types matching these
868 arguments are returned."""
868 arguments are returned."""
869
869
870 user_ns = self.shell.user_ns
870 user_ns = self.shell.user_ns
871 internal_ns = self.shell.internal_ns
871 internal_ns = self.shell.internal_ns
872 user_config_ns = self.shell.user_config_ns
872 user_config_ns = self.shell.user_config_ns
873 out = []
873 out = []
874 typelist = parameter_s.split()
874 typelist = parameter_s.split()
875
875
876 for i in user_ns:
876 for i in user_ns:
877 if not (i.startswith('_') or i.startswith('_i')) \
877 if not (i.startswith('_') or i.startswith('_i')) \
878 and not (i in internal_ns or i in user_config_ns):
878 and not (i in internal_ns or i in user_config_ns):
879 if typelist:
879 if typelist:
880 if type(user_ns[i]).__name__ in typelist:
880 if type(user_ns[i]).__name__ in typelist:
881 out.append(i)
881 out.append(i)
882 else:
882 else:
883 out.append(i)
883 out.append(i)
884 out.sort()
884 out.sort()
885 return out
885 return out
886
886
887 def magic_who(self, parameter_s=''):
887 def magic_who(self, parameter_s=''):
888 """Print all interactive variables, with some minimal formatting.
888 """Print all interactive variables, with some minimal formatting.
889
889
890 If any arguments are given, only variables whose type matches one of
890 If any arguments are given, only variables whose type matches one of
891 these are printed. For example:
891 these are printed. For example:
892
892
893 %who function str
893 %who function str
894
894
895 will only list functions and strings, excluding all other types of
895 will only list functions and strings, excluding all other types of
896 variables. To find the proper type names, simply use type(var) at a
896 variables. To find the proper type names, simply use type(var) at a
897 command line to see how python prints type names. For example:
897 command line to see how python prints type names. For example:
898
898
899 In [1]: type('hello')\\
899 In [1]: type('hello')\\
900 Out[1]: <type 'str'>
900 Out[1]: <type 'str'>
901
901
902 indicates that the type name for strings is 'str'.
902 indicates that the type name for strings is 'str'.
903
903
904 %who always excludes executed names loaded through your configuration
904 %who always excludes executed names loaded through your configuration
905 file and things which are internal to IPython.
905 file and things which are internal to IPython.
906
906
907 This is deliberate, as typically you may load many modules and the
907 This is deliberate, as typically you may load many modules and the
908 purpose of %who is to show you only what you've manually defined."""
908 purpose of %who is to show you only what you've manually defined."""
909
909
910 varlist = self.magic_who_ls(parameter_s)
910 varlist = self.magic_who_ls(parameter_s)
911 if not varlist:
911 if not varlist:
912 if parameter_s:
912 if parameter_s:
913 print 'No variables match your requested type.'
913 print 'No variables match your requested type.'
914 else:
914 else:
915 print 'Interactive namespace is empty.'
915 print 'Interactive namespace is empty.'
916 return
916 return
917
917
918 # if we have variables, move on...
918 # if we have variables, move on...
919 count = 0
919 count = 0
920 for i in varlist:
920 for i in varlist:
921 print i+'\t',
921 print i+'\t',
922 count += 1
922 count += 1
923 if count > 8:
923 if count > 8:
924 count = 0
924 count = 0
925 print
925 print
926 print
926 print
927
927
928 def magic_whos(self, parameter_s=''):
928 def magic_whos(self, parameter_s=''):
929 """Like %who, but gives some extra information about each variable.
929 """Like %who, but gives some extra information about each variable.
930
930
931 The same type filtering of %who can be applied here.
931 The same type filtering of %who can be applied here.
932
932
933 For all variables, the type is printed. Additionally it prints:
933 For all variables, the type is printed. Additionally it prints:
934
934
935 - For {},[],(): their length.
935 - For {},[],(): their length.
936
936
937 - For numpy and Numeric arrays, a summary with shape, number of
937 - For numpy and Numeric arrays, a summary with shape, number of
938 elements, typecode and size in memory.
938 elements, typecode and size in memory.
939
939
940 - Everything else: a string representation, snipping their middle if
940 - Everything else: a string representation, snipping their middle if
941 too long."""
941 too long."""
942
942
943 varnames = self.magic_who_ls(parameter_s)
943 varnames = self.magic_who_ls(parameter_s)
944 if not varnames:
944 if not varnames:
945 if parameter_s:
945 if parameter_s:
946 print 'No variables match your requested type.'
946 print 'No variables match your requested type.'
947 else:
947 else:
948 print 'Interactive namespace is empty.'
948 print 'Interactive namespace is empty.'
949 return
949 return
950
950
951 # if we have variables, move on...
951 # if we have variables, move on...
952
952
953 # for these types, show len() instead of data:
953 # for these types, show len() instead of data:
954 seq_types = [types.DictType,types.ListType,types.TupleType]
954 seq_types = [types.DictType,types.ListType,types.TupleType]
955
955
956 # for numpy/Numeric arrays, display summary info
956 # for numpy/Numeric arrays, display summary info
957 try:
957 try:
958 import numpy
958 import numpy
959 except ImportError:
959 except ImportError:
960 ndarray_type = None
960 ndarray_type = None
961 else:
961 else:
962 ndarray_type = numpy.ndarray.__name__
962 ndarray_type = numpy.ndarray.__name__
963 try:
963 try:
964 import Numeric
964 import Numeric
965 except ImportError:
965 except ImportError:
966 array_type = None
966 array_type = None
967 else:
967 else:
968 array_type = Numeric.ArrayType.__name__
968 array_type = Numeric.ArrayType.__name__
969
969
970 # Find all variable names and types so we can figure out column sizes
970 # Find all variable names and types so we can figure out column sizes
971 def get_vars(i):
971 def get_vars(i):
972 return self.shell.user_ns[i]
972 return self.shell.user_ns[i]
973
973
974 # some types are well known and can be shorter
974 # some types are well known and can be shorter
975 abbrevs = {'IPython.macro.Macro' : 'Macro'}
975 abbrevs = {'IPython.macro.Macro' : 'Macro'}
976 def type_name(v):
976 def type_name(v):
977 tn = type(v).__name__
977 tn = type(v).__name__
978 return abbrevs.get(tn,tn)
978 return abbrevs.get(tn,tn)
979
979
980 varlist = map(get_vars,varnames)
980 varlist = map(get_vars,varnames)
981
981
982 typelist = []
982 typelist = []
983 for vv in varlist:
983 for vv in varlist:
984 tt = type_name(vv)
984 tt = type_name(vv)
985
985
986 if tt=='instance':
986 if tt=='instance':
987 typelist.append( abbrevs.get(str(vv.__class__),
987 typelist.append( abbrevs.get(str(vv.__class__),
988 str(vv.__class__)))
988 str(vv.__class__)))
989 else:
989 else:
990 typelist.append(tt)
990 typelist.append(tt)
991
991
992 # column labels and # of spaces as separator
992 # column labels and # of spaces as separator
993 varlabel = 'Variable'
993 varlabel = 'Variable'
994 typelabel = 'Type'
994 typelabel = 'Type'
995 datalabel = 'Data/Info'
995 datalabel = 'Data/Info'
996 colsep = 3
996 colsep = 3
997 # variable format strings
997 # variable format strings
998 vformat = "$vname.ljust(varwidth)$vtype.ljust(typewidth)"
998 vformat = "$vname.ljust(varwidth)$vtype.ljust(typewidth)"
999 vfmt_short = '$vstr[:25]<...>$vstr[-25:]'
999 vfmt_short = '$vstr[:25]<...>$vstr[-25:]'
1000 aformat = "%s: %s elems, type `%s`, %s bytes"
1000 aformat = "%s: %s elems, type `%s`, %s bytes"
1001 # find the size of the columns to format the output nicely
1001 # find the size of the columns to format the output nicely
1002 varwidth = max(max(map(len,varnames)), len(varlabel)) + colsep
1002 varwidth = max(max(map(len,varnames)), len(varlabel)) + colsep
1003 typewidth = max(max(map(len,typelist)), len(typelabel)) + colsep
1003 typewidth = max(max(map(len,typelist)), len(typelabel)) + colsep
1004 # table header
1004 # table header
1005 print varlabel.ljust(varwidth) + typelabel.ljust(typewidth) + \
1005 print varlabel.ljust(varwidth) + typelabel.ljust(typewidth) + \
1006 ' '+datalabel+'\n' + '-'*(varwidth+typewidth+len(datalabel)+1)
1006 ' '+datalabel+'\n' + '-'*(varwidth+typewidth+len(datalabel)+1)
1007 # and the table itself
1007 # and the table itself
1008 kb = 1024
1008 kb = 1024
1009 Mb = 1048576 # kb**2
1009 Mb = 1048576 # kb**2
1010 for vname,var,vtype in zip(varnames,varlist,typelist):
1010 for vname,var,vtype in zip(varnames,varlist,typelist):
1011 print itpl(vformat),
1011 print itpl(vformat),
1012 if vtype in seq_types:
1012 if vtype in seq_types:
1013 print len(var)
1013 print len(var)
1014 elif vtype in [array_type,ndarray_type]:
1014 elif vtype in [array_type,ndarray_type]:
1015 vshape = str(var.shape).replace(',','').replace(' ','x')[1:-1]
1015 vshape = str(var.shape).replace(',','').replace(' ','x')[1:-1]
1016 if vtype==ndarray_type:
1016 if vtype==ndarray_type:
1017 # numpy
1017 # numpy
1018 vsize = var.size
1018 vsize = var.size
1019 vbytes = vsize*var.itemsize
1019 vbytes = vsize*var.itemsize
1020 vdtype = var.dtype
1020 vdtype = var.dtype
1021 else:
1021 else:
1022 # Numeric
1022 # Numeric
1023 vsize = Numeric.size(var)
1023 vsize = Numeric.size(var)
1024 vbytes = vsize*var.itemsize()
1024 vbytes = vsize*var.itemsize()
1025 vdtype = var.typecode()
1025 vdtype = var.typecode()
1026
1026
1027 if vbytes < 100000:
1027 if vbytes < 100000:
1028 print aformat % (vshape,vsize,vdtype,vbytes)
1028 print aformat % (vshape,vsize,vdtype,vbytes)
1029 else:
1029 else:
1030 print aformat % (vshape,vsize,vdtype,vbytes),
1030 print aformat % (vshape,vsize,vdtype,vbytes),
1031 if vbytes < Mb:
1031 if vbytes < Mb:
1032 print '(%s kb)' % (vbytes/kb,)
1032 print '(%s kb)' % (vbytes/kb,)
1033 else:
1033 else:
1034 print '(%s Mb)' % (vbytes/Mb,)
1034 print '(%s Mb)' % (vbytes/Mb,)
1035 else:
1035 else:
1036 try:
1036 try:
1037 vstr = str(var)
1037 vstr = str(var)
1038 except UnicodeEncodeError:
1038 except UnicodeEncodeError:
1039 vstr = unicode(var).encode(sys.getdefaultencoding(),
1039 vstr = unicode(var).encode(sys.getdefaultencoding(),
1040 'backslashreplace')
1040 'backslashreplace')
1041 vstr = vstr.replace('\n','\\n')
1041 vstr = vstr.replace('\n','\\n')
1042 if len(vstr) < 50:
1042 if len(vstr) < 50:
1043 print vstr
1043 print vstr
1044 else:
1044 else:
1045 printpl(vfmt_short)
1045 printpl(vfmt_short)
1046
1046
1047 def magic_reset(self, parameter_s=''):
1047 def magic_reset(self, parameter_s=''):
1048 """Resets the namespace by removing all names defined by the user.
1048 """Resets the namespace by removing all names defined by the user.
1049
1049
1050 Input/Output history are left around in case you need them.
1050 Input/Output history are left around in case you need them.
1051
1051
1052 Parameters
1052 Parameters
1053 ----------
1053 ----------
1054 -y : force reset without asking for confirmation.
1054 -y : force reset without asking for confirmation.
1055
1055
1056 Examples
1056 Examples
1057 --------
1057 --------
1058 In [6]: a = 1
1058 In [6]: a = 1
1059
1059
1060 In [7]: a
1060 In [7]: a
1061 Out[7]: 1
1061 Out[7]: 1
1062
1062
1063 In [8]: 'a' in _ip.user_ns
1063 In [8]: 'a' in _ip.user_ns
1064 Out[8]: True
1064 Out[8]: True
1065
1065
1066 In [9]: %reset -f
1066 In [9]: %reset -f
1067
1067
1068 In [10]: 'a' in _ip.user_ns
1068 In [10]: 'a' in _ip.user_ns
1069 Out[10]: False
1069 Out[10]: False
1070 """
1070 """
1071
1071
1072 if parameter_s == '-f':
1072 if parameter_s == '-f':
1073 ans = True
1073 ans = True
1074 else:
1074 else:
1075 ans = self.shell.ask_yes_no(
1075 ans = self.shell.ask_yes_no(
1076 "Once deleted, variables cannot be recovered. Proceed (y/[n])? ")
1076 "Once deleted, variables cannot be recovered. Proceed (y/[n])? ")
1077 if not ans:
1077 if not ans:
1078 print 'Nothing done.'
1078 print 'Nothing done.'
1079 return
1079 return
1080 user_ns = self.shell.user_ns
1080 user_ns = self.shell.user_ns
1081 for i in self.magic_who_ls():
1081 for i in self.magic_who_ls():
1082 del(user_ns[i])
1082 del(user_ns[i])
1083
1083
1084 # Also flush the private list of module references kept for script
1084 # Also flush the private list of module references kept for script
1085 # execution protection
1085 # execution protection
1086 self.shell.clear_main_mod_cache()
1086 self.shell.clear_main_mod_cache()
1087
1087
1088 def magic_logstart(self,parameter_s=''):
1088 def magic_logstart(self,parameter_s=''):
1089 """Start logging anywhere in a session.
1089 """Start logging anywhere in a session.
1090
1090
1091 %logstart [-o|-r|-t] [log_name [log_mode]]
1091 %logstart [-o|-r|-t] [log_name [log_mode]]
1092
1092
1093 If no name is given, it defaults to a file named 'ipython_log.py' in your
1093 If no name is given, it defaults to a file named 'ipython_log.py' in your
1094 current directory, in 'rotate' mode (see below).
1094 current directory, in 'rotate' mode (see below).
1095
1095
1096 '%logstart name' saves to file 'name' in 'backup' mode. It saves your
1096 '%logstart name' saves to file 'name' in 'backup' mode. It saves your
1097 history up to that point and then continues logging.
1097 history up to that point and then continues logging.
1098
1098
1099 %logstart takes a second optional parameter: logging mode. This can be one
1099 %logstart takes a second optional parameter: logging mode. This can be one
1100 of (note that the modes are given unquoted):\\
1100 of (note that the modes are given unquoted):\\
1101 append: well, that says it.\\
1101 append: well, that says it.\\
1102 backup: rename (if exists) to name~ and start name.\\
1102 backup: rename (if exists) to name~ and start name.\\
1103 global: single logfile in your home dir, appended to.\\
1103 global: single logfile in your home dir, appended to.\\
1104 over : overwrite existing log.\\
1104 over : overwrite existing log.\\
1105 rotate: create rotating logs name.1~, name.2~, etc.
1105 rotate: create rotating logs name.1~, name.2~, etc.
1106
1106
1107 Options:
1107 Options:
1108
1108
1109 -o: log also IPython's output. In this mode, all commands which
1109 -o: log also IPython's output. In this mode, all commands which
1110 generate an Out[NN] prompt are recorded to the logfile, right after
1110 generate an Out[NN] prompt are recorded to the logfile, right after
1111 their corresponding input line. The output lines are always
1111 their corresponding input line. The output lines are always
1112 prepended with a '#[Out]# ' marker, so that the log remains valid
1112 prepended with a '#[Out]# ' marker, so that the log remains valid
1113 Python code.
1113 Python code.
1114
1114
1115 Since this marker is always the same, filtering only the output from
1115 Since this marker is always the same, filtering only the output from
1116 a log is very easy, using for example a simple awk call:
1116 a log is very easy, using for example a simple awk call:
1117
1117
1118 awk -F'#\\[Out\\]# ' '{if($2) {print $2}}' ipython_log.py
1118 awk -F'#\\[Out\\]# ' '{if($2) {print $2}}' ipython_log.py
1119
1119
1120 -r: log 'raw' input. Normally, IPython's logs contain the processed
1120 -r: log 'raw' input. Normally, IPython's logs contain the processed
1121 input, so that user lines are logged in their final form, converted
1121 input, so that user lines are logged in their final form, converted
1122 into valid Python. For example, %Exit is logged as
1122 into valid Python. For example, %Exit is logged as
1123 '_ip.magic("Exit"). If the -r flag is given, all input is logged
1123 '_ip.magic("Exit"). If the -r flag is given, all input is logged
1124 exactly as typed, with no transformations applied.
1124 exactly as typed, with no transformations applied.
1125
1125
1126 -t: put timestamps before each input line logged (these are put in
1126 -t: put timestamps before each input line logged (these are put in
1127 comments)."""
1127 comments)."""
1128
1128
1129 opts,par = self.parse_options(parameter_s,'ort')
1129 opts,par = self.parse_options(parameter_s,'ort')
1130 log_output = 'o' in opts
1130 log_output = 'o' in opts
1131 log_raw_input = 'r' in opts
1131 log_raw_input = 'r' in opts
1132 timestamp = 't' in opts
1132 timestamp = 't' in opts
1133
1133
1134 rc = self.shell.rc
1134 rc = self.shell.rc
1135 logger = self.shell.logger
1135 logger = self.shell.logger
1136
1136
1137 # if no args are given, the defaults set in the logger constructor by
1137 # if no args are given, the defaults set in the logger constructor by
1138 # ipytohn remain valid
1138 # ipytohn remain valid
1139 if par:
1139 if par:
1140 try:
1140 try:
1141 logfname,logmode = par.split()
1141 logfname,logmode = par.split()
1142 except:
1142 except:
1143 logfname = par
1143 logfname = par
1144 logmode = 'backup'
1144 logmode = 'backup'
1145 else:
1145 else:
1146 logfname = logger.logfname
1146 logfname = logger.logfname
1147 logmode = logger.logmode
1147 logmode = logger.logmode
1148 # put logfname into rc struct as if it had been called on the command
1148 # put logfname into rc struct as if it had been called on the command
1149 # line, so it ends up saved in the log header Save it in case we need
1149 # line, so it ends up saved in the log header Save it in case we need
1150 # to restore it...
1150 # to restore it...
1151 old_logfile = rc.opts.get('logfile','')
1151 old_logfile = rc.opts.get('logfile','')
1152 if logfname:
1152 if logfname:
1153 logfname = os.path.expanduser(logfname)
1153 logfname = os.path.expanduser(logfname)
1154 rc.opts.logfile = logfname
1154 rc.opts.logfile = logfname
1155 loghead = self.shell.loghead_tpl % (rc.opts,rc.args)
1155 loghead = self.shell.loghead_tpl % (rc.opts,rc.args)
1156 try:
1156 try:
1157 started = logger.logstart(logfname,loghead,logmode,
1157 started = logger.logstart(logfname,loghead,logmode,
1158 log_output,timestamp,log_raw_input)
1158 log_output,timestamp,log_raw_input)
1159 except:
1159 except:
1160 rc.opts.logfile = old_logfile
1160 rc.opts.logfile = old_logfile
1161 warn("Couldn't start log: %s" % sys.exc_info()[1])
1161 warn("Couldn't start log: %s" % sys.exc_info()[1])
1162 else:
1162 else:
1163 # log input history up to this point, optionally interleaving
1163 # log input history up to this point, optionally interleaving
1164 # output if requested
1164 # output if requested
1165
1165
1166 if timestamp:
1166 if timestamp:
1167 # disable timestamping for the previous history, since we've
1167 # disable timestamping for the previous history, since we've
1168 # lost those already (no time machine here).
1168 # lost those already (no time machine here).
1169 logger.timestamp = False
1169 logger.timestamp = False
1170
1170
1171 if log_raw_input:
1171 if log_raw_input:
1172 input_hist = self.shell.input_hist_raw
1172 input_hist = self.shell.input_hist_raw
1173 else:
1173 else:
1174 input_hist = self.shell.input_hist
1174 input_hist = self.shell.input_hist
1175
1175
1176 if log_output:
1176 if log_output:
1177 log_write = logger.log_write
1177 log_write = logger.log_write
1178 output_hist = self.shell.output_hist
1178 output_hist = self.shell.output_hist
1179 for n in range(1,len(input_hist)-1):
1179 for n in range(1,len(input_hist)-1):
1180 log_write(input_hist[n].rstrip())
1180 log_write(input_hist[n].rstrip())
1181 if n in output_hist:
1181 if n in output_hist:
1182 log_write(repr(output_hist[n]),'output')
1182 log_write(repr(output_hist[n]),'output')
1183 else:
1183 else:
1184 logger.log_write(input_hist[1:])
1184 logger.log_write(input_hist[1:])
1185 if timestamp:
1185 if timestamp:
1186 # re-enable timestamping
1186 # re-enable timestamping
1187 logger.timestamp = True
1187 logger.timestamp = True
1188
1188
1189 print ('Activating auto-logging. '
1189 print ('Activating auto-logging. '
1190 'Current session state plus future input saved.')
1190 'Current session state plus future input saved.')
1191 logger.logstate()
1191 logger.logstate()
1192
1192
1193 def magic_logstop(self,parameter_s=''):
1193 def magic_logstop(self,parameter_s=''):
1194 """Fully stop logging and close log file.
1194 """Fully stop logging and close log file.
1195
1195
1196 In order to start logging again, a new %logstart call needs to be made,
1196 In order to start logging again, a new %logstart call needs to be made,
1197 possibly (though not necessarily) with a new filename, mode and other
1197 possibly (though not necessarily) with a new filename, mode and other
1198 options."""
1198 options."""
1199 self.logger.logstop()
1199 self.logger.logstop()
1200
1200
1201 def magic_logoff(self,parameter_s=''):
1201 def magic_logoff(self,parameter_s=''):
1202 """Temporarily stop logging.
1202 """Temporarily stop logging.
1203
1203
1204 You must have previously started logging."""
1204 You must have previously started logging."""
1205 self.shell.logger.switch_log(0)
1205 self.shell.logger.switch_log(0)
1206
1206
1207 def magic_logon(self,parameter_s=''):
1207 def magic_logon(self,parameter_s=''):
1208 """Restart logging.
1208 """Restart logging.
1209
1209
1210 This function is for restarting logging which you've temporarily
1210 This function is for restarting logging which you've temporarily
1211 stopped with %logoff. For starting logging for the first time, you
1211 stopped with %logoff. For starting logging for the first time, you
1212 must use the %logstart function, which allows you to specify an
1212 must use the %logstart function, which allows you to specify an
1213 optional log filename."""
1213 optional log filename."""
1214
1214
1215 self.shell.logger.switch_log(1)
1215 self.shell.logger.switch_log(1)
1216
1216
1217 def magic_logstate(self,parameter_s=''):
1217 def magic_logstate(self,parameter_s=''):
1218 """Print the status of the logging system."""
1218 """Print the status of the logging system."""
1219
1219
1220 self.shell.logger.logstate()
1220 self.shell.logger.logstate()
1221
1221
1222 def magic_pdb(self, parameter_s=''):
1222 def magic_pdb(self, parameter_s=''):
1223 """Control the automatic calling of the pdb interactive debugger.
1223 """Control the automatic calling of the pdb interactive debugger.
1224
1224
1225 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
1225 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
1226 argument it works as a toggle.
1226 argument it works as a toggle.
1227
1227
1228 When an exception is triggered, IPython can optionally call the
1228 When an exception is triggered, IPython can optionally call the
1229 interactive pdb debugger after the traceback printout. %pdb toggles
1229 interactive pdb debugger after the traceback printout. %pdb toggles
1230 this feature on and off.
1230 this feature on and off.
1231
1231
1232 The initial state of this feature is set in your ipythonrc
1232 The initial state of this feature is set in your ipythonrc
1233 configuration file (the variable is called 'pdb').
1233 configuration file (the variable is called 'pdb').
1234
1234
1235 If you want to just activate the debugger AFTER an exception has fired,
1235 If you want to just activate the debugger AFTER an exception has fired,
1236 without having to type '%pdb on' and rerunning your code, you can use
1236 without having to type '%pdb on' and rerunning your code, you can use
1237 the %debug magic."""
1237 the %debug magic."""
1238
1238
1239 par = parameter_s.strip().lower()
1239 par = parameter_s.strip().lower()
1240
1240
1241 if par:
1241 if par:
1242 try:
1242 try:
1243 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
1243 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
1244 except KeyError:
1244 except KeyError:
1245 print ('Incorrect argument. Use on/1, off/0, '
1245 print ('Incorrect argument. Use on/1, off/0, '
1246 'or nothing for a toggle.')
1246 'or nothing for a toggle.')
1247 return
1247 return
1248 else:
1248 else:
1249 # toggle
1249 # toggle
1250 new_pdb = not self.shell.call_pdb
1250 new_pdb = not self.shell.call_pdb
1251
1251
1252 # set on the shell
1252 # set on the shell
1253 self.shell.call_pdb = new_pdb
1253 self.shell.call_pdb = new_pdb
1254 print 'Automatic pdb calling has been turned',on_off(new_pdb)
1254 print 'Automatic pdb calling has been turned',on_off(new_pdb)
1255
1255
1256 def magic_debug(self, parameter_s=''):
1256 def magic_debug(self, parameter_s=''):
1257 """Activate the interactive debugger in post-mortem mode.
1257 """Activate the interactive debugger in post-mortem mode.
1258
1258
1259 If an exception has just occurred, this lets you inspect its stack
1259 If an exception has just occurred, this lets you inspect its stack
1260 frames interactively. Note that this will always work only on the last
1260 frames interactively. Note that this will always work only on the last
1261 traceback that occurred, so you must call this quickly after an
1261 traceback that occurred, so you must call this quickly after an
1262 exception that you wish to inspect has fired, because if another one
1262 exception that you wish to inspect has fired, because if another one
1263 occurs, it clobbers the previous one.
1263 occurs, it clobbers the previous one.
1264
1264
1265 If you want IPython to automatically do this on every exception, see
1265 If you want IPython to automatically do this on every exception, see
1266 the %pdb magic for more details.
1266 the %pdb magic for more details.
1267 """
1267 """
1268
1268
1269 self.shell.debugger(force=True)
1269 self.shell.debugger(force=True)
1270
1270
1271 @testdec.skip_doctest
1271 @testdec.skip_doctest
1272 def magic_prun(self, parameter_s ='',user_mode=1,
1272 def magic_prun(self, parameter_s ='',user_mode=1,
1273 opts=None,arg_lst=None,prog_ns=None):
1273 opts=None,arg_lst=None,prog_ns=None):
1274
1274
1275 """Run a statement through the python code profiler.
1275 """Run a statement through the python code profiler.
1276
1276
1277 Usage:
1277 Usage:
1278 %prun [options] statement
1278 %prun [options] statement
1279
1279
1280 The given statement (which doesn't require quote marks) is run via the
1280 The given statement (which doesn't require quote marks) is run via the
1281 python profiler in a manner similar to the profile.run() function.
1281 python profiler in a manner similar to the profile.run() function.
1282 Namespaces are internally managed to work correctly; profile.run
1282 Namespaces are internally managed to work correctly; profile.run
1283 cannot be used in IPython because it makes certain assumptions about
1283 cannot be used in IPython because it makes certain assumptions about
1284 namespaces which do not hold under IPython.
1284 namespaces which do not hold under IPython.
1285
1285
1286 Options:
1286 Options:
1287
1287
1288 -l <limit>: you can place restrictions on what or how much of the
1288 -l <limit>: you can place restrictions on what or how much of the
1289 profile gets printed. The limit value can be:
1289 profile gets printed. The limit value can be:
1290
1290
1291 * A string: only information for function names containing this string
1291 * A string: only information for function names containing this string
1292 is printed.
1292 is printed.
1293
1293
1294 * An integer: only these many lines are printed.
1294 * An integer: only these many lines are printed.
1295
1295
1296 * A float (between 0 and 1): this fraction of the report is printed
1296 * A float (between 0 and 1): this fraction of the report is printed
1297 (for example, use a limit of 0.4 to see the topmost 40% only).
1297 (for example, use a limit of 0.4 to see the topmost 40% only).
1298
1298
1299 You can combine several limits with repeated use of the option. For
1299 You can combine several limits with repeated use of the option. For
1300 example, '-l __init__ -l 5' will print only the topmost 5 lines of
1300 example, '-l __init__ -l 5' will print only the topmost 5 lines of
1301 information about class constructors.
1301 information about class constructors.
1302
1302
1303 -r: return the pstats.Stats object generated by the profiling. This
1303 -r: return the pstats.Stats object generated by the profiling. This
1304 object has all the information about the profile in it, and you can
1304 object has all the information about the profile in it, and you can
1305 later use it for further analysis or in other functions.
1305 later use it for further analysis or in other functions.
1306
1306
1307 -s <key>: sort profile by given key. You can provide more than one key
1307 -s <key>: sort profile by given key. You can provide more than one key
1308 by using the option several times: '-s key1 -s key2 -s key3...'. The
1308 by using the option several times: '-s key1 -s key2 -s key3...'. The
1309 default sorting key is 'time'.
1309 default sorting key is 'time'.
1310
1310
1311 The following is copied verbatim from the profile documentation
1311 The following is copied verbatim from the profile documentation
1312 referenced below:
1312 referenced below:
1313
1313
1314 When more than one key is provided, additional keys are used as
1314 When more than one key is provided, additional keys are used as
1315 secondary criteria when the there is equality in all keys selected
1315 secondary criteria when the there is equality in all keys selected
1316 before them.
1316 before them.
1317
1317
1318 Abbreviations can be used for any key names, as long as the
1318 Abbreviations can be used for any key names, as long as the
1319 abbreviation is unambiguous. The following are the keys currently
1319 abbreviation is unambiguous. The following are the keys currently
1320 defined:
1320 defined:
1321
1321
1322 Valid Arg Meaning
1322 Valid Arg Meaning
1323 "calls" call count
1323 "calls" call count
1324 "cumulative" cumulative time
1324 "cumulative" cumulative time
1325 "file" file name
1325 "file" file name
1326 "module" file name
1326 "module" file name
1327 "pcalls" primitive call count
1327 "pcalls" primitive call count
1328 "line" line number
1328 "line" line number
1329 "name" function name
1329 "name" function name
1330 "nfl" name/file/line
1330 "nfl" name/file/line
1331 "stdname" standard name
1331 "stdname" standard name
1332 "time" internal time
1332 "time" internal time
1333
1333
1334 Note that all sorts on statistics are in descending order (placing
1334 Note that all sorts on statistics are in descending order (placing
1335 most time consuming items first), where as name, file, and line number
1335 most time consuming items first), where as name, file, and line number
1336 searches are in ascending order (i.e., alphabetical). The subtle
1336 searches are in ascending order (i.e., alphabetical). The subtle
1337 distinction between "nfl" and "stdname" is that the standard name is a
1337 distinction between "nfl" and "stdname" is that the standard name is a
1338 sort of the name as printed, which means that the embedded line
1338 sort of the name as printed, which means that the embedded line
1339 numbers get compared in an odd way. For example, lines 3, 20, and 40
1339 numbers get compared in an odd way. For example, lines 3, 20, and 40
1340 would (if the file names were the same) appear in the string order
1340 would (if the file names were the same) appear in the string order
1341 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
1341 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
1342 line numbers. In fact, sort_stats("nfl") is the same as
1342 line numbers. In fact, sort_stats("nfl") is the same as
1343 sort_stats("name", "file", "line").
1343 sort_stats("name", "file", "line").
1344
1344
1345 -T <filename>: save profile results as shown on screen to a text
1345 -T <filename>: save profile results as shown on screen to a text
1346 file. The profile is still shown on screen.
1346 file. The profile is still shown on screen.
1347
1347
1348 -D <filename>: save (via dump_stats) profile statistics to given
1348 -D <filename>: save (via dump_stats) profile statistics to given
1349 filename. This data is in a format understod by the pstats module, and
1349 filename. This data is in a format understod by the pstats module, and
1350 is generated by a call to the dump_stats() method of profile
1350 is generated by a call to the dump_stats() method of profile
1351 objects. The profile is still shown on screen.
1351 objects. The profile is still shown on screen.
1352
1352
1353 If you want to run complete programs under the profiler's control, use
1353 If you want to run complete programs under the profiler's control, use
1354 '%run -p [prof_opts] filename.py [args to program]' where prof_opts
1354 '%run -p [prof_opts] filename.py [args to program]' where prof_opts
1355 contains profiler specific options as described here.
1355 contains profiler specific options as described here.
1356
1356
1357 You can read the complete documentation for the profile module with::
1357 You can read the complete documentation for the profile module with::
1358
1358
1359 In [1]: import profile; profile.help()
1359 In [1]: import profile; profile.help()
1360 """
1360 """
1361
1361
1362 opts_def = Struct(D=[''],l=[],s=['time'],T=[''])
1362 opts_def = Struct(D=[''],l=[],s=['time'],T=[''])
1363 # protect user quote marks
1363 # protect user quote marks
1364 parameter_s = parameter_s.replace('"',r'\"').replace("'",r"\'")
1364 parameter_s = parameter_s.replace('"',r'\"').replace("'",r"\'")
1365
1365
1366 if user_mode: # regular user call
1366 if user_mode: # regular user call
1367 opts,arg_str = self.parse_options(parameter_s,'D:l:rs:T:',
1367 opts,arg_str = self.parse_options(parameter_s,'D:l:rs:T:',
1368 list_all=1)
1368 list_all=1)
1369 namespace = self.shell.user_ns
1369 namespace = self.shell.user_ns
1370 else: # called to run a program by %run -p
1370 else: # called to run a program by %run -p
1371 try:
1371 try:
1372 filename = get_py_filename(arg_lst[0])
1372 filename = get_py_filename(arg_lst[0])
1373 except IOError,msg:
1373 except IOError,msg:
1374 error(msg)
1374 error(msg)
1375 return
1375 return
1376
1376
1377 arg_str = 'execfile(filename,prog_ns)'
1377 arg_str = 'execfile(filename,prog_ns)'
1378 namespace = locals()
1378 namespace = locals()
1379
1379
1380 opts.merge(opts_def)
1380 opts.merge(opts_def)
1381
1381
1382 prof = profile.Profile()
1382 prof = profile.Profile()
1383 try:
1383 try:
1384 prof = prof.runctx(arg_str,namespace,namespace)
1384 prof = prof.runctx(arg_str,namespace,namespace)
1385 sys_exit = ''
1385 sys_exit = ''
1386 except SystemExit:
1386 except SystemExit:
1387 sys_exit = """*** SystemExit exception caught in code being profiled."""
1387 sys_exit = """*** SystemExit exception caught in code being profiled."""
1388
1388
1389 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
1389 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
1390
1390
1391 lims = opts.l
1391 lims = opts.l
1392 if lims:
1392 if lims:
1393 lims = [] # rebuild lims with ints/floats/strings
1393 lims = [] # rebuild lims with ints/floats/strings
1394 for lim in opts.l:
1394 for lim in opts.l:
1395 try:
1395 try:
1396 lims.append(int(lim))
1396 lims.append(int(lim))
1397 except ValueError:
1397 except ValueError:
1398 try:
1398 try:
1399 lims.append(float(lim))
1399 lims.append(float(lim))
1400 except ValueError:
1400 except ValueError:
1401 lims.append(lim)
1401 lims.append(lim)
1402
1402
1403 # Trap output.
1403 # Trap output.
1404 stdout_trap = StringIO()
1404 stdout_trap = StringIO()
1405
1405
1406 if hasattr(stats,'stream'):
1406 if hasattr(stats,'stream'):
1407 # In newer versions of python, the stats object has a 'stream'
1407 # In newer versions of python, the stats object has a 'stream'
1408 # attribute to write into.
1408 # attribute to write into.
1409 stats.stream = stdout_trap
1409 stats.stream = stdout_trap
1410 stats.print_stats(*lims)
1410 stats.print_stats(*lims)
1411 else:
1411 else:
1412 # For older versions, we manually redirect stdout during printing
1412 # For older versions, we manually redirect stdout during printing
1413 sys_stdout = sys.stdout
1413 sys_stdout = sys.stdout
1414 try:
1414 try:
1415 sys.stdout = stdout_trap
1415 sys.stdout = stdout_trap
1416 stats.print_stats(*lims)
1416 stats.print_stats(*lims)
1417 finally:
1417 finally:
1418 sys.stdout = sys_stdout
1418 sys.stdout = sys_stdout
1419
1419
1420 output = stdout_trap.getvalue()
1420 output = stdout_trap.getvalue()
1421 output = output.rstrip()
1421 output = output.rstrip()
1422
1422
1423 page(output,screen_lines=self.shell.rc.screen_length)
1423 page(output,screen_lines=self.shell.rc.screen_length)
1424 print sys_exit,
1424 print sys_exit,
1425
1425
1426 dump_file = opts.D[0]
1426 dump_file = opts.D[0]
1427 text_file = opts.T[0]
1427 text_file = opts.T[0]
1428 if dump_file:
1428 if dump_file:
1429 prof.dump_stats(dump_file)
1429 prof.dump_stats(dump_file)
1430 print '\n*** Profile stats marshalled to file',\
1430 print '\n*** Profile stats marshalled to file',\
1431 `dump_file`+'.',sys_exit
1431 `dump_file`+'.',sys_exit
1432 if text_file:
1432 if text_file:
1433 pfile = file(text_file,'w')
1433 pfile = file(text_file,'w')
1434 pfile.write(output)
1434 pfile.write(output)
1435 pfile.close()
1435 pfile.close()
1436 print '\n*** Profile printout saved to text file',\
1436 print '\n*** Profile printout saved to text file',\
1437 `text_file`+'.',sys_exit
1437 `text_file`+'.',sys_exit
1438
1438
1439 if opts.has_key('r'):
1439 if opts.has_key('r'):
1440 return stats
1440 return stats
1441 else:
1441 else:
1442 return None
1442 return None
1443
1443
1444 @testdec.skip_doctest
1444 @testdec.skip_doctest
1445 def magic_run(self, parameter_s ='',runner=None,
1445 def magic_run(self, parameter_s ='',runner=None,
1446 file_finder=get_py_filename):
1446 file_finder=get_py_filename):
1447 """Run the named file inside IPython as a program.
1447 """Run the named file inside IPython as a program.
1448
1448
1449 Usage:\\
1449 Usage:\\
1450 %run [-n -i -t [-N<N>] -d [-b<N>] -p [profile options]] file [args]
1450 %run [-n -i -t [-N<N>] -d [-b<N>] -p [profile options]] file [args]
1451
1451
1452 Parameters after the filename are passed as command-line arguments to
1452 Parameters after the filename are passed as command-line arguments to
1453 the program (put in sys.argv). Then, control returns to IPython's
1453 the program (put in sys.argv). Then, control returns to IPython's
1454 prompt.
1454 prompt.
1455
1455
1456 This is similar to running at a system prompt:\\
1456 This is similar to running at a system prompt:\\
1457 $ python file args\\
1457 $ python file args\\
1458 but with the advantage of giving you IPython's tracebacks, and of
1458 but with the advantage of giving you IPython's tracebacks, and of
1459 loading all variables into your interactive namespace for further use
1459 loading all variables into your interactive namespace for further use
1460 (unless -p is used, see below).
1460 (unless -p is used, see below).
1461
1461
1462 The file is executed in a namespace initially consisting only of
1462 The file is executed in a namespace initially consisting only of
1463 __name__=='__main__' and sys.argv constructed as indicated. It thus
1463 __name__=='__main__' and sys.argv constructed as indicated. It thus
1464 sees its environment as if it were being run as a stand-alone program
1464 sees its environment as if it were being run as a stand-alone program
1465 (except for sharing global objects such as previously imported
1465 (except for sharing global objects such as previously imported
1466 modules). But after execution, the IPython interactive namespace gets
1466 modules). But after execution, the IPython interactive namespace gets
1467 updated with all variables defined in the program (except for __name__
1467 updated with all variables defined in the program (except for __name__
1468 and sys.argv). This allows for very convenient loading of code for
1468 and sys.argv). This allows for very convenient loading of code for
1469 interactive work, while giving each program a 'clean sheet' to run in.
1469 interactive work, while giving each program a 'clean sheet' to run in.
1470
1470
1471 Options:
1471 Options:
1472
1472
1473 -n: __name__ is NOT set to '__main__', but to the running file's name
1473 -n: __name__ is NOT set to '__main__', but to the running file's name
1474 without extension (as python does under import). This allows running
1474 without extension (as python does under import). This allows running
1475 scripts and reloading the definitions in them without calling code
1475 scripts and reloading the definitions in them without calling code
1476 protected by an ' if __name__ == "__main__" ' clause.
1476 protected by an ' if __name__ == "__main__" ' clause.
1477
1477
1478 -i: run the file in IPython's namespace instead of an empty one. This
1478 -i: run the file in IPython's namespace instead of an empty one. This
1479 is useful if you are experimenting with code written in a text editor
1479 is useful if you are experimenting with code written in a text editor
1480 which depends on variables defined interactively.
1480 which depends on variables defined interactively.
1481
1481
1482 -e: ignore sys.exit() calls or SystemExit exceptions in the script
1482 -e: ignore sys.exit() calls or SystemExit exceptions in the script
1483 being run. This is particularly useful if IPython is being used to
1483 being run. This is particularly useful if IPython is being used to
1484 run unittests, which always exit with a sys.exit() call. In such
1484 run unittests, which always exit with a sys.exit() call. In such
1485 cases you are interested in the output of the test results, not in
1485 cases you are interested in the output of the test results, not in
1486 seeing a traceback of the unittest module.
1486 seeing a traceback of the unittest module.
1487
1487
1488 -t: print timing information at the end of the run. IPython will give
1488 -t: print timing information at the end of the run. IPython will give
1489 you an estimated CPU time consumption for your script, which under
1489 you an estimated CPU time consumption for your script, which under
1490 Unix uses the resource module to avoid the wraparound problems of
1490 Unix uses the resource module to avoid the wraparound problems of
1491 time.clock(). Under Unix, an estimate of time spent on system tasks
1491 time.clock(). Under Unix, an estimate of time spent on system tasks
1492 is also given (for Windows platforms this is reported as 0.0).
1492 is also given (for Windows platforms this is reported as 0.0).
1493
1493
1494 If -t is given, an additional -N<N> option can be given, where <N>
1494 If -t is given, an additional -N<N> option can be given, where <N>
1495 must be an integer indicating how many times you want the script to
1495 must be an integer indicating how many times you want the script to
1496 run. The final timing report will include total and per run results.
1496 run. The final timing report will include total and per run results.
1497
1497
1498 For example (testing the script uniq_stable.py):
1498 For example (testing the script uniq_stable.py):
1499
1499
1500 In [1]: run -t uniq_stable
1500 In [1]: run -t uniq_stable
1501
1501
1502 IPython CPU timings (estimated):\\
1502 IPython CPU timings (estimated):\\
1503 User : 0.19597 s.\\
1503 User : 0.19597 s.\\
1504 System: 0.0 s.\\
1504 System: 0.0 s.\\
1505
1505
1506 In [2]: run -t -N5 uniq_stable
1506 In [2]: run -t -N5 uniq_stable
1507
1507
1508 IPython CPU timings (estimated):\\
1508 IPython CPU timings (estimated):\\
1509 Total runs performed: 5\\
1509 Total runs performed: 5\\
1510 Times : Total Per run\\
1510 Times : Total Per run\\
1511 User : 0.910862 s, 0.1821724 s.\\
1511 User : 0.910862 s, 0.1821724 s.\\
1512 System: 0.0 s, 0.0 s.
1512 System: 0.0 s, 0.0 s.
1513
1513
1514 -d: run your program under the control of pdb, the Python debugger.
1514 -d: run your program under the control of pdb, the Python debugger.
1515 This allows you to execute your program step by step, watch variables,
1515 This allows you to execute your program step by step, watch variables,
1516 etc. Internally, what IPython does is similar to calling:
1516 etc. Internally, what IPython does is similar to calling:
1517
1517
1518 pdb.run('execfile("YOURFILENAME")')
1518 pdb.run('execfile("YOURFILENAME")')
1519
1519
1520 with a breakpoint set on line 1 of your file. You can change the line
1520 with a breakpoint set on line 1 of your file. You can change the line
1521 number for this automatic breakpoint to be <N> by using the -bN option
1521 number for this automatic breakpoint to be <N> by using the -bN option
1522 (where N must be an integer). For example:
1522 (where N must be an integer). For example:
1523
1523
1524 %run -d -b40 myscript
1524 %run -d -b40 myscript
1525
1525
1526 will set the first breakpoint at line 40 in myscript.py. Note that
1526 will set the first breakpoint at line 40 in myscript.py. Note that
1527 the first breakpoint must be set on a line which actually does
1527 the first breakpoint must be set on a line which actually does
1528 something (not a comment or docstring) for it to stop execution.
1528 something (not a comment or docstring) for it to stop execution.
1529
1529
1530 When the pdb debugger starts, you will see a (Pdb) prompt. You must
1530 When the pdb debugger starts, you will see a (Pdb) prompt. You must
1531 first enter 'c' (without qoutes) to start execution up to the first
1531 first enter 'c' (without qoutes) to start execution up to the first
1532 breakpoint.
1532 breakpoint.
1533
1533
1534 Entering 'help' gives information about the use of the debugger. You
1534 Entering 'help' gives information about the use of the debugger. You
1535 can easily see pdb's full documentation with "import pdb;pdb.help()"
1535 can easily see pdb's full documentation with "import pdb;pdb.help()"
1536 at a prompt.
1536 at a prompt.
1537
1537
1538 -p: run program under the control of the Python profiler module (which
1538 -p: run program under the control of the Python profiler module (which
1539 prints a detailed report of execution times, function calls, etc).
1539 prints a detailed report of execution times, function calls, etc).
1540
1540
1541 You can pass other options after -p which affect the behavior of the
1541 You can pass other options after -p which affect the behavior of the
1542 profiler itself. See the docs for %prun for details.
1542 profiler itself. See the docs for %prun for details.
1543
1543
1544 In this mode, the program's variables do NOT propagate back to the
1544 In this mode, the program's variables do NOT propagate back to the
1545 IPython interactive namespace (because they remain in the namespace
1545 IPython interactive namespace (because they remain in the namespace
1546 where the profiler executes them).
1546 where the profiler executes them).
1547
1547
1548 Internally this triggers a call to %prun, see its documentation for
1548 Internally this triggers a call to %prun, see its documentation for
1549 details on the options available specifically for profiling.
1549 details on the options available specifically for profiling.
1550
1550
1551 There is one special usage for which the text above doesn't apply:
1551 There is one special usage for which the text above doesn't apply:
1552 if the filename ends with .ipy, the file is run as ipython script,
1552 if the filename ends with .ipy, the file is run as ipython script,
1553 just as if the commands were written on IPython prompt.
1553 just as if the commands were written on IPython prompt.
1554 """
1554 """
1555
1555
1556 # get arguments and set sys.argv for program to be run.
1556 # get arguments and set sys.argv for program to be run.
1557 opts,arg_lst = self.parse_options(parameter_s,'nidtN:b:pD:l:rs:T:e',
1557 opts,arg_lst = self.parse_options(parameter_s,'nidtN:b:pD:l:rs:T:e',
1558 mode='list',list_all=1)
1558 mode='list',list_all=1)
1559
1559
1560 try:
1560 try:
1561 filename = file_finder(arg_lst[0])
1561 filename = file_finder(arg_lst[0])
1562 except IndexError:
1562 except IndexError:
1563 warn('you must provide at least a filename.')
1563 warn('you must provide at least a filename.')
1564 print '\n%run:\n',OInspect.getdoc(self.magic_run)
1564 print '\n%run:\n',OInspect.getdoc(self.magic_run)
1565 return
1565 return
1566 except IOError,msg:
1566 except IOError,msg:
1567 error(msg)
1567 error(msg)
1568 return
1568 return
1569
1569
1570 if filename.lower().endswith('.ipy'):
1570 if filename.lower().endswith('.ipy'):
1571 self.api.runlines(open(filename).read())
1571 self.api.runlines(open(filename).read())
1572 return
1572 return
1573
1573
1574 # Control the response to exit() calls made by the script being run
1574 # Control the response to exit() calls made by the script being run
1575 exit_ignore = opts.has_key('e')
1575 exit_ignore = opts.has_key('e')
1576
1576
1577 # Make sure that the running script gets a proper sys.argv as if it
1577 # Make sure that the running script gets a proper sys.argv as if it
1578 # were run from a system shell.
1578 # were run from a system shell.
1579 save_argv = sys.argv # save it for later restoring
1579 save_argv = sys.argv # save it for later restoring
1580 sys.argv = [filename]+ arg_lst[1:] # put in the proper filename
1580 sys.argv = [filename]+ arg_lst[1:] # put in the proper filename
1581
1581
1582 if opts.has_key('i'):
1582 if opts.has_key('i'):
1583 # Run in user's interactive namespace
1583 # Run in user's interactive namespace
1584 prog_ns = self.shell.user_ns
1584 prog_ns = self.shell.user_ns
1585 __name__save = self.shell.user_ns['__name__']
1585 __name__save = self.shell.user_ns['__name__']
1586 prog_ns['__name__'] = '__main__'
1586 prog_ns['__name__'] = '__main__'
1587 main_mod = FakeModule(prog_ns)
1587 main_mod = self.shell.new_main_mod(prog_ns)
1588 else:
1588 else:
1589 # Run in a fresh, empty namespace
1589 # Run in a fresh, empty namespace
1590 if opts.has_key('n'):
1590 if opts.has_key('n'):
1591 name = os.path.splitext(os.path.basename(filename))[0]
1591 name = os.path.splitext(os.path.basename(filename))[0]
1592 else:
1592 else:
1593 name = '__main__'
1593 name = '__main__'
1594 main_mod = FakeModule()
1594
1595 main_mod = self.shell.new_main_mod()
1595 prog_ns = main_mod.__dict__
1596 prog_ns = main_mod.__dict__
1596 prog_ns['__name__'] = name
1597 prog_ns['__name__'] = name
1597
1598 # The shell MUST hold a reference to main_mod so after %run exits,
1599 # the python deletion mechanism doesn't zero it out (leaving
1600 # dangling references). However, we should drop old versions of
1601 # main_mod. There is now a proper API to manage this caching in
1602 # the main shell object, we use that.
1603 self.shell.cache_main_mod(main_mod)
1604
1598
1605 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
1599 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
1606 # set the __file__ global in the script's namespace
1600 # set the __file__ global in the script's namespace
1607 prog_ns['__file__'] = filename
1601 prog_ns['__file__'] = filename
1608
1602
1609 # pickle fix. See iplib for an explanation. But we need to make sure
1603 # pickle fix. See iplib for an explanation. But we need to make sure
1610 # that, if we overwrite __main__, we replace it at the end
1604 # that, if we overwrite __main__, we replace it at the end
1611 main_mod_name = prog_ns['__name__']
1605 main_mod_name = prog_ns['__name__']
1612
1606
1613 if main_mod_name == '__main__':
1607 if main_mod_name == '__main__':
1614 restore_main = sys.modules['__main__']
1608 restore_main = sys.modules['__main__']
1615 else:
1609 else:
1616 restore_main = False
1610 restore_main = False
1617
1611
1618 # This needs to be undone at the end to prevent holding references to
1612 # This needs to be undone at the end to prevent holding references to
1619 # every single object ever created.
1613 # every single object ever created.
1620 sys.modules[main_mod_name] = main_mod
1614 sys.modules[main_mod_name] = main_mod
1621
1615
1622 stats = None
1616 stats = None
1623 try:
1617 try:
1624 self.shell.savehist()
1618 self.shell.savehist()
1625
1619
1626 if opts.has_key('p'):
1620 if opts.has_key('p'):
1627 stats = self.magic_prun('',0,opts,arg_lst,prog_ns)
1621 stats = self.magic_prun('',0,opts,arg_lst,prog_ns)
1628 else:
1622 else:
1629 if opts.has_key('d'):
1623 if opts.has_key('d'):
1630 deb = Debugger.Pdb(self.shell.rc.colors)
1624 deb = Debugger.Pdb(self.shell.rc.colors)
1631 # reset Breakpoint state, which is moronically kept
1625 # reset Breakpoint state, which is moronically kept
1632 # in a class
1626 # in a class
1633 bdb.Breakpoint.next = 1
1627 bdb.Breakpoint.next = 1
1634 bdb.Breakpoint.bplist = {}
1628 bdb.Breakpoint.bplist = {}
1635 bdb.Breakpoint.bpbynumber = [None]
1629 bdb.Breakpoint.bpbynumber = [None]
1636 # Set an initial breakpoint to stop execution
1630 # Set an initial breakpoint to stop execution
1637 maxtries = 10
1631 maxtries = 10
1638 bp = int(opts.get('b',[1])[0])
1632 bp = int(opts.get('b',[1])[0])
1639 checkline = deb.checkline(filename,bp)
1633 checkline = deb.checkline(filename,bp)
1640 if not checkline:
1634 if not checkline:
1641 for bp in range(bp+1,bp+maxtries+1):
1635 for bp in range(bp+1,bp+maxtries+1):
1642 if deb.checkline(filename,bp):
1636 if deb.checkline(filename,bp):
1643 break
1637 break
1644 else:
1638 else:
1645 msg = ("\nI failed to find a valid line to set "
1639 msg = ("\nI failed to find a valid line to set "
1646 "a breakpoint\n"
1640 "a breakpoint\n"
1647 "after trying up to line: %s.\n"
1641 "after trying up to line: %s.\n"
1648 "Please set a valid breakpoint manually "
1642 "Please set a valid breakpoint manually "
1649 "with the -b option." % bp)
1643 "with the -b option." % bp)
1650 error(msg)
1644 error(msg)
1651 return
1645 return
1652 # if we find a good linenumber, set the breakpoint
1646 # if we find a good linenumber, set the breakpoint
1653 deb.do_break('%s:%s' % (filename,bp))
1647 deb.do_break('%s:%s' % (filename,bp))
1654 # Start file run
1648 # Start file run
1655 print "NOTE: Enter 'c' at the",
1649 print "NOTE: Enter 'c' at the",
1656 print "%s prompt to start your script." % deb.prompt
1650 print "%s prompt to start your script." % deb.prompt
1657 try:
1651 try:
1658 deb.run('execfile("%s")' % filename,prog_ns)
1652 deb.run('execfile("%s")' % filename,prog_ns)
1659
1653
1660 except:
1654 except:
1661 etype, value, tb = sys.exc_info()
1655 etype, value, tb = sys.exc_info()
1662 # Skip three frames in the traceback: the %run one,
1656 # Skip three frames in the traceback: the %run one,
1663 # one inside bdb.py, and the command-line typed by the
1657 # one inside bdb.py, and the command-line typed by the
1664 # user (run by exec in pdb itself).
1658 # user (run by exec in pdb itself).
1665 self.shell.InteractiveTB(etype,value,tb,tb_offset=3)
1659 self.shell.InteractiveTB(etype,value,tb,tb_offset=3)
1666 else:
1660 else:
1667 if runner is None:
1661 if runner is None:
1668 runner = self.shell.safe_execfile
1662 runner = self.shell.safe_execfile
1669 if opts.has_key('t'):
1663 if opts.has_key('t'):
1670 # timed execution
1664 # timed execution
1671 try:
1665 try:
1672 nruns = int(opts['N'][0])
1666 nruns = int(opts['N'][0])
1673 if nruns < 1:
1667 if nruns < 1:
1674 error('Number of runs must be >=1')
1668 error('Number of runs must be >=1')
1675 return
1669 return
1676 except (KeyError):
1670 except (KeyError):
1677 nruns = 1
1671 nruns = 1
1678 if nruns == 1:
1672 if nruns == 1:
1679 t0 = clock2()
1673 t0 = clock2()
1680 runner(filename,prog_ns,prog_ns,
1674 runner(filename,prog_ns,prog_ns,
1681 exit_ignore=exit_ignore)
1675 exit_ignore=exit_ignore)
1682 t1 = clock2()
1676 t1 = clock2()
1683 t_usr = t1[0]-t0[0]
1677 t_usr = t1[0]-t0[0]
1684 t_sys = t1[1]-t1[1]
1678 t_sys = t1[1]-t0[1]
1685 print "\nIPython CPU timings (estimated):"
1679 print "\nIPython CPU timings (estimated):"
1686 print " User : %10s s." % t_usr
1680 print " User : %10s s." % t_usr
1687 print " System: %10s s." % t_sys
1681 print " System: %10s s." % t_sys
1688 else:
1682 else:
1689 runs = range(nruns)
1683 runs = range(nruns)
1690 t0 = clock2()
1684 t0 = clock2()
1691 for nr in runs:
1685 for nr in runs:
1692 runner(filename,prog_ns,prog_ns,
1686 runner(filename,prog_ns,prog_ns,
1693 exit_ignore=exit_ignore)
1687 exit_ignore=exit_ignore)
1694 t1 = clock2()
1688 t1 = clock2()
1695 t_usr = t1[0]-t0[0]
1689 t_usr = t1[0]-t0[0]
1696 t_sys = t1[1]-t1[1]
1690 t_sys = t1[1]-t0[1]
1697 print "\nIPython CPU timings (estimated):"
1691 print "\nIPython CPU timings (estimated):"
1698 print "Total runs performed:",nruns
1692 print "Total runs performed:",nruns
1699 print " Times : %10s %10s" % ('Total','Per run')
1693 print " Times : %10s %10s" % ('Total','Per run')
1700 print " User : %10s s, %10s s." % (t_usr,t_usr/nruns)
1694 print " User : %10s s, %10s s." % (t_usr,t_usr/nruns)
1701 print " System: %10s s, %10s s." % (t_sys,t_sys/nruns)
1695 print " System: %10s s, %10s s." % (t_sys,t_sys/nruns)
1702
1696
1703 else:
1697 else:
1704 # regular execution
1698 # regular execution
1705 runner(filename,prog_ns,prog_ns,exit_ignore=exit_ignore)
1699 runner(filename,prog_ns,prog_ns,exit_ignore=exit_ignore)
1700
1706 if opts.has_key('i'):
1701 if opts.has_key('i'):
1707 self.shell.user_ns['__name__'] = __name__save
1702 self.shell.user_ns['__name__'] = __name__save
1708 else:
1703 else:
1704 # The shell MUST hold a reference to prog_ns so after %run
1705 # exits, the python deletion mechanism doesn't zero it out
1706 # (leaving dangling references).
1707 self.shell.cache_main_mod(prog_ns,filename)
1709 # update IPython interactive namespace
1708 # update IPython interactive namespace
1710 del prog_ns['__name__']
1709 del prog_ns['__name__']
1711 self.shell.user_ns.update(prog_ns)
1710 self.shell.user_ns.update(prog_ns)
1712 finally:
1711 finally:
1712 # It's a bit of a mystery why, but __builtins__ can change from
1713 # being a module to becoming a dict missing some key data after
1714 # %run. As best I can see, this is NOT something IPython is doing
1715 # at all, and similar problems have been reported before:
1716 # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
1717 # Since this seems to be done by the interpreter itself, the best
1718 # we can do is to at least restore __builtins__ for the user on
1719 # exit.
1720 self.shell.user_ns['__builtins__'] = __builtin__
1721
1713 # Ensure key global structures are restored
1722 # Ensure key global structures are restored
1714 sys.argv = save_argv
1723 sys.argv = save_argv
1715 if restore_main:
1724 if restore_main:
1716 sys.modules['__main__'] = restore_main
1725 sys.modules['__main__'] = restore_main
1717 else:
1726 else:
1718 # Remove from sys.modules the reference to main_mod we'd
1727 # Remove from sys.modules the reference to main_mod we'd
1719 # added. Otherwise it will trap references to objects
1728 # added. Otherwise it will trap references to objects
1720 # contained therein.
1729 # contained therein.
1721 del sys.modules[main_mod_name]
1730 del sys.modules[main_mod_name]
1731
1722 self.shell.reloadhist()
1732 self.shell.reloadhist()
1723
1733
1724 return stats
1734 return stats
1725
1735
1726 def magic_runlog(self, parameter_s =''):
1736 def magic_runlog(self, parameter_s =''):
1727 """Run files as logs.
1737 """Run files as logs.
1728
1738
1729 Usage:\\
1739 Usage:\\
1730 %runlog file1 file2 ...
1740 %runlog file1 file2 ...
1731
1741
1732 Run the named files (treating them as log files) in sequence inside
1742 Run the named files (treating them as log files) in sequence inside
1733 the interpreter, and return to the prompt. This is much slower than
1743 the interpreter, and return to the prompt. This is much slower than
1734 %run because each line is executed in a try/except block, but it
1744 %run because each line is executed in a try/except block, but it
1735 allows running files with syntax errors in them.
1745 allows running files with syntax errors in them.
1736
1746
1737 Normally IPython will guess when a file is one of its own logfiles, so
1747 Normally IPython will guess when a file is one of its own logfiles, so
1738 you can typically use %run even for logs. This shorthand allows you to
1748 you can typically use %run even for logs. This shorthand allows you to
1739 force any file to be treated as a log file."""
1749 force any file to be treated as a log file."""
1740
1750
1741 for f in parameter_s.split():
1751 for f in parameter_s.split():
1742 self.shell.safe_execfile(f,self.shell.user_ns,
1752 self.shell.safe_execfile(f,self.shell.user_ns,
1743 self.shell.user_ns,islog=1)
1753 self.shell.user_ns,islog=1)
1744
1754
1745 @testdec.skip_doctest
1755 @testdec.skip_doctest
1746 def magic_timeit(self, parameter_s =''):
1756 def magic_timeit(self, parameter_s =''):
1747 """Time execution of a Python statement or expression
1757 """Time execution of a Python statement or expression
1748
1758
1749 Usage:\\
1759 Usage:\\
1750 %timeit [-n<N> -r<R> [-t|-c]] statement
1760 %timeit [-n<N> -r<R> [-t|-c]] statement
1751
1761
1752 Time execution of a Python statement or expression using the timeit
1762 Time execution of a Python statement or expression using the timeit
1753 module.
1763 module.
1754
1764
1755 Options:
1765 Options:
1756 -n<N>: execute the given statement <N> times in a loop. If this value
1766 -n<N>: execute the given statement <N> times in a loop. If this value
1757 is not given, a fitting value is chosen.
1767 is not given, a fitting value is chosen.
1758
1768
1759 -r<R>: repeat the loop iteration <R> times and take the best result.
1769 -r<R>: repeat the loop iteration <R> times and take the best result.
1760 Default: 3
1770 Default: 3
1761
1771
1762 -t: use time.time to measure the time, which is the default on Unix.
1772 -t: use time.time to measure the time, which is the default on Unix.
1763 This function measures wall time.
1773 This function measures wall time.
1764
1774
1765 -c: use time.clock to measure the time, which is the default on
1775 -c: use time.clock to measure the time, which is the default on
1766 Windows and measures wall time. On Unix, resource.getrusage is used
1776 Windows and measures wall time. On Unix, resource.getrusage is used
1767 instead and returns the CPU user time.
1777 instead and returns the CPU user time.
1768
1778
1769 -p<P>: use a precision of <P> digits to display the timing result.
1779 -p<P>: use a precision of <P> digits to display the timing result.
1770 Default: 3
1780 Default: 3
1771
1781
1772
1782
1773 Examples:
1783 Examples:
1774
1784
1775 In [1]: %timeit pass
1785 In [1]: %timeit pass
1776 10000000 loops, best of 3: 53.3 ns per loop
1786 10000000 loops, best of 3: 53.3 ns per loop
1777
1787
1778 In [2]: u = None
1788 In [2]: u = None
1779
1789
1780 In [3]: %timeit u is None
1790 In [3]: %timeit u is None
1781 10000000 loops, best of 3: 184 ns per loop
1791 10000000 loops, best of 3: 184 ns per loop
1782
1792
1783 In [4]: %timeit -r 4 u == None
1793 In [4]: %timeit -r 4 u == None
1784 1000000 loops, best of 4: 242 ns per loop
1794 1000000 loops, best of 4: 242 ns per loop
1785
1795
1786 In [5]: import time
1796 In [5]: import time
1787
1797
1788 In [6]: %timeit -n1 time.sleep(2)
1798 In [6]: %timeit -n1 time.sleep(2)
1789 1 loops, best of 3: 2 s per loop
1799 1 loops, best of 3: 2 s per loop
1790
1800
1791
1801
1792 The times reported by %timeit will be slightly higher than those
1802 The times reported by %timeit will be slightly higher than those
1793 reported by the timeit.py script when variables are accessed. This is
1803 reported by the timeit.py script when variables are accessed. This is
1794 due to the fact that %timeit executes the statement in the namespace
1804 due to the fact that %timeit executes the statement in the namespace
1795 of the shell, compared with timeit.py, which uses a single setup
1805 of the shell, compared with timeit.py, which uses a single setup
1796 statement to import function or create variables. Generally, the bias
1806 statement to import function or create variables. Generally, the bias
1797 does not matter as long as results from timeit.py are not mixed with
1807 does not matter as long as results from timeit.py are not mixed with
1798 those from %timeit."""
1808 those from %timeit."""
1799
1809
1800 import timeit
1810 import timeit
1801 import math
1811 import math
1802
1812
1803 units = [u"s", u"ms", u"\xb5s", u"ns"]
1813 # XXX: Unfortunately the unicode 'micro' symbol can cause problems in
1814 # certain terminals. Until we figure out a robust way of
1815 # auto-detecting if the terminal can deal with it, use plain 'us' for
1816 # microseconds. I am really NOT happy about disabling the proper
1817 # 'micro' prefix, but crashing is worse... If anyone knows what the
1818 # right solution for this is, I'm all ears...
1819 #
1820 # Note: using
1821 #
1822 # s = u'\xb5'
1823 # s.encode(sys.getdefaultencoding())
1824 #
1825 # is not sufficient, as I've seen terminals where that fails but
1826 # print s
1827 #
1828 # succeeds
1829 #
1830 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
1831
1832 #units = [u"s", u"ms",u'\xb5',"ns"]
1833 units = [u"s", u"ms",u'us',"ns"]
1834
1804 scaling = [1, 1e3, 1e6, 1e9]
1835 scaling = [1, 1e3, 1e6, 1e9]
1805
1836
1806 opts, stmt = self.parse_options(parameter_s,'n:r:tcp:',
1837 opts, stmt = self.parse_options(parameter_s,'n:r:tcp:',
1807 posix=False)
1838 posix=False)
1808 if stmt == "":
1839 if stmt == "":
1809 return
1840 return
1810 timefunc = timeit.default_timer
1841 timefunc = timeit.default_timer
1811 number = int(getattr(opts, "n", 0))
1842 number = int(getattr(opts, "n", 0))
1812 repeat = int(getattr(opts, "r", timeit.default_repeat))
1843 repeat = int(getattr(opts, "r", timeit.default_repeat))
1813 precision = int(getattr(opts, "p", 3))
1844 precision = int(getattr(opts, "p", 3))
1814 if hasattr(opts, "t"):
1845 if hasattr(opts, "t"):
1815 timefunc = time.time
1846 timefunc = time.time
1816 if hasattr(opts, "c"):
1847 if hasattr(opts, "c"):
1817 timefunc = clock
1848 timefunc = clock
1818
1849
1819 timer = timeit.Timer(timer=timefunc)
1850 timer = timeit.Timer(timer=timefunc)
1820 # this code has tight coupling to the inner workings of timeit.Timer,
1851 # this code has tight coupling to the inner workings of timeit.Timer,
1821 # but is there a better way to achieve that the code stmt has access
1852 # but is there a better way to achieve that the code stmt has access
1822 # to the shell namespace?
1853 # to the shell namespace?
1823
1854
1824 src = timeit.template % {'stmt': timeit.reindent(stmt, 8),
1855 src = timeit.template % {'stmt': timeit.reindent(stmt, 8),
1825 'setup': "pass"}
1856 'setup': "pass"}
1826 # Track compilation time so it can be reported if too long
1857 # Track compilation time so it can be reported if too long
1827 # Minimum time above which compilation time will be reported
1858 # Minimum time above which compilation time will be reported
1828 tc_min = 0.1
1859 tc_min = 0.1
1829
1860
1830 t0 = clock()
1861 t0 = clock()
1831 code = compile(src, "<magic-timeit>", "exec")
1862 code = compile(src, "<magic-timeit>", "exec")
1832 tc = clock()-t0
1863 tc = clock()-t0
1833
1864
1834 ns = {}
1865 ns = {}
1835 exec code in self.shell.user_ns, ns
1866 exec code in self.shell.user_ns, ns
1836 timer.inner = ns["inner"]
1867 timer.inner = ns["inner"]
1837
1868
1838 if number == 0:
1869 if number == 0:
1839 # determine number so that 0.2 <= total time < 2.0
1870 # determine number so that 0.2 <= total time < 2.0
1840 number = 1
1871 number = 1
1841 for i in range(1, 10):
1872 for i in range(1, 10):
1842 number *= 10
1843 if timer.timeit(number) >= 0.2:
1873 if timer.timeit(number) >= 0.2:
1844 break
1874 break
1875 number *= 10
1845
1876
1846 best = min(timer.repeat(repeat, number)) / number
1877 best = min(timer.repeat(repeat, number)) / number
1847
1878
1848 if best > 0.0:
1879 if best > 0.0:
1849 order = min(-int(math.floor(math.log10(best)) // 3), 3)
1880 order = min(-int(math.floor(math.log10(best)) // 3), 3)
1850 else:
1881 else:
1851 order = 3
1882 order = 3
1852 print u"%d loops, best of %d: %.*g %s per loop" % (number, repeat,
1883 print u"%d loops, best of %d: %.*g %s per loop" % (number, repeat,
1853 precision,
1884 precision,
1854 best * scaling[order],
1885 best * scaling[order],
1855 units[order])
1886 units[order])
1856 if tc > tc_min:
1887 if tc > tc_min:
1857 print "Compiler time: %.2f s" % tc
1888 print "Compiler time: %.2f s" % tc
1858
1889
1859 @testdec.skip_doctest
1890 @testdec.skip_doctest
1860 def magic_time(self,parameter_s = ''):
1891 def magic_time(self,parameter_s = ''):
1861 """Time execution of a Python statement or expression.
1892 """Time execution of a Python statement or expression.
1862
1893
1863 The CPU and wall clock times are printed, and the value of the
1894 The CPU and wall clock times are printed, and the value of the
1864 expression (if any) is returned. Note that under Win32, system time
1895 expression (if any) is returned. Note that under Win32, system time
1865 is always reported as 0, since it can not be measured.
1896 is always reported as 0, since it can not be measured.
1866
1897
1867 This function provides very basic timing functionality. In Python
1898 This function provides very basic timing functionality. In Python
1868 2.3, the timeit module offers more control and sophistication, so this
1899 2.3, the timeit module offers more control and sophistication, so this
1869 could be rewritten to use it (patches welcome).
1900 could be rewritten to use it (patches welcome).
1870
1901
1871 Some examples:
1902 Some examples:
1872
1903
1873 In [1]: time 2**128
1904 In [1]: time 2**128
1874 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1905 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1875 Wall time: 0.00
1906 Wall time: 0.00
1876 Out[1]: 340282366920938463463374607431768211456L
1907 Out[1]: 340282366920938463463374607431768211456L
1877
1908
1878 In [2]: n = 1000000
1909 In [2]: n = 1000000
1879
1910
1880 In [3]: time sum(range(n))
1911 In [3]: time sum(range(n))
1881 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1912 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1882 Wall time: 1.37
1913 Wall time: 1.37
1883 Out[3]: 499999500000L
1914 Out[3]: 499999500000L
1884
1915
1885 In [4]: time print 'hello world'
1916 In [4]: time print 'hello world'
1886 hello world
1917 hello world
1887 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1918 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1888 Wall time: 0.00
1919 Wall time: 0.00
1889
1920
1890 Note that the time needed by Python to compile the given expression
1921 Note that the time needed by Python to compile the given expression
1891 will be reported if it is more than 0.1s. In this example, the
1922 will be reported if it is more than 0.1s. In this example, the
1892 actual exponentiation is done by Python at compilation time, so while
1923 actual exponentiation is done by Python at compilation time, so while
1893 the expression can take a noticeable amount of time to compute, that
1924 the expression can take a noticeable amount of time to compute, that
1894 time is purely due to the compilation:
1925 time is purely due to the compilation:
1895
1926
1896 In [5]: time 3**9999;
1927 In [5]: time 3**9999;
1897 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1928 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1898 Wall time: 0.00 s
1929 Wall time: 0.00 s
1899
1930
1900 In [6]: time 3**999999;
1931 In [6]: time 3**999999;
1901 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1932 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1902 Wall time: 0.00 s
1933 Wall time: 0.00 s
1903 Compiler : 0.78 s
1934 Compiler : 0.78 s
1904 """
1935 """
1905
1936
1906 # fail immediately if the given expression can't be compiled
1937 # fail immediately if the given expression can't be compiled
1907
1938
1908 expr = self.shell.prefilter(parameter_s,False)
1939 expr = self.shell.prefilter(parameter_s,False)
1909
1940
1910 # Minimum time above which compilation time will be reported
1941 # Minimum time above which compilation time will be reported
1911 tc_min = 0.1
1942 tc_min = 0.1
1912
1943
1913 try:
1944 try:
1914 mode = 'eval'
1945 mode = 'eval'
1915 t0 = clock()
1946 t0 = clock()
1916 code = compile(expr,'<timed eval>',mode)
1947 code = compile(expr,'<timed eval>',mode)
1917 tc = clock()-t0
1948 tc = clock()-t0
1918 except SyntaxError:
1949 except SyntaxError:
1919 mode = 'exec'
1950 mode = 'exec'
1920 t0 = clock()
1951 t0 = clock()
1921 code = compile(expr,'<timed exec>',mode)
1952 code = compile(expr,'<timed exec>',mode)
1922 tc = clock()-t0
1953 tc = clock()-t0
1923 # skew measurement as little as possible
1954 # skew measurement as little as possible
1924 glob = self.shell.user_ns
1955 glob = self.shell.user_ns
1925 clk = clock2
1956 clk = clock2
1926 wtime = time.time
1957 wtime = time.time
1927 # time execution
1958 # time execution
1928 wall_st = wtime()
1959 wall_st = wtime()
1929 if mode=='eval':
1960 if mode=='eval':
1930 st = clk()
1961 st = clk()
1931 out = eval(code,glob)
1962 out = eval(code,glob)
1932 end = clk()
1963 end = clk()
1933 else:
1964 else:
1934 st = clk()
1965 st = clk()
1935 exec code in glob
1966 exec code in glob
1936 end = clk()
1967 end = clk()
1937 out = None
1968 out = None
1938 wall_end = wtime()
1969 wall_end = wtime()
1939 # Compute actual times and report
1970 # Compute actual times and report
1940 wall_time = wall_end-wall_st
1971 wall_time = wall_end-wall_st
1941 cpu_user = end[0]-st[0]
1972 cpu_user = end[0]-st[0]
1942 cpu_sys = end[1]-st[1]
1973 cpu_sys = end[1]-st[1]
1943 cpu_tot = cpu_user+cpu_sys
1974 cpu_tot = cpu_user+cpu_sys
1944 print "CPU times: user %.2f s, sys: %.2f s, total: %.2f s" % \
1975 print "CPU times: user %.2f s, sys: %.2f s, total: %.2f s" % \
1945 (cpu_user,cpu_sys,cpu_tot)
1976 (cpu_user,cpu_sys,cpu_tot)
1946 print "Wall time: %.2f s" % wall_time
1977 print "Wall time: %.2f s" % wall_time
1947 if tc > tc_min:
1978 if tc > tc_min:
1948 print "Compiler : %.2f s" % tc
1979 print "Compiler : %.2f s" % tc
1949 return out
1980 return out
1950
1981
1951 @testdec.skip_doctest
1982 @testdec.skip_doctest
1952 def magic_macro(self,parameter_s = ''):
1983 def magic_macro(self,parameter_s = ''):
1953 """Define a set of input lines as a macro for future re-execution.
1984 """Define a set of input lines as a macro for future re-execution.
1954
1985
1955 Usage:\\
1986 Usage:\\
1956 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1987 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1957
1988
1958 Options:
1989 Options:
1959
1990
1960 -r: use 'raw' input. By default, the 'processed' history is used,
1991 -r: use 'raw' input. By default, the 'processed' history is used,
1961 so that magics are loaded in their transformed version to valid
1992 so that magics are loaded in their transformed version to valid
1962 Python. If this option is given, the raw input as typed as the
1993 Python. If this option is given, the raw input as typed as the
1963 command line is used instead.
1994 command line is used instead.
1964
1995
1965 This will define a global variable called `name` which is a string
1996 This will define a global variable called `name` which is a string
1966 made of joining the slices and lines you specify (n1,n2,... numbers
1997 made of joining the slices and lines you specify (n1,n2,... numbers
1967 above) from your input history into a single string. This variable
1998 above) from your input history into a single string. This variable
1968 acts like an automatic function which re-executes those lines as if
1999 acts like an automatic function which re-executes those lines as if
1969 you had typed them. You just type 'name' at the prompt and the code
2000 you had typed them. You just type 'name' at the prompt and the code
1970 executes.
2001 executes.
1971
2002
1972 The notation for indicating number ranges is: n1-n2 means 'use line
2003 The notation for indicating number ranges is: n1-n2 means 'use line
1973 numbers n1,...n2' (the endpoint is included). That is, '5-7' means
2004 numbers n1,...n2' (the endpoint is included). That is, '5-7' means
1974 using the lines numbered 5,6 and 7.
2005 using the lines numbered 5,6 and 7.
1975
2006
1976 Note: as a 'hidden' feature, you can also use traditional python slice
2007 Note: as a 'hidden' feature, you can also use traditional python slice
1977 notation, where N:M means numbers N through M-1.
2008 notation, where N:M means numbers N through M-1.
1978
2009
1979 For example, if your history contains (%hist prints it):
2010 For example, if your history contains (%hist prints it):
1980
2011
1981 44: x=1
2012 44: x=1
1982 45: y=3
2013 45: y=3
1983 46: z=x+y
2014 46: z=x+y
1984 47: print x
2015 47: print x
1985 48: a=5
2016 48: a=5
1986 49: print 'x',x,'y',y
2017 49: print 'x',x,'y',y
1987
2018
1988 you can create a macro with lines 44 through 47 (included) and line 49
2019 you can create a macro with lines 44 through 47 (included) and line 49
1989 called my_macro with:
2020 called my_macro with:
1990
2021
1991 In [55]: %macro my_macro 44-47 49
2022 In [55]: %macro my_macro 44-47 49
1992
2023
1993 Now, typing `my_macro` (without quotes) will re-execute all this code
2024 Now, typing `my_macro` (without quotes) will re-execute all this code
1994 in one pass.
2025 in one pass.
1995
2026
1996 You don't need to give the line-numbers in order, and any given line
2027 You don't need to give the line-numbers in order, and any given line
1997 number can appear multiple times. You can assemble macros with any
2028 number can appear multiple times. You can assemble macros with any
1998 lines from your input history in any order.
2029 lines from your input history in any order.
1999
2030
2000 The macro is a simple object which holds its value in an attribute,
2031 The macro is a simple object which holds its value in an attribute,
2001 but IPython's display system checks for macros and executes them as
2032 but IPython's display system checks for macros and executes them as
2002 code instead of printing them when you type their name.
2033 code instead of printing them when you type their name.
2003
2034
2004 You can view a macro's contents by explicitly printing it with:
2035 You can view a macro's contents by explicitly printing it with:
2005
2036
2006 'print macro_name'.
2037 'print macro_name'.
2007
2038
2008 For one-off cases which DON'T contain magic function calls in them you
2039 For one-off cases which DON'T contain magic function calls in them you
2009 can obtain similar results by explicitly executing slices from your
2040 can obtain similar results by explicitly executing slices from your
2010 input history with:
2041 input history with:
2011
2042
2012 In [60]: exec In[44:48]+In[49]"""
2043 In [60]: exec In[44:48]+In[49]"""
2013
2044
2014 opts,args = self.parse_options(parameter_s,'r',mode='list')
2045 opts,args = self.parse_options(parameter_s,'r',mode='list')
2015 if not args:
2046 if not args:
2016 macs = [k for k,v in self.shell.user_ns.items() if isinstance(v, Macro)]
2047 macs = [k for k,v in self.shell.user_ns.items() if isinstance(v, Macro)]
2017 macs.sort()
2048 macs.sort()
2018 return macs
2049 return macs
2019 if len(args) == 1:
2050 if len(args) == 1:
2020 raise UsageError(
2051 raise UsageError(
2021 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
2052 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
2022 name,ranges = args[0], args[1:]
2053 name,ranges = args[0], args[1:]
2023
2054
2024 #print 'rng',ranges # dbg
2055 #print 'rng',ranges # dbg
2025 lines = self.extract_input_slices(ranges,opts.has_key('r'))
2056 lines = self.extract_input_slices(ranges,opts.has_key('r'))
2026 macro = Macro(lines)
2057 macro = Macro(lines)
2027 self.shell.user_ns.update({name:macro})
2058 self.shell.user_ns.update({name:macro})
2028 print 'Macro `%s` created. To execute, type its name (without quotes).' % name
2059 print 'Macro `%s` created. To execute, type its name (without quotes).' % name
2029 print 'Macro contents:'
2060 print 'Macro contents:'
2030 print macro,
2061 print macro,
2031
2062
2032 def magic_save(self,parameter_s = ''):
2063 def magic_save(self,parameter_s = ''):
2033 """Save a set of lines to a given filename.
2064 """Save a set of lines to a given filename.
2034
2065
2035 Usage:\\
2066 Usage:\\
2036 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
2067 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
2037
2068
2038 Options:
2069 Options:
2039
2070
2040 -r: use 'raw' input. By default, the 'processed' history is used,
2071 -r: use 'raw' input. By default, the 'processed' history is used,
2041 so that magics are loaded in their transformed version to valid
2072 so that magics are loaded in their transformed version to valid
2042 Python. If this option is given, the raw input as typed as the
2073 Python. If this option is given, the raw input as typed as the
2043 command line is used instead.
2074 command line is used instead.
2044
2075
2045 This function uses the same syntax as %macro for line extraction, but
2076 This function uses the same syntax as %macro for line extraction, but
2046 instead of creating a macro it saves the resulting string to the
2077 instead of creating a macro it saves the resulting string to the
2047 filename you specify.
2078 filename you specify.
2048
2079
2049 It adds a '.py' extension to the file if you don't do so yourself, and
2080 It adds a '.py' extension to the file if you don't do so yourself, and
2050 it asks for confirmation before overwriting existing files."""
2081 it asks for confirmation before overwriting existing files."""
2051
2082
2052 opts,args = self.parse_options(parameter_s,'r',mode='list')
2083 opts,args = self.parse_options(parameter_s,'r',mode='list')
2053 fname,ranges = args[0], args[1:]
2084 fname,ranges = args[0], args[1:]
2054 if not fname.endswith('.py'):
2085 if not fname.endswith('.py'):
2055 fname += '.py'
2086 fname += '.py'
2056 if os.path.isfile(fname):
2087 if os.path.isfile(fname):
2057 ans = raw_input('File `%s` exists. Overwrite (y/[N])? ' % fname)
2088 ans = raw_input('File `%s` exists. Overwrite (y/[N])? ' % fname)
2058 if ans.lower() not in ['y','yes']:
2089 if ans.lower() not in ['y','yes']:
2059 print 'Operation cancelled.'
2090 print 'Operation cancelled.'
2060 return
2091 return
2061 cmds = ''.join(self.extract_input_slices(ranges,opts.has_key('r')))
2092 cmds = ''.join(self.extract_input_slices(ranges,opts.has_key('r')))
2062 f = file(fname,'w')
2093 f = file(fname,'w')
2063 f.write(cmds)
2094 f.write(cmds)
2064 f.close()
2095 f.close()
2065 print 'The following commands were written to file `%s`:' % fname
2096 print 'The following commands were written to file `%s`:' % fname
2066 print cmds
2097 print cmds
2067
2098
2068 def _edit_macro(self,mname,macro):
2099 def _edit_macro(self,mname,macro):
2069 """open an editor with the macro data in a file"""
2100 """open an editor with the macro data in a file"""
2070 filename = self.shell.mktempfile(macro.value)
2101 filename = self.shell.mktempfile(macro.value)
2071 self.shell.hooks.editor(filename)
2102 self.shell.hooks.editor(filename)
2072
2103
2073 # and make a new macro object, to replace the old one
2104 # and make a new macro object, to replace the old one
2074 mfile = open(filename)
2105 mfile = open(filename)
2075 mvalue = mfile.read()
2106 mvalue = mfile.read()
2076 mfile.close()
2107 mfile.close()
2077 self.shell.user_ns[mname] = Macro(mvalue)
2108 self.shell.user_ns[mname] = Macro(mvalue)
2078
2109
2079 def magic_ed(self,parameter_s=''):
2110 def magic_ed(self,parameter_s=''):
2080 """Alias to %edit."""
2111 """Alias to %edit."""
2081 return self.magic_edit(parameter_s)
2112 return self.magic_edit(parameter_s)
2082
2113
2083 @testdec.skip_doctest
2114 @testdec.skip_doctest
2084 def magic_edit(self,parameter_s='',last_call=['','']):
2115 def magic_edit(self,parameter_s='',last_call=['','']):
2085 """Bring up an editor and execute the resulting code.
2116 """Bring up an editor and execute the resulting code.
2086
2117
2087 Usage:
2118 Usage:
2088 %edit [options] [args]
2119 %edit [options] [args]
2089
2120
2090 %edit runs IPython's editor hook. The default version of this hook is
2121 %edit runs IPython's editor hook. The default version of this hook is
2091 set to call the __IPYTHON__.rc.editor command. This is read from your
2122 set to call the __IPYTHON__.rc.editor command. This is read from your
2092 environment variable $EDITOR. If this isn't found, it will default to
2123 environment variable $EDITOR. If this isn't found, it will default to
2093 vi under Linux/Unix and to notepad under Windows. See the end of this
2124 vi under Linux/Unix and to notepad under Windows. See the end of this
2094 docstring for how to change the editor hook.
2125 docstring for how to change the editor hook.
2095
2126
2096 You can also set the value of this editor via the command line option
2127 You can also set the value of this editor via the command line option
2097 '-editor' or in your ipythonrc file. This is useful if you wish to use
2128 '-editor' or in your ipythonrc file. This is useful if you wish to use
2098 specifically for IPython an editor different from your typical default
2129 specifically for IPython an editor different from your typical default
2099 (and for Windows users who typically don't set environment variables).
2130 (and for Windows users who typically don't set environment variables).
2100
2131
2101 This command allows you to conveniently edit multi-line code right in
2132 This command allows you to conveniently edit multi-line code right in
2102 your IPython session.
2133 your IPython session.
2103
2134
2104 If called without arguments, %edit opens up an empty editor with a
2135 If called without arguments, %edit opens up an empty editor with a
2105 temporary file and will execute the contents of this file when you
2136 temporary file and will execute the contents of this file when you
2106 close it (don't forget to save it!).
2137 close it (don't forget to save it!).
2107
2138
2108
2139
2109 Options:
2140 Options:
2110
2141
2111 -n <number>: open the editor at a specified line number. By default,
2142 -n <number>: open the editor at a specified line number. By default,
2112 the IPython editor hook uses the unix syntax 'editor +N filename', but
2143 the IPython editor hook uses the unix syntax 'editor +N filename', but
2113 you can configure this by providing your own modified hook if your
2144 you can configure this by providing your own modified hook if your
2114 favorite editor supports line-number specifications with a different
2145 favorite editor supports line-number specifications with a different
2115 syntax.
2146 syntax.
2116
2147
2117 -p: this will call the editor with the same data as the previous time
2148 -p: this will call the editor with the same data as the previous time
2118 it was used, regardless of how long ago (in your current session) it
2149 it was used, regardless of how long ago (in your current session) it
2119 was.
2150 was.
2120
2151
2121 -r: use 'raw' input. This option only applies to input taken from the
2152 -r: use 'raw' input. This option only applies to input taken from the
2122 user's history. By default, the 'processed' history is used, so that
2153 user's history. By default, the 'processed' history is used, so that
2123 magics are loaded in their transformed version to valid Python. If
2154 magics are loaded in their transformed version to valid Python. If
2124 this option is given, the raw input as typed as the command line is
2155 this option is given, the raw input as typed as the command line is
2125 used instead. When you exit the editor, it will be executed by
2156 used instead. When you exit the editor, it will be executed by
2126 IPython's own processor.
2157 IPython's own processor.
2127
2158
2128 -x: do not execute the edited code immediately upon exit. This is
2159 -x: do not execute the edited code immediately upon exit. This is
2129 mainly useful if you are editing programs which need to be called with
2160 mainly useful if you are editing programs which need to be called with
2130 command line arguments, which you can then do using %run.
2161 command line arguments, which you can then do using %run.
2131
2162
2132
2163
2133 Arguments:
2164 Arguments:
2134
2165
2135 If arguments are given, the following possibilites exist:
2166 If arguments are given, the following possibilites exist:
2136
2167
2137 - The arguments are numbers or pairs of colon-separated numbers (like
2168 - The arguments are numbers or pairs of colon-separated numbers (like
2138 1 4:8 9). These are interpreted as lines of previous input to be
2169 1 4:8 9). These are interpreted as lines of previous input to be
2139 loaded into the editor. The syntax is the same of the %macro command.
2170 loaded into the editor. The syntax is the same of the %macro command.
2140
2171
2141 - If the argument doesn't start with a number, it is evaluated as a
2172 - If the argument doesn't start with a number, it is evaluated as a
2142 variable and its contents loaded into the editor. You can thus edit
2173 variable and its contents loaded into the editor. You can thus edit
2143 any string which contains python code (including the result of
2174 any string which contains python code (including the result of
2144 previous edits).
2175 previous edits).
2145
2176
2146 - If the argument is the name of an object (other than a string),
2177 - If the argument is the name of an object (other than a string),
2147 IPython will try to locate the file where it was defined and open the
2178 IPython will try to locate the file where it was defined and open the
2148 editor at the point where it is defined. You can use `%edit function`
2179 editor at the point where it is defined. You can use `%edit function`
2149 to load an editor exactly at the point where 'function' is defined,
2180 to load an editor exactly at the point where 'function' is defined,
2150 edit it and have the file be executed automatically.
2181 edit it and have the file be executed automatically.
2151
2182
2152 If the object is a macro (see %macro for details), this opens up your
2183 If the object is a macro (see %macro for details), this opens up your
2153 specified editor with a temporary file containing the macro's data.
2184 specified editor with a temporary file containing the macro's data.
2154 Upon exit, the macro is reloaded with the contents of the file.
2185 Upon exit, the macro is reloaded with the contents of the file.
2155
2186
2156 Note: opening at an exact line is only supported under Unix, and some
2187 Note: opening at an exact line is only supported under Unix, and some
2157 editors (like kedit and gedit up to Gnome 2.8) do not understand the
2188 editors (like kedit and gedit up to Gnome 2.8) do not understand the
2158 '+NUMBER' parameter necessary for this feature. Good editors like
2189 '+NUMBER' parameter necessary for this feature. Good editors like
2159 (X)Emacs, vi, jed, pico and joe all do.
2190 (X)Emacs, vi, jed, pico and joe all do.
2160
2191
2161 - If the argument is not found as a variable, IPython will look for a
2192 - If the argument is not found as a variable, IPython will look for a
2162 file with that name (adding .py if necessary) and load it into the
2193 file with that name (adding .py if necessary) and load it into the
2163 editor. It will execute its contents with execfile() when you exit,
2194 editor. It will execute its contents with execfile() when you exit,
2164 loading any code in the file into your interactive namespace.
2195 loading any code in the file into your interactive namespace.
2165
2196
2166 After executing your code, %edit will return as output the code you
2197 After executing your code, %edit will return as output the code you
2167 typed in the editor (except when it was an existing file). This way
2198 typed in the editor (except when it was an existing file). This way
2168 you can reload the code in further invocations of %edit as a variable,
2199 you can reload the code in further invocations of %edit as a variable,
2169 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
2200 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
2170 the output.
2201 the output.
2171
2202
2172 Note that %edit is also available through the alias %ed.
2203 Note that %edit is also available through the alias %ed.
2173
2204
2174 This is an example of creating a simple function inside the editor and
2205 This is an example of creating a simple function inside the editor and
2175 then modifying it. First, start up the editor:
2206 then modifying it. First, start up the editor:
2176
2207
2177 In [1]: ed
2208 In [1]: ed
2178 Editing... done. Executing edited code...
2209 Editing... done. Executing edited code...
2179 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
2210 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
2180
2211
2181 We can then call the function foo():
2212 We can then call the function foo():
2182
2213
2183 In [2]: foo()
2214 In [2]: foo()
2184 foo() was defined in an editing session
2215 foo() was defined in an editing session
2185
2216
2186 Now we edit foo. IPython automatically loads the editor with the
2217 Now we edit foo. IPython automatically loads the editor with the
2187 (temporary) file where foo() was previously defined:
2218 (temporary) file where foo() was previously defined:
2188
2219
2189 In [3]: ed foo
2220 In [3]: ed foo
2190 Editing... done. Executing edited code...
2221 Editing... done. Executing edited code...
2191
2222
2192 And if we call foo() again we get the modified version:
2223 And if we call foo() again we get the modified version:
2193
2224
2194 In [4]: foo()
2225 In [4]: foo()
2195 foo() has now been changed!
2226 foo() has now been changed!
2196
2227
2197 Here is an example of how to edit a code snippet successive
2228 Here is an example of how to edit a code snippet successive
2198 times. First we call the editor:
2229 times. First we call the editor:
2199
2230
2200 In [5]: ed
2231 In [5]: ed
2201 Editing... done. Executing edited code...
2232 Editing... done. Executing edited code...
2202 hello
2233 hello
2203 Out[5]: "print 'hello'n"
2234 Out[5]: "print 'hello'n"
2204
2235
2205 Now we call it again with the previous output (stored in _):
2236 Now we call it again with the previous output (stored in _):
2206
2237
2207 In [6]: ed _
2238 In [6]: ed _
2208 Editing... done. Executing edited code...
2239 Editing... done. Executing edited code...
2209 hello world
2240 hello world
2210 Out[6]: "print 'hello world'n"
2241 Out[6]: "print 'hello world'n"
2211
2242
2212 Now we call it with the output #8 (stored in _8, also as Out[8]):
2243 Now we call it with the output #8 (stored in _8, also as Out[8]):
2213
2244
2214 In [7]: ed _8
2245 In [7]: ed _8
2215 Editing... done. Executing edited code...
2246 Editing... done. Executing edited code...
2216 hello again
2247 hello again
2217 Out[7]: "print 'hello again'n"
2248 Out[7]: "print 'hello again'n"
2218
2249
2219
2250
2220 Changing the default editor hook:
2251 Changing the default editor hook:
2221
2252
2222 If you wish to write your own editor hook, you can put it in a
2253 If you wish to write your own editor hook, you can put it in a
2223 configuration file which you load at startup time. The default hook
2254 configuration file which you load at startup time. The default hook
2224 is defined in the IPython.hooks module, and you can use that as a
2255 is defined in the IPython.hooks module, and you can use that as a
2225 starting example for further modifications. That file also has
2256 starting example for further modifications. That file also has
2226 general instructions on how to set a new hook for use once you've
2257 general instructions on how to set a new hook for use once you've
2227 defined it."""
2258 defined it."""
2228
2259
2229 # FIXME: This function has become a convoluted mess. It needs a
2260 # FIXME: This function has become a convoluted mess. It needs a
2230 # ground-up rewrite with clean, simple logic.
2261 # ground-up rewrite with clean, simple logic.
2231
2262
2232 def make_filename(arg):
2263 def make_filename(arg):
2233 "Make a filename from the given args"
2264 "Make a filename from the given args"
2234 try:
2265 try:
2235 filename = get_py_filename(arg)
2266 filename = get_py_filename(arg)
2236 except IOError:
2267 except IOError:
2237 if args.endswith('.py'):
2268 if args.endswith('.py'):
2238 filename = arg
2269 filename = arg
2239 else:
2270 else:
2240 filename = None
2271 filename = None
2241 return filename
2272 return filename
2242
2273
2243 # custom exceptions
2274 # custom exceptions
2244 class DataIsObject(Exception): pass
2275 class DataIsObject(Exception): pass
2245
2276
2246 opts,args = self.parse_options(parameter_s,'prxn:')
2277 opts,args = self.parse_options(parameter_s,'prxn:')
2247 # Set a few locals from the options for convenience:
2278 # Set a few locals from the options for convenience:
2248 opts_p = opts.has_key('p')
2279 opts_p = opts.has_key('p')
2249 opts_r = opts.has_key('r')
2280 opts_r = opts.has_key('r')
2250
2281
2251 # Default line number value
2282 # Default line number value
2252 lineno = opts.get('n',None)
2283 lineno = opts.get('n',None)
2253
2284
2254 if opts_p:
2285 if opts_p:
2255 args = '_%s' % last_call[0]
2286 args = '_%s' % last_call[0]
2256 if not self.shell.user_ns.has_key(args):
2287 if not self.shell.user_ns.has_key(args):
2257 args = last_call[1]
2288 args = last_call[1]
2258
2289
2259 # use last_call to remember the state of the previous call, but don't
2290 # use last_call to remember the state of the previous call, but don't
2260 # let it be clobbered by successive '-p' calls.
2291 # let it be clobbered by successive '-p' calls.
2261 try:
2292 try:
2262 last_call[0] = self.shell.outputcache.prompt_count
2293 last_call[0] = self.shell.outputcache.prompt_count
2263 if not opts_p:
2294 if not opts_p:
2264 last_call[1] = parameter_s
2295 last_call[1] = parameter_s
2265 except:
2296 except:
2266 pass
2297 pass
2267
2298
2268 # by default this is done with temp files, except when the given
2299 # by default this is done with temp files, except when the given
2269 # arg is a filename
2300 # arg is a filename
2270 use_temp = 1
2301 use_temp = 1
2271
2302
2272 if re.match(r'\d',args):
2303 if re.match(r'\d',args):
2273 # Mode where user specifies ranges of lines, like in %macro.
2304 # Mode where user specifies ranges of lines, like in %macro.
2274 # This means that you can't edit files whose names begin with
2305 # This means that you can't edit files whose names begin with
2275 # numbers this way. Tough.
2306 # numbers this way. Tough.
2276 ranges = args.split()
2307 ranges = args.split()
2277 data = ''.join(self.extract_input_slices(ranges,opts_r))
2308 data = ''.join(self.extract_input_slices(ranges,opts_r))
2278 elif args.endswith('.py'):
2309 elif args.endswith('.py'):
2279 filename = make_filename(args)
2310 filename = make_filename(args)
2280 data = ''
2311 data = ''
2281 use_temp = 0
2312 use_temp = 0
2282 elif args:
2313 elif args:
2283 try:
2314 try:
2284 # Load the parameter given as a variable. If not a string,
2315 # Load the parameter given as a variable. If not a string,
2285 # process it as an object instead (below)
2316 # process it as an object instead (below)
2286
2317
2287 #print '*** args',args,'type',type(args) # dbg
2318 #print '*** args',args,'type',type(args) # dbg
2288 data = eval(args,self.shell.user_ns)
2319 data = eval(args,self.shell.user_ns)
2289 if not type(data) in StringTypes:
2320 if not type(data) in StringTypes:
2290 raise DataIsObject
2321 raise DataIsObject
2291
2322
2292 except (NameError,SyntaxError):
2323 except (NameError,SyntaxError):
2293 # given argument is not a variable, try as a filename
2324 # given argument is not a variable, try as a filename
2294 filename = make_filename(args)
2325 filename = make_filename(args)
2295 if filename is None:
2326 if filename is None:
2296 warn("Argument given (%s) can't be found as a variable "
2327 warn("Argument given (%s) can't be found as a variable "
2297 "or as a filename." % args)
2328 "or as a filename." % args)
2298 return
2329 return
2299
2330
2300 data = ''
2331 data = ''
2301 use_temp = 0
2332 use_temp = 0
2302 except DataIsObject:
2333 except DataIsObject:
2303
2334
2304 # macros have a special edit function
2335 # macros have a special edit function
2305 if isinstance(data,Macro):
2336 if isinstance(data,Macro):
2306 self._edit_macro(args,data)
2337 self._edit_macro(args,data)
2307 return
2338 return
2308
2339
2309 # For objects, try to edit the file where they are defined
2340 # For objects, try to edit the file where they are defined
2310 try:
2341 try:
2311 filename = inspect.getabsfile(data)
2342 filename = inspect.getabsfile(data)
2312 if 'fakemodule' in filename.lower() and inspect.isclass(data):
2343 if 'fakemodule' in filename.lower() and inspect.isclass(data):
2313 # class created by %edit? Try to find source
2344 # class created by %edit? Try to find source
2314 # by looking for method definitions instead, the
2345 # by looking for method definitions instead, the
2315 # __module__ in those classes is FakeModule.
2346 # __module__ in those classes is FakeModule.
2316 attrs = [getattr(data, aname) for aname in dir(data)]
2347 attrs = [getattr(data, aname) for aname in dir(data)]
2317 for attr in attrs:
2348 for attr in attrs:
2318 if not inspect.ismethod(attr):
2349 if not inspect.ismethod(attr):
2319 continue
2350 continue
2320 filename = inspect.getabsfile(attr)
2351 filename = inspect.getabsfile(attr)
2321 if filename and 'fakemodule' not in filename.lower():
2352 if filename and 'fakemodule' not in filename.lower():
2322 # change the attribute to be the edit target instead
2353 # change the attribute to be the edit target instead
2323 data = attr
2354 data = attr
2324 break
2355 break
2325
2356
2326 datafile = 1
2357 datafile = 1
2327 except TypeError:
2358 except TypeError:
2328 filename = make_filename(args)
2359 filename = make_filename(args)
2329 datafile = 1
2360 datafile = 1
2330 warn('Could not find file where `%s` is defined.\n'
2361 warn('Could not find file where `%s` is defined.\n'
2331 'Opening a file named `%s`' % (args,filename))
2362 'Opening a file named `%s`' % (args,filename))
2332 # Now, make sure we can actually read the source (if it was in
2363 # Now, make sure we can actually read the source (if it was in
2333 # a temp file it's gone by now).
2364 # a temp file it's gone by now).
2334 if datafile:
2365 if datafile:
2335 try:
2366 try:
2336 if lineno is None:
2367 if lineno is None:
2337 lineno = inspect.getsourcelines(data)[1]
2368 lineno = inspect.getsourcelines(data)[1]
2338 except IOError:
2369 except IOError:
2339 filename = make_filename(args)
2370 filename = make_filename(args)
2340 if filename is None:
2371 if filename is None:
2341 warn('The file `%s` where `%s` was defined cannot '
2372 warn('The file `%s` where `%s` was defined cannot '
2342 'be read.' % (filename,data))
2373 'be read.' % (filename,data))
2343 return
2374 return
2344 use_temp = 0
2375 use_temp = 0
2345 else:
2376 else:
2346 data = ''
2377 data = ''
2347
2378
2348 if use_temp:
2379 if use_temp:
2349 filename = self.shell.mktempfile(data)
2380 filename = self.shell.mktempfile(data)
2350 print 'IPython will make a temporary file named:',filename
2381 print 'IPython will make a temporary file named:',filename
2351
2382
2352 # do actual editing here
2383 # do actual editing here
2353 print 'Editing...',
2384 print 'Editing...',
2354 sys.stdout.flush()
2385 sys.stdout.flush()
2355 try:
2386 try:
2356 self.shell.hooks.editor(filename,lineno)
2387 self.shell.hooks.editor(filename,lineno)
2357 except IPython.ipapi.TryNext:
2388 except IPython.ipapi.TryNext:
2358 warn('Could not open editor')
2389 warn('Could not open editor')
2359 return
2390 return
2360
2391
2361 # XXX TODO: should this be generalized for all string vars?
2392 # XXX TODO: should this be generalized for all string vars?
2362 # For now, this is special-cased to blocks created by cpaste
2393 # For now, this is special-cased to blocks created by cpaste
2363 if args.strip() == 'pasted_block':
2394 if args.strip() == 'pasted_block':
2364 self.shell.user_ns['pasted_block'] = file_read(filename)
2395 self.shell.user_ns['pasted_block'] = file_read(filename)
2365
2396
2366 if opts.has_key('x'): # -x prevents actual execution
2397 if opts.has_key('x'): # -x prevents actual execution
2367 print
2398 print
2368 else:
2399 else:
2369 print 'done. Executing edited code...'
2400 print 'done. Executing edited code...'
2370 if opts_r:
2401 if opts_r:
2371 self.shell.runlines(file_read(filename))
2402 self.shell.runlines(file_read(filename))
2372 else:
2403 else:
2373 self.shell.safe_execfile(filename,self.shell.user_ns,
2404 self.shell.safe_execfile(filename,self.shell.user_ns,
2374 self.shell.user_ns)
2405 self.shell.user_ns)
2375
2406
2376
2407
2377 if use_temp:
2408 if use_temp:
2378 try:
2409 try:
2379 return open(filename).read()
2410 return open(filename).read()
2380 except IOError,msg:
2411 except IOError,msg:
2381 if msg.filename == filename:
2412 if msg.filename == filename:
2382 warn('File not found. Did you forget to save?')
2413 warn('File not found. Did you forget to save?')
2383 return
2414 return
2384 else:
2415 else:
2385 self.shell.showtraceback()
2416 self.shell.showtraceback()
2386
2417
2387 def magic_xmode(self,parameter_s = ''):
2418 def magic_xmode(self,parameter_s = ''):
2388 """Switch modes for the exception handlers.
2419 """Switch modes for the exception handlers.
2389
2420
2390 Valid modes: Plain, Context and Verbose.
2421 Valid modes: Plain, Context and Verbose.
2391
2422
2392 If called without arguments, acts as a toggle."""
2423 If called without arguments, acts as a toggle."""
2393
2424
2394 def xmode_switch_err(name):
2425 def xmode_switch_err(name):
2395 warn('Error changing %s exception modes.\n%s' %
2426 warn('Error changing %s exception modes.\n%s' %
2396 (name,sys.exc_info()[1]))
2427 (name,sys.exc_info()[1]))
2397
2428
2398 shell = self.shell
2429 shell = self.shell
2399 new_mode = parameter_s.strip().capitalize()
2430 new_mode = parameter_s.strip().capitalize()
2400 try:
2431 try:
2401 shell.InteractiveTB.set_mode(mode=new_mode)
2432 shell.InteractiveTB.set_mode(mode=new_mode)
2402 print 'Exception reporting mode:',shell.InteractiveTB.mode
2433 print 'Exception reporting mode:',shell.InteractiveTB.mode
2403 except:
2434 except:
2404 xmode_switch_err('user')
2435 xmode_switch_err('user')
2405
2436
2406 # threaded shells use a special handler in sys.excepthook
2437 # threaded shells use a special handler in sys.excepthook
2407 if shell.isthreaded:
2438 if shell.isthreaded:
2408 try:
2439 try:
2409 shell.sys_excepthook.set_mode(mode=new_mode)
2440 shell.sys_excepthook.set_mode(mode=new_mode)
2410 except:
2441 except:
2411 xmode_switch_err('threaded')
2442 xmode_switch_err('threaded')
2412
2443
2413 def magic_colors(self,parameter_s = ''):
2444 def magic_colors(self,parameter_s = ''):
2414 """Switch color scheme for prompts, info system and exception handlers.
2445 """Switch color scheme for prompts, info system and exception handlers.
2415
2446
2416 Currently implemented schemes: NoColor, Linux, LightBG.
2447 Currently implemented schemes: NoColor, Linux, LightBG.
2417
2448
2418 Color scheme names are not case-sensitive."""
2449 Color scheme names are not case-sensitive."""
2419
2450
2420 def color_switch_err(name):
2451 def color_switch_err(name):
2421 warn('Error changing %s color schemes.\n%s' %
2452 warn('Error changing %s color schemes.\n%s' %
2422 (name,sys.exc_info()[1]))
2453 (name,sys.exc_info()[1]))
2423
2454
2424
2455
2425 new_scheme = parameter_s.strip()
2456 new_scheme = parameter_s.strip()
2426 if not new_scheme:
2457 if not new_scheme:
2427 raise UsageError(
2458 raise UsageError(
2428 "%colors: you must specify a color scheme. See '%colors?'")
2459 "%colors: you must specify a color scheme. See '%colors?'")
2429 return
2460 return
2430 # local shortcut
2461 # local shortcut
2431 shell = self.shell
2462 shell = self.shell
2432
2463
2433 import IPython.rlineimpl as readline
2464 import IPython.rlineimpl as readline
2434
2465
2435 if not readline.have_readline and sys.platform == "win32":
2466 if not readline.have_readline and sys.platform == "win32":
2436 msg = """\
2467 msg = """\
2437 Proper color support under MS Windows requires the pyreadline library.
2468 Proper color support under MS Windows requires the pyreadline library.
2438 You can find it at:
2469 You can find it at:
2439 http://ipython.scipy.org/moin/PyReadline/Intro
2470 http://ipython.scipy.org/moin/PyReadline/Intro
2440 Gary's readline needs the ctypes module, from:
2471 Gary's readline needs the ctypes module, from:
2441 http://starship.python.net/crew/theller/ctypes
2472 http://starship.python.net/crew/theller/ctypes
2442 (Note that ctypes is already part of Python versions 2.5 and newer).
2473 (Note that ctypes is already part of Python versions 2.5 and newer).
2443
2474
2444 Defaulting color scheme to 'NoColor'"""
2475 Defaulting color scheme to 'NoColor'"""
2445 new_scheme = 'NoColor'
2476 new_scheme = 'NoColor'
2446 warn(msg)
2477 warn(msg)
2447
2478
2448 # readline option is 0
2479 # readline option is 0
2449 if not shell.has_readline:
2480 if not shell.has_readline:
2450 new_scheme = 'NoColor'
2481 new_scheme = 'NoColor'
2451
2482
2452 # Set prompt colors
2483 # Set prompt colors
2453 try:
2484 try:
2454 shell.outputcache.set_colors(new_scheme)
2485 shell.outputcache.set_colors(new_scheme)
2455 except:
2486 except:
2456 color_switch_err('prompt')
2487 color_switch_err('prompt')
2457 else:
2488 else:
2458 shell.rc.colors = \
2489 shell.rc.colors = \
2459 shell.outputcache.color_table.active_scheme_name
2490 shell.outputcache.color_table.active_scheme_name
2460 # Set exception colors
2491 # Set exception colors
2461 try:
2492 try:
2462 shell.InteractiveTB.set_colors(scheme = new_scheme)
2493 shell.InteractiveTB.set_colors(scheme = new_scheme)
2463 shell.SyntaxTB.set_colors(scheme = new_scheme)
2494 shell.SyntaxTB.set_colors(scheme = new_scheme)
2464 except:
2495 except:
2465 color_switch_err('exception')
2496 color_switch_err('exception')
2466
2497
2467 # threaded shells use a verbose traceback in sys.excepthook
2498 # threaded shells use a verbose traceback in sys.excepthook
2468 if shell.isthreaded:
2499 if shell.isthreaded:
2469 try:
2500 try:
2470 shell.sys_excepthook.set_colors(scheme=new_scheme)
2501 shell.sys_excepthook.set_colors(scheme=new_scheme)
2471 except:
2502 except:
2472 color_switch_err('system exception handler')
2503 color_switch_err('system exception handler')
2473
2504
2474 # Set info (for 'object?') colors
2505 # Set info (for 'object?') colors
2475 if shell.rc.color_info:
2506 if shell.rc.color_info:
2476 try:
2507 try:
2477 shell.inspector.set_active_scheme(new_scheme)
2508 shell.inspector.set_active_scheme(new_scheme)
2478 except:
2509 except:
2479 color_switch_err('object inspector')
2510 color_switch_err('object inspector')
2480 else:
2511 else:
2481 shell.inspector.set_active_scheme('NoColor')
2512 shell.inspector.set_active_scheme('NoColor')
2482
2513
2483 def magic_color_info(self,parameter_s = ''):
2514 def magic_color_info(self,parameter_s = ''):
2484 """Toggle color_info.
2515 """Toggle color_info.
2485
2516
2486 The color_info configuration parameter controls whether colors are
2517 The color_info configuration parameter controls whether colors are
2487 used for displaying object details (by things like %psource, %pfile or
2518 used for displaying object details (by things like %psource, %pfile or
2488 the '?' system). This function toggles this value with each call.
2519 the '?' system). This function toggles this value with each call.
2489
2520
2490 Note that unless you have a fairly recent pager (less works better
2521 Note that unless you have a fairly recent pager (less works better
2491 than more) in your system, using colored object information displays
2522 than more) in your system, using colored object information displays
2492 will not work properly. Test it and see."""
2523 will not work properly. Test it and see."""
2493
2524
2494 self.shell.rc.color_info = 1 - self.shell.rc.color_info
2525 self.shell.rc.color_info = 1 - self.shell.rc.color_info
2495 self.magic_colors(self.shell.rc.colors)
2526 self.magic_colors(self.shell.rc.colors)
2496 print 'Object introspection functions have now coloring:',
2527 print 'Object introspection functions have now coloring:',
2497 print ['OFF','ON'][self.shell.rc.color_info]
2528 print ['OFF','ON'][self.shell.rc.color_info]
2498
2529
2499 def magic_Pprint(self, parameter_s=''):
2530 def magic_Pprint(self, parameter_s=''):
2500 """Toggle pretty printing on/off."""
2531 """Toggle pretty printing on/off."""
2501
2532
2502 self.shell.rc.pprint = 1 - self.shell.rc.pprint
2533 self.shell.rc.pprint = 1 - self.shell.rc.pprint
2503 print 'Pretty printing has been turned', \
2534 print 'Pretty printing has been turned', \
2504 ['OFF','ON'][self.shell.rc.pprint]
2535 ['OFF','ON'][self.shell.rc.pprint]
2505
2536
2506 def magic_exit(self, parameter_s=''):
2537 def magic_exit(self, parameter_s=''):
2507 """Exit IPython, confirming if configured to do so.
2538 """Exit IPython, confirming if configured to do so.
2508
2539
2509 You can configure whether IPython asks for confirmation upon exit by
2540 You can configure whether IPython asks for confirmation upon exit by
2510 setting the confirm_exit flag in the ipythonrc file."""
2541 setting the confirm_exit flag in the ipythonrc file."""
2511
2542
2512 self.shell.exit()
2543 self.shell.exit()
2513
2544
2514 def magic_quit(self, parameter_s=''):
2545 def magic_quit(self, parameter_s=''):
2515 """Exit IPython, confirming if configured to do so (like %exit)"""
2546 """Exit IPython, confirming if configured to do so (like %exit)"""
2516
2547
2517 self.shell.exit()
2548 self.shell.exit()
2518
2549
2519 def magic_Exit(self, parameter_s=''):
2550 def magic_Exit(self, parameter_s=''):
2520 """Exit IPython without confirmation."""
2551 """Exit IPython without confirmation."""
2521
2552
2522 self.shell.ask_exit()
2553 self.shell.ask_exit()
2523
2554
2524 #......................................................................
2555 #......................................................................
2525 # Functions to implement unix shell-type things
2556 # Functions to implement unix shell-type things
2526
2557
2527 @testdec.skip_doctest
2558 @testdec.skip_doctest
2528 def magic_alias(self, parameter_s = ''):
2559 def magic_alias(self, parameter_s = ''):
2529 """Define an alias for a system command.
2560 """Define an alias for a system command.
2530
2561
2531 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
2562 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
2532
2563
2533 Then, typing 'alias_name params' will execute the system command 'cmd
2564 Then, typing 'alias_name params' will execute the system command 'cmd
2534 params' (from your underlying operating system).
2565 params' (from your underlying operating system).
2535
2566
2536 Aliases have lower precedence than magic functions and Python normal
2567 Aliases have lower precedence than magic functions and Python normal
2537 variables, so if 'foo' is both a Python variable and an alias, the
2568 variables, so if 'foo' is both a Python variable and an alias, the
2538 alias can not be executed until 'del foo' removes the Python variable.
2569 alias can not be executed until 'del foo' removes the Python variable.
2539
2570
2540 You can use the %l specifier in an alias definition to represent the
2571 You can use the %l specifier in an alias definition to represent the
2541 whole line when the alias is called. For example:
2572 whole line when the alias is called. For example:
2542
2573
2543 In [2]: alias all echo "Input in brackets: <%l>"
2574 In [2]: alias all echo "Input in brackets: <%l>"
2544 In [3]: all hello world
2575 In [3]: all hello world
2545 Input in brackets: <hello world>
2576 Input in brackets: <hello world>
2546
2577
2547 You can also define aliases with parameters using %s specifiers (one
2578 You can also define aliases with parameters using %s specifiers (one
2548 per parameter):
2579 per parameter):
2549
2580
2550 In [1]: alias parts echo first %s second %s
2581 In [1]: alias parts echo first %s second %s
2551 In [2]: %parts A B
2582 In [2]: %parts A B
2552 first A second B
2583 first A second B
2553 In [3]: %parts A
2584 In [3]: %parts A
2554 Incorrect number of arguments: 2 expected.
2585 Incorrect number of arguments: 2 expected.
2555 parts is an alias to: 'echo first %s second %s'
2586 parts is an alias to: 'echo first %s second %s'
2556
2587
2557 Note that %l and %s are mutually exclusive. You can only use one or
2588 Note that %l and %s are mutually exclusive. You can only use one or
2558 the other in your aliases.
2589 the other in your aliases.
2559
2590
2560 Aliases expand Python variables just like system calls using ! or !!
2591 Aliases expand Python variables just like system calls using ! or !!
2561 do: all expressions prefixed with '$' get expanded. For details of
2592 do: all expressions prefixed with '$' get expanded. For details of
2562 the semantic rules, see PEP-215:
2593 the semantic rules, see PEP-215:
2563 http://www.python.org/peps/pep-0215.html. This is the library used by
2594 http://www.python.org/peps/pep-0215.html. This is the library used by
2564 IPython for variable expansion. If you want to access a true shell
2595 IPython for variable expansion. If you want to access a true shell
2565 variable, an extra $ is necessary to prevent its expansion by IPython:
2596 variable, an extra $ is necessary to prevent its expansion by IPython:
2566
2597
2567 In [6]: alias show echo
2598 In [6]: alias show echo
2568 In [7]: PATH='A Python string'
2599 In [7]: PATH='A Python string'
2569 In [8]: show $PATH
2600 In [8]: show $PATH
2570 A Python string
2601 A Python string
2571 In [9]: show $$PATH
2602 In [9]: show $$PATH
2572 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
2603 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
2573
2604
2574 You can use the alias facility to acess all of $PATH. See the %rehash
2605 You can use the alias facility to acess all of $PATH. See the %rehash
2575 and %rehashx functions, which automatically create aliases for the
2606 and %rehashx functions, which automatically create aliases for the
2576 contents of your $PATH.
2607 contents of your $PATH.
2577
2608
2578 If called with no parameters, %alias prints the current alias table."""
2609 If called with no parameters, %alias prints the current alias table."""
2579
2610
2580 par = parameter_s.strip()
2611 par = parameter_s.strip()
2581 if not par:
2612 if not par:
2582 stored = self.db.get('stored_aliases', {} )
2613 stored = self.db.get('stored_aliases', {} )
2583 atab = self.shell.alias_table
2614 atab = self.shell.alias_table
2584 aliases = atab.keys()
2615 aliases = atab.keys()
2585 aliases.sort()
2616 aliases.sort()
2586 res = []
2617 res = []
2587 showlast = []
2618 showlast = []
2588 for alias in aliases:
2619 for alias in aliases:
2589 special = False
2620 special = False
2590 try:
2621 try:
2591 tgt = atab[alias][1]
2622 tgt = atab[alias][1]
2592 except (TypeError, AttributeError):
2623 except (TypeError, AttributeError):
2593 # unsubscriptable? probably a callable
2624 # unsubscriptable? probably a callable
2594 tgt = atab[alias]
2625 tgt = atab[alias]
2595 special = True
2626 special = True
2596 # 'interesting' aliases
2627 # 'interesting' aliases
2597 if (alias in stored or
2628 if (alias in stored or
2598 special or
2629 special or
2599 alias.lower() != os.path.splitext(tgt)[0].lower() or
2630 alias.lower() != os.path.splitext(tgt)[0].lower() or
2600 ' ' in tgt):
2631 ' ' in tgt):
2601 showlast.append((alias, tgt))
2632 showlast.append((alias, tgt))
2602 else:
2633 else:
2603 res.append((alias, tgt ))
2634 res.append((alias, tgt ))
2604
2635
2605 # show most interesting aliases last
2636 # show most interesting aliases last
2606 res.extend(showlast)
2637 res.extend(showlast)
2607 print "Total number of aliases:",len(aliases)
2638 print "Total number of aliases:",len(aliases)
2608 return res
2639 return res
2609 try:
2640 try:
2610 alias,cmd = par.split(None,1)
2641 alias,cmd = par.split(None,1)
2611 except:
2642 except:
2612 print OInspect.getdoc(self.magic_alias)
2643 print OInspect.getdoc(self.magic_alias)
2613 else:
2644 else:
2614 nargs = cmd.count('%s')
2645 nargs = cmd.count('%s')
2615 if nargs>0 and cmd.find('%l')>=0:
2646 if nargs>0 and cmd.find('%l')>=0:
2616 error('The %s and %l specifiers are mutually exclusive '
2647 error('The %s and %l specifiers are mutually exclusive '
2617 'in alias definitions.')
2648 'in alias definitions.')
2618 else: # all looks OK
2649 else: # all looks OK
2619 self.shell.alias_table[alias] = (nargs,cmd)
2650 self.shell.alias_table[alias] = (nargs,cmd)
2620 self.shell.alias_table_validate(verbose=0)
2651 self.shell.alias_table_validate(verbose=0)
2621 # end magic_alias
2652 # end magic_alias
2622
2653
2623 def magic_unalias(self, parameter_s = ''):
2654 def magic_unalias(self, parameter_s = ''):
2624 """Remove an alias"""
2655 """Remove an alias"""
2625
2656
2626 aname = parameter_s.strip()
2657 aname = parameter_s.strip()
2627 if aname in self.shell.alias_table:
2658 if aname in self.shell.alias_table:
2628 del self.shell.alias_table[aname]
2659 del self.shell.alias_table[aname]
2629 stored = self.db.get('stored_aliases', {} )
2660 stored = self.db.get('stored_aliases', {} )
2630 if aname in stored:
2661 if aname in stored:
2631 print "Removing %stored alias",aname
2662 print "Removing %stored alias",aname
2632 del stored[aname]
2663 del stored[aname]
2633 self.db['stored_aliases'] = stored
2664 self.db['stored_aliases'] = stored
2634
2665
2635
2666
2636 def magic_rehashx(self, parameter_s = ''):
2667 def magic_rehashx(self, parameter_s = ''):
2637 """Update the alias table with all executable files in $PATH.
2668 """Update the alias table with all executable files in $PATH.
2638
2669
2639 This version explicitly checks that every entry in $PATH is a file
2670 This version explicitly checks that every entry in $PATH is a file
2640 with execute access (os.X_OK), so it is much slower than %rehash.
2671 with execute access (os.X_OK), so it is much slower than %rehash.
2641
2672
2642 Under Windows, it checks executability as a match agains a
2673 Under Windows, it checks executability as a match agains a
2643 '|'-separated string of extensions, stored in the IPython config
2674 '|'-separated string of extensions, stored in the IPython config
2644 variable win_exec_ext. This defaults to 'exe|com|bat'.
2675 variable win_exec_ext. This defaults to 'exe|com|bat'.
2645
2676
2646 This function also resets the root module cache of module completer,
2677 This function also resets the root module cache of module completer,
2647 used on slow filesystems.
2678 used on slow filesystems.
2648 """
2679 """
2649
2680
2650
2681
2651 ip = self.api
2682 ip = self.api
2652
2683
2653 # for the benefit of module completer in ipy_completers.py
2684 # for the benefit of module completer in ipy_completers.py
2654 del ip.db['rootmodules']
2685 del ip.db['rootmodules']
2655
2686
2656 path = [os.path.abspath(os.path.expanduser(p)) for p in
2687 path = [os.path.abspath(os.path.expanduser(p)) for p in
2657 os.environ.get('PATH','').split(os.pathsep)]
2688 os.environ.get('PATH','').split(os.pathsep)]
2658 path = filter(os.path.isdir,path)
2689 path = filter(os.path.isdir,path)
2659
2690
2660 alias_table = self.shell.alias_table
2691 alias_table = self.shell.alias_table
2661 syscmdlist = []
2692 syscmdlist = []
2662 if os.name == 'posix':
2693 if os.name == 'posix':
2663 isexec = lambda fname:os.path.isfile(fname) and \
2694 isexec = lambda fname:os.path.isfile(fname) and \
2664 os.access(fname,os.X_OK)
2695 os.access(fname,os.X_OK)
2665 else:
2696 else:
2666
2697
2667 try:
2698 try:
2668 winext = os.environ['pathext'].replace(';','|').replace('.','')
2699 winext = os.environ['pathext'].replace(';','|').replace('.','')
2669 except KeyError:
2700 except KeyError:
2670 winext = 'exe|com|bat|py'
2701 winext = 'exe|com|bat|py'
2671 if 'py' not in winext:
2702 if 'py' not in winext:
2672 winext += '|py'
2703 winext += '|py'
2673 execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
2704 execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
2674 isexec = lambda fname:os.path.isfile(fname) and execre.match(fname)
2705 isexec = lambda fname:os.path.isfile(fname) and execre.match(fname)
2675 savedir = os.getcwd()
2706 savedir = os.getcwd()
2676 try:
2707 try:
2677 # write the whole loop for posix/Windows so we don't have an if in
2708 # write the whole loop for posix/Windows so we don't have an if in
2678 # the innermost part
2709 # the innermost part
2679 if os.name == 'posix':
2710 if os.name == 'posix':
2680 for pdir in path:
2711 for pdir in path:
2681 os.chdir(pdir)
2712 os.chdir(pdir)
2682 for ff in os.listdir(pdir):
2713 for ff in os.listdir(pdir):
2683 if isexec(ff) and ff not in self.shell.no_alias:
2714 if isexec(ff) and ff not in self.shell.no_alias:
2684 # each entry in the alias table must be (N,name),
2715 # each entry in the alias table must be (N,name),
2685 # where N is the number of positional arguments of the
2716 # where N is the number of positional arguments of the
2686 # alias.
2717 # alias.
2687 # Dots will be removed from alias names, since ipython
2718 # Dots will be removed from alias names, since ipython
2688 # assumes names with dots to be python code
2719 # assumes names with dots to be python code
2689 alias_table[ff.replace('.','')] = (0,ff)
2720 alias_table[ff.replace('.','')] = (0,ff)
2690 syscmdlist.append(ff)
2721 syscmdlist.append(ff)
2691 else:
2722 else:
2692 for pdir in path:
2723 for pdir in path:
2693 os.chdir(pdir)
2724 os.chdir(pdir)
2694 for ff in os.listdir(pdir):
2725 for ff in os.listdir(pdir):
2695 base, ext = os.path.splitext(ff)
2726 base, ext = os.path.splitext(ff)
2696 if isexec(ff) and base.lower() not in self.shell.no_alias:
2727 if isexec(ff) and base.lower() not in self.shell.no_alias:
2697 if ext.lower() == '.exe':
2728 if ext.lower() == '.exe':
2698 ff = base
2729 ff = base
2699 alias_table[base.lower().replace('.','')] = (0,ff)
2730 alias_table[base.lower().replace('.','')] = (0,ff)
2700 syscmdlist.append(ff)
2731 syscmdlist.append(ff)
2701 # Make sure the alias table doesn't contain keywords or builtins
2732 # Make sure the alias table doesn't contain keywords or builtins
2702 self.shell.alias_table_validate()
2733 self.shell.alias_table_validate()
2703 # Call again init_auto_alias() so we get 'rm -i' and other
2734 # Call again init_auto_alias() so we get 'rm -i' and other
2704 # modified aliases since %rehashx will probably clobber them
2735 # modified aliases since %rehashx will probably clobber them
2705
2736
2706 # no, we don't want them. if %rehashx clobbers them, good,
2737 # no, we don't want them. if %rehashx clobbers them, good,
2707 # we'll probably get better versions
2738 # we'll probably get better versions
2708 # self.shell.init_auto_alias()
2739 # self.shell.init_auto_alias()
2709 db = ip.db
2740 db = ip.db
2710 db['syscmdlist'] = syscmdlist
2741 db['syscmdlist'] = syscmdlist
2711 finally:
2742 finally:
2712 os.chdir(savedir)
2743 os.chdir(savedir)
2713
2744
2714 def magic_pwd(self, parameter_s = ''):
2745 def magic_pwd(self, parameter_s = ''):
2715 """Return the current working directory path."""
2746 """Return the current working directory path."""
2716 return os.getcwd()
2747 return os.getcwd()
2717
2748
2718 def magic_cd(self, parameter_s=''):
2749 def magic_cd(self, parameter_s=''):
2719 """Change the current working directory.
2750 """Change the current working directory.
2720
2751
2721 This command automatically maintains an internal list of directories
2752 This command automatically maintains an internal list of directories
2722 you visit during your IPython session, in the variable _dh. The
2753 you visit during your IPython session, in the variable _dh. The
2723 command %dhist shows this history nicely formatted. You can also
2754 command %dhist shows this history nicely formatted. You can also
2724 do 'cd -<tab>' to see directory history conveniently.
2755 do 'cd -<tab>' to see directory history conveniently.
2725
2756
2726 Usage:
2757 Usage:
2727
2758
2728 cd 'dir': changes to directory 'dir'.
2759 cd 'dir': changes to directory 'dir'.
2729
2760
2730 cd -: changes to the last visited directory.
2761 cd -: changes to the last visited directory.
2731
2762
2732 cd -<n>: changes to the n-th directory in the directory history.
2763 cd -<n>: changes to the n-th directory in the directory history.
2733
2764
2734 cd --foo: change to directory that matches 'foo' in history
2765 cd --foo: change to directory that matches 'foo' in history
2735
2766
2736 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
2767 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
2737 (note: cd <bookmark_name> is enough if there is no
2768 (note: cd <bookmark_name> is enough if there is no
2738 directory <bookmark_name>, but a bookmark with the name exists.)
2769 directory <bookmark_name>, but a bookmark with the name exists.)
2739 'cd -b <tab>' allows you to tab-complete bookmark names.
2770 'cd -b <tab>' allows you to tab-complete bookmark names.
2740
2771
2741 Options:
2772 Options:
2742
2773
2743 -q: quiet. Do not print the working directory after the cd command is
2774 -q: quiet. Do not print the working directory after the cd command is
2744 executed. By default IPython's cd command does print this directory,
2775 executed. By default IPython's cd command does print this directory,
2745 since the default prompts do not display path information.
2776 since the default prompts do not display path information.
2746
2777
2747 Note that !cd doesn't work for this purpose because the shell where
2778 Note that !cd doesn't work for this purpose because the shell where
2748 !command runs is immediately discarded after executing 'command'."""
2779 !command runs is immediately discarded after executing 'command'."""
2749
2780
2750 parameter_s = parameter_s.strip()
2781 parameter_s = parameter_s.strip()
2751 #bkms = self.shell.persist.get("bookmarks",{})
2782 #bkms = self.shell.persist.get("bookmarks",{})
2752
2783
2753 oldcwd = os.getcwd()
2784 oldcwd = os.getcwd()
2754 numcd = re.match(r'(-)(\d+)$',parameter_s)
2785 numcd = re.match(r'(-)(\d+)$',parameter_s)
2755 # jump in directory history by number
2786 # jump in directory history by number
2756 if numcd:
2787 if numcd:
2757 nn = int(numcd.group(2))
2788 nn = int(numcd.group(2))
2758 try:
2789 try:
2759 ps = self.shell.user_ns['_dh'][nn]
2790 ps = self.shell.user_ns['_dh'][nn]
2760 except IndexError:
2791 except IndexError:
2761 print 'The requested directory does not exist in history.'
2792 print 'The requested directory does not exist in history.'
2762 return
2793 return
2763 else:
2794 else:
2764 opts = {}
2795 opts = {}
2765 elif parameter_s.startswith('--'):
2796 elif parameter_s.startswith('--'):
2766 ps = None
2797 ps = None
2767 fallback = None
2798 fallback = None
2768 pat = parameter_s[2:]
2799 pat = parameter_s[2:]
2769 dh = self.shell.user_ns['_dh']
2800 dh = self.shell.user_ns['_dh']
2770 # first search only by basename (last component)
2801 # first search only by basename (last component)
2771 for ent in reversed(dh):
2802 for ent in reversed(dh):
2772 if pat in os.path.basename(ent) and os.path.isdir(ent):
2803 if pat in os.path.basename(ent) and os.path.isdir(ent):
2773 ps = ent
2804 ps = ent
2774 break
2805 break
2775
2806
2776 if fallback is None and pat in ent and os.path.isdir(ent):
2807 if fallback is None and pat in ent and os.path.isdir(ent):
2777 fallback = ent
2808 fallback = ent
2778
2809
2779 # if we have no last part match, pick the first full path match
2810 # if we have no last part match, pick the first full path match
2780 if ps is None:
2811 if ps is None:
2781 ps = fallback
2812 ps = fallback
2782
2813
2783 if ps is None:
2814 if ps is None:
2784 print "No matching entry in directory history"
2815 print "No matching entry in directory history"
2785 return
2816 return
2786 else:
2817 else:
2787 opts = {}
2818 opts = {}
2788
2819
2789
2820
2790 else:
2821 else:
2791 #turn all non-space-escaping backslashes to slashes,
2822 #turn all non-space-escaping backslashes to slashes,
2792 # for c:\windows\directory\names\
2823 # for c:\windows\directory\names\
2793 parameter_s = re.sub(r'\\(?! )','/', parameter_s)
2824 parameter_s = re.sub(r'\\(?! )','/', parameter_s)
2794 opts,ps = self.parse_options(parameter_s,'qb',mode='string')
2825 opts,ps = self.parse_options(parameter_s,'qb',mode='string')
2795 # jump to previous
2826 # jump to previous
2796 if ps == '-':
2827 if ps == '-':
2797 try:
2828 try:
2798 ps = self.shell.user_ns['_dh'][-2]
2829 ps = self.shell.user_ns['_dh'][-2]
2799 except IndexError:
2830 except IndexError:
2800 raise UsageError('%cd -: No previous directory to change to.')
2831 raise UsageError('%cd -: No previous directory to change to.')
2801 # jump to bookmark if needed
2832 # jump to bookmark if needed
2802 else:
2833 else:
2803 if not os.path.isdir(ps) or opts.has_key('b'):
2834 if not os.path.isdir(ps) or opts.has_key('b'):
2804 bkms = self.db.get('bookmarks', {})
2835 bkms = self.db.get('bookmarks', {})
2805
2836
2806 if bkms.has_key(ps):
2837 if bkms.has_key(ps):
2807 target = bkms[ps]
2838 target = bkms[ps]
2808 print '(bookmark:%s) -> %s' % (ps,target)
2839 print '(bookmark:%s) -> %s' % (ps,target)
2809 ps = target
2840 ps = target
2810 else:
2841 else:
2811 if opts.has_key('b'):
2842 if opts.has_key('b'):
2812 raise UsageError("Bookmark '%s' not found. "
2843 raise UsageError("Bookmark '%s' not found. "
2813 "Use '%%bookmark -l' to see your bookmarks." % ps)
2844 "Use '%%bookmark -l' to see your bookmarks." % ps)
2814
2845
2815 # at this point ps should point to the target dir
2846 # at this point ps should point to the target dir
2816 if ps:
2847 if ps:
2817 try:
2848 try:
2818 os.chdir(os.path.expanduser(ps))
2849 os.chdir(os.path.expanduser(ps))
2819 if self.shell.rc.term_title:
2850 if self.shell.rc.term_title:
2820 #print 'set term title:',self.shell.rc.term_title # dbg
2851 #print 'set term title:',self.shell.rc.term_title # dbg
2821 platutils.set_term_title('IPy ' + abbrev_cwd())
2852 platutils.set_term_title('IPy ' + abbrev_cwd())
2822 except OSError:
2853 except OSError:
2823 print sys.exc_info()[1]
2854 print sys.exc_info()[1]
2824 else:
2855 else:
2825 cwd = os.getcwd()
2856 cwd = os.getcwd()
2826 dhist = self.shell.user_ns['_dh']
2857 dhist = self.shell.user_ns['_dh']
2827 if oldcwd != cwd:
2858 if oldcwd != cwd:
2828 dhist.append(cwd)
2859 dhist.append(cwd)
2829 self.db['dhist'] = compress_dhist(dhist)[-100:]
2860 self.db['dhist'] = compress_dhist(dhist)[-100:]
2830
2861
2831 else:
2862 else:
2832 os.chdir(self.shell.home_dir)
2863 os.chdir(self.shell.home_dir)
2833 if self.shell.rc.term_title:
2864 if self.shell.rc.term_title:
2834 platutils.set_term_title("IPy ~")
2865 platutils.set_term_title("IPy ~")
2835 cwd = os.getcwd()
2866 cwd = os.getcwd()
2836 dhist = self.shell.user_ns['_dh']
2867 dhist = self.shell.user_ns['_dh']
2837
2868
2838 if oldcwd != cwd:
2869 if oldcwd != cwd:
2839 dhist.append(cwd)
2870 dhist.append(cwd)
2840 self.db['dhist'] = compress_dhist(dhist)[-100:]
2871 self.db['dhist'] = compress_dhist(dhist)[-100:]
2841 if not 'q' in opts and self.shell.user_ns['_dh']:
2872 if not 'q' in opts and self.shell.user_ns['_dh']:
2842 print self.shell.user_ns['_dh'][-1]
2873 print self.shell.user_ns['_dh'][-1]
2843
2874
2844
2875
2845 def magic_env(self, parameter_s=''):
2876 def magic_env(self, parameter_s=''):
2846 """List environment variables."""
2877 """List environment variables."""
2847
2878
2848 return os.environ.data
2879 return os.environ.data
2849
2880
2850 def magic_pushd(self, parameter_s=''):
2881 def magic_pushd(self, parameter_s=''):
2851 """Place the current dir on stack and change directory.
2882 """Place the current dir on stack and change directory.
2852
2883
2853 Usage:\\
2884 Usage:\\
2854 %pushd ['dirname']
2885 %pushd ['dirname']
2855 """
2886 """
2856
2887
2857 dir_s = self.shell.dir_stack
2888 dir_s = self.shell.dir_stack
2858 tgt = os.path.expanduser(parameter_s)
2889 tgt = os.path.expanduser(parameter_s)
2859 cwd = os.getcwd().replace(self.home_dir,'~')
2890 cwd = os.getcwd().replace(self.home_dir,'~')
2860 if tgt:
2891 if tgt:
2861 self.magic_cd(parameter_s)
2892 self.magic_cd(parameter_s)
2862 dir_s.insert(0,cwd)
2893 dir_s.insert(0,cwd)
2863 return self.magic_dirs()
2894 return self.magic_dirs()
2864
2895
2865 def magic_popd(self, parameter_s=''):
2896 def magic_popd(self, parameter_s=''):
2866 """Change to directory popped off the top of the stack.
2897 """Change to directory popped off the top of the stack.
2867 """
2898 """
2868 if not self.shell.dir_stack:
2899 if not self.shell.dir_stack:
2869 raise UsageError("%popd on empty stack")
2900 raise UsageError("%popd on empty stack")
2870 top = self.shell.dir_stack.pop(0)
2901 top = self.shell.dir_stack.pop(0)
2871 self.magic_cd(top)
2902 self.magic_cd(top)
2872 print "popd ->",top
2903 print "popd ->",top
2873
2904
2874 def magic_dirs(self, parameter_s=''):
2905 def magic_dirs(self, parameter_s=''):
2875 """Return the current directory stack."""
2906 """Return the current directory stack."""
2876
2907
2877 return self.shell.dir_stack
2908 return self.shell.dir_stack
2878
2909
2879 def magic_dhist(self, parameter_s=''):
2910 def magic_dhist(self, parameter_s=''):
2880 """Print your history of visited directories.
2911 """Print your history of visited directories.
2881
2912
2882 %dhist -> print full history\\
2913 %dhist -> print full history\\
2883 %dhist n -> print last n entries only\\
2914 %dhist n -> print last n entries only\\
2884 %dhist n1 n2 -> print entries between n1 and n2 (n1 not included)\\
2915 %dhist n1 n2 -> print entries between n1 and n2 (n1 not included)\\
2885
2916
2886 This history is automatically maintained by the %cd command, and
2917 This history is automatically maintained by the %cd command, and
2887 always available as the global list variable _dh. You can use %cd -<n>
2918 always available as the global list variable _dh. You can use %cd -<n>
2888 to go to directory number <n>.
2919 to go to directory number <n>.
2889
2920
2890 Note that most of time, you should view directory history by entering
2921 Note that most of time, you should view directory history by entering
2891 cd -<TAB>.
2922 cd -<TAB>.
2892
2923
2893 """
2924 """
2894
2925
2895 dh = self.shell.user_ns['_dh']
2926 dh = self.shell.user_ns['_dh']
2896 if parameter_s:
2927 if parameter_s:
2897 try:
2928 try:
2898 args = map(int,parameter_s.split())
2929 args = map(int,parameter_s.split())
2899 except:
2930 except:
2900 self.arg_err(Magic.magic_dhist)
2931 self.arg_err(Magic.magic_dhist)
2901 return
2932 return
2902 if len(args) == 1:
2933 if len(args) == 1:
2903 ini,fin = max(len(dh)-(args[0]),0),len(dh)
2934 ini,fin = max(len(dh)-(args[0]),0),len(dh)
2904 elif len(args) == 2:
2935 elif len(args) == 2:
2905 ini,fin = args
2936 ini,fin = args
2906 else:
2937 else:
2907 self.arg_err(Magic.magic_dhist)
2938 self.arg_err(Magic.magic_dhist)
2908 return
2939 return
2909 else:
2940 else:
2910 ini,fin = 0,len(dh)
2941 ini,fin = 0,len(dh)
2911 nlprint(dh,
2942 nlprint(dh,
2912 header = 'Directory history (kept in _dh)',
2943 header = 'Directory history (kept in _dh)',
2913 start=ini,stop=fin)
2944 start=ini,stop=fin)
2914
2945
2915 @testdec.skip_doctest
2946 @testdec.skip_doctest
2916 def magic_sc(self, parameter_s=''):
2947 def magic_sc(self, parameter_s=''):
2917 """Shell capture - execute a shell command and capture its output.
2948 """Shell capture - execute a shell command and capture its output.
2918
2949
2919 DEPRECATED. Suboptimal, retained for backwards compatibility.
2950 DEPRECATED. Suboptimal, retained for backwards compatibility.
2920
2951
2921 You should use the form 'var = !command' instead. Example:
2952 You should use the form 'var = !command' instead. Example:
2922
2953
2923 "%sc -l myfiles = ls ~" should now be written as
2954 "%sc -l myfiles = ls ~" should now be written as
2924
2955
2925 "myfiles = !ls ~"
2956 "myfiles = !ls ~"
2926
2957
2927 myfiles.s, myfiles.l and myfiles.n still apply as documented
2958 myfiles.s, myfiles.l and myfiles.n still apply as documented
2928 below.
2959 below.
2929
2960
2930 --
2961 --
2931 %sc [options] varname=command
2962 %sc [options] varname=command
2932
2963
2933 IPython will run the given command using commands.getoutput(), and
2964 IPython will run the given command using commands.getoutput(), and
2934 will then update the user's interactive namespace with a variable
2965 will then update the user's interactive namespace with a variable
2935 called varname, containing the value of the call. Your command can
2966 called varname, containing the value of the call. Your command can
2936 contain shell wildcards, pipes, etc.
2967 contain shell wildcards, pipes, etc.
2937
2968
2938 The '=' sign in the syntax is mandatory, and the variable name you
2969 The '=' sign in the syntax is mandatory, and the variable name you
2939 supply must follow Python's standard conventions for valid names.
2970 supply must follow Python's standard conventions for valid names.
2940
2971
2941 (A special format without variable name exists for internal use)
2972 (A special format without variable name exists for internal use)
2942
2973
2943 Options:
2974 Options:
2944
2975
2945 -l: list output. Split the output on newlines into a list before
2976 -l: list output. Split the output on newlines into a list before
2946 assigning it to the given variable. By default the output is stored
2977 assigning it to the given variable. By default the output is stored
2947 as a single string.
2978 as a single string.
2948
2979
2949 -v: verbose. Print the contents of the variable.
2980 -v: verbose. Print the contents of the variable.
2950
2981
2951 In most cases you should not need to split as a list, because the
2982 In most cases you should not need to split as a list, because the
2952 returned value is a special type of string which can automatically
2983 returned value is a special type of string which can automatically
2953 provide its contents either as a list (split on newlines) or as a
2984 provide its contents either as a list (split on newlines) or as a
2954 space-separated string. These are convenient, respectively, either
2985 space-separated string. These are convenient, respectively, either
2955 for sequential processing or to be passed to a shell command.
2986 for sequential processing or to be passed to a shell command.
2956
2987
2957 For example:
2988 For example:
2958
2989
2959 # all-random
2990 # all-random
2960
2991
2961 # Capture into variable a
2992 # Capture into variable a
2962 In [1]: sc a=ls *py
2993 In [1]: sc a=ls *py
2963
2994
2964 # a is a string with embedded newlines
2995 # a is a string with embedded newlines
2965 In [2]: a
2996 In [2]: a
2966 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
2997 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
2967
2998
2968 # which can be seen as a list:
2999 # which can be seen as a list:
2969 In [3]: a.l
3000 In [3]: a.l
2970 Out[3]: ['setup.py', 'win32_manual_post_install.py']
3001 Out[3]: ['setup.py', 'win32_manual_post_install.py']
2971
3002
2972 # or as a whitespace-separated string:
3003 # or as a whitespace-separated string:
2973 In [4]: a.s
3004 In [4]: a.s
2974 Out[4]: 'setup.py win32_manual_post_install.py'
3005 Out[4]: 'setup.py win32_manual_post_install.py'
2975
3006
2976 # a.s is useful to pass as a single command line:
3007 # a.s is useful to pass as a single command line:
2977 In [5]: !wc -l $a.s
3008 In [5]: !wc -l $a.s
2978 146 setup.py
3009 146 setup.py
2979 130 win32_manual_post_install.py
3010 130 win32_manual_post_install.py
2980 276 total
3011 276 total
2981
3012
2982 # while the list form is useful to loop over:
3013 # while the list form is useful to loop over:
2983 In [6]: for f in a.l:
3014 In [6]: for f in a.l:
2984 ...: !wc -l $f
3015 ...: !wc -l $f
2985 ...:
3016 ...:
2986 146 setup.py
3017 146 setup.py
2987 130 win32_manual_post_install.py
3018 130 win32_manual_post_install.py
2988
3019
2989 Similiarly, the lists returned by the -l option are also special, in
3020 Similiarly, the lists returned by the -l option are also special, in
2990 the sense that you can equally invoke the .s attribute on them to
3021 the sense that you can equally invoke the .s attribute on them to
2991 automatically get a whitespace-separated string from their contents:
3022 automatically get a whitespace-separated string from their contents:
2992
3023
2993 In [7]: sc -l b=ls *py
3024 In [7]: sc -l b=ls *py
2994
3025
2995 In [8]: b
3026 In [8]: b
2996 Out[8]: ['setup.py', 'win32_manual_post_install.py']
3027 Out[8]: ['setup.py', 'win32_manual_post_install.py']
2997
3028
2998 In [9]: b.s
3029 In [9]: b.s
2999 Out[9]: 'setup.py win32_manual_post_install.py'
3030 Out[9]: 'setup.py win32_manual_post_install.py'
3000
3031
3001 In summary, both the lists and strings used for ouptut capture have
3032 In summary, both the lists and strings used for ouptut capture have
3002 the following special attributes:
3033 the following special attributes:
3003
3034
3004 .l (or .list) : value as list.
3035 .l (or .list) : value as list.
3005 .n (or .nlstr): value as newline-separated string.
3036 .n (or .nlstr): value as newline-separated string.
3006 .s (or .spstr): value as space-separated string.
3037 .s (or .spstr): value as space-separated string.
3007 """
3038 """
3008
3039
3009 opts,args = self.parse_options(parameter_s,'lv')
3040 opts,args = self.parse_options(parameter_s,'lv')
3010 # Try to get a variable name and command to run
3041 # Try to get a variable name and command to run
3011 try:
3042 try:
3012 # the variable name must be obtained from the parse_options
3043 # the variable name must be obtained from the parse_options
3013 # output, which uses shlex.split to strip options out.
3044 # output, which uses shlex.split to strip options out.
3014 var,_ = args.split('=',1)
3045 var,_ = args.split('=',1)
3015 var = var.strip()
3046 var = var.strip()
3016 # But the the command has to be extracted from the original input
3047 # But the the command has to be extracted from the original input
3017 # parameter_s, not on what parse_options returns, to avoid the
3048 # parameter_s, not on what parse_options returns, to avoid the
3018 # quote stripping which shlex.split performs on it.
3049 # quote stripping which shlex.split performs on it.
3019 _,cmd = parameter_s.split('=',1)
3050 _,cmd = parameter_s.split('=',1)
3020 except ValueError:
3051 except ValueError:
3021 var,cmd = '',''
3052 var,cmd = '',''
3022 # If all looks ok, proceed
3053 # If all looks ok, proceed
3023 out,err = self.shell.getoutputerror(cmd)
3054 out,err = self.shell.getoutputerror(cmd)
3024 if err:
3055 if err:
3025 print >> Term.cerr,err
3056 print >> Term.cerr,err
3026 if opts.has_key('l'):
3057 if opts.has_key('l'):
3027 out = SList(out.split('\n'))
3058 out = SList(out.split('\n'))
3028 else:
3059 else:
3029 out = LSString(out)
3060 out = LSString(out)
3030 if opts.has_key('v'):
3061 if opts.has_key('v'):
3031 print '%s ==\n%s' % (var,pformat(out))
3062 print '%s ==\n%s' % (var,pformat(out))
3032 if var:
3063 if var:
3033 self.shell.user_ns.update({var:out})
3064 self.shell.user_ns.update({var:out})
3034 else:
3065 else:
3035 return out
3066 return out
3036
3067
3037 def magic_sx(self, parameter_s=''):
3068 def magic_sx(self, parameter_s=''):
3038 """Shell execute - run a shell command and capture its output.
3069 """Shell execute - run a shell command and capture its output.
3039
3070
3040 %sx command
3071 %sx command
3041
3072
3042 IPython will run the given command using commands.getoutput(), and
3073 IPython will run the given command using commands.getoutput(), and
3043 return the result formatted as a list (split on '\\n'). Since the
3074 return the result formatted as a list (split on '\\n'). Since the
3044 output is _returned_, it will be stored in ipython's regular output
3075 output is _returned_, it will be stored in ipython's regular output
3045 cache Out[N] and in the '_N' automatic variables.
3076 cache Out[N] and in the '_N' automatic variables.
3046
3077
3047 Notes:
3078 Notes:
3048
3079
3049 1) If an input line begins with '!!', then %sx is automatically
3080 1) If an input line begins with '!!', then %sx is automatically
3050 invoked. That is, while:
3081 invoked. That is, while:
3051 !ls
3082 !ls
3052 causes ipython to simply issue system('ls'), typing
3083 causes ipython to simply issue system('ls'), typing
3053 !!ls
3084 !!ls
3054 is a shorthand equivalent to:
3085 is a shorthand equivalent to:
3055 %sx ls
3086 %sx ls
3056
3087
3057 2) %sx differs from %sc in that %sx automatically splits into a list,
3088 2) %sx differs from %sc in that %sx automatically splits into a list,
3058 like '%sc -l'. The reason for this is to make it as easy as possible
3089 like '%sc -l'. The reason for this is to make it as easy as possible
3059 to process line-oriented shell output via further python commands.
3090 to process line-oriented shell output via further python commands.
3060 %sc is meant to provide much finer control, but requires more
3091 %sc is meant to provide much finer control, but requires more
3061 typing.
3092 typing.
3062
3093
3063 3) Just like %sc -l, this is a list with special attributes:
3094 3) Just like %sc -l, this is a list with special attributes:
3064
3095
3065 .l (or .list) : value as list.
3096 .l (or .list) : value as list.
3066 .n (or .nlstr): value as newline-separated string.
3097 .n (or .nlstr): value as newline-separated string.
3067 .s (or .spstr): value as whitespace-separated string.
3098 .s (or .spstr): value as whitespace-separated string.
3068
3099
3069 This is very useful when trying to use such lists as arguments to
3100 This is very useful when trying to use such lists as arguments to
3070 system commands."""
3101 system commands."""
3071
3102
3072 if parameter_s:
3103 if parameter_s:
3073 out,err = self.shell.getoutputerror(parameter_s)
3104 out,err = self.shell.getoutputerror(parameter_s)
3074 if err:
3105 if err:
3075 print >> Term.cerr,err
3106 print >> Term.cerr,err
3076 return SList(out.split('\n'))
3107 return SList(out.split('\n'))
3077
3108
3078 def magic_bg(self, parameter_s=''):
3109 def magic_bg(self, parameter_s=''):
3079 """Run a job in the background, in a separate thread.
3110 """Run a job in the background, in a separate thread.
3080
3111
3081 For example,
3112 For example,
3082
3113
3083 %bg myfunc(x,y,z=1)
3114 %bg myfunc(x,y,z=1)
3084
3115
3085 will execute 'myfunc(x,y,z=1)' in a background thread. As soon as the
3116 will execute 'myfunc(x,y,z=1)' in a background thread. As soon as the
3086 execution starts, a message will be printed indicating the job
3117 execution starts, a message will be printed indicating the job
3087 number. If your job number is 5, you can use
3118 number. If your job number is 5, you can use
3088
3119
3089 myvar = jobs.result(5) or myvar = jobs[5].result
3120 myvar = jobs.result(5) or myvar = jobs[5].result
3090
3121
3091 to assign this result to variable 'myvar'.
3122 to assign this result to variable 'myvar'.
3092
3123
3093 IPython has a job manager, accessible via the 'jobs' object. You can
3124 IPython has a job manager, accessible via the 'jobs' object. You can
3094 type jobs? to get more information about it, and use jobs.<TAB> to see
3125 type jobs? to get more information about it, and use jobs.<TAB> to see
3095 its attributes. All attributes not starting with an underscore are
3126 its attributes. All attributes not starting with an underscore are
3096 meant for public use.
3127 meant for public use.
3097
3128
3098 In particular, look at the jobs.new() method, which is used to create
3129 In particular, look at the jobs.new() method, which is used to create
3099 new jobs. This magic %bg function is just a convenience wrapper
3130 new jobs. This magic %bg function is just a convenience wrapper
3100 around jobs.new(), for expression-based jobs. If you want to create a
3131 around jobs.new(), for expression-based jobs. If you want to create a
3101 new job with an explicit function object and arguments, you must call
3132 new job with an explicit function object and arguments, you must call
3102 jobs.new() directly.
3133 jobs.new() directly.
3103
3134
3104 The jobs.new docstring also describes in detail several important
3135 The jobs.new docstring also describes in detail several important
3105 caveats associated with a thread-based model for background job
3136 caveats associated with a thread-based model for background job
3106 execution. Type jobs.new? for details.
3137 execution. Type jobs.new? for details.
3107
3138
3108 You can check the status of all jobs with jobs.status().
3139 You can check the status of all jobs with jobs.status().
3109
3140
3110 The jobs variable is set by IPython into the Python builtin namespace.
3141 The jobs variable is set by IPython into the Python builtin namespace.
3111 If you ever declare a variable named 'jobs', you will shadow this
3142 If you ever declare a variable named 'jobs', you will shadow this
3112 name. You can either delete your global jobs variable to regain
3143 name. You can either delete your global jobs variable to regain
3113 access to the job manager, or make a new name and assign it manually
3144 access to the job manager, or make a new name and assign it manually
3114 to the manager (stored in IPython's namespace). For example, to
3145 to the manager (stored in IPython's namespace). For example, to
3115 assign the job manager to the Jobs name, use:
3146 assign the job manager to the Jobs name, use:
3116
3147
3117 Jobs = __builtins__.jobs"""
3148 Jobs = __builtins__.jobs"""
3118
3149
3119 self.shell.jobs.new(parameter_s,self.shell.user_ns)
3150 self.shell.jobs.new(parameter_s,self.shell.user_ns)
3120
3151
3121 def magic_r(self, parameter_s=''):
3152 def magic_r(self, parameter_s=''):
3122 """Repeat previous input.
3153 """Repeat previous input.
3123
3154
3124 Note: Consider using the more powerfull %rep instead!
3155 Note: Consider using the more powerfull %rep instead!
3125
3156
3126 If given an argument, repeats the previous command which starts with
3157 If given an argument, repeats the previous command which starts with
3127 the same string, otherwise it just repeats the previous input.
3158 the same string, otherwise it just repeats the previous input.
3128
3159
3129 Shell escaped commands (with ! as first character) are not recognized
3160 Shell escaped commands (with ! as first character) are not recognized
3130 by this system, only pure python code and magic commands.
3161 by this system, only pure python code and magic commands.
3131 """
3162 """
3132
3163
3133 start = parameter_s.strip()
3164 start = parameter_s.strip()
3134 esc_magic = self.shell.ESC_MAGIC
3165 esc_magic = self.shell.ESC_MAGIC
3135 # Identify magic commands even if automagic is on (which means
3166 # Identify magic commands even if automagic is on (which means
3136 # the in-memory version is different from that typed by the user).
3167 # the in-memory version is different from that typed by the user).
3137 if self.shell.rc.automagic:
3168 if self.shell.rc.automagic:
3138 start_magic = esc_magic+start
3169 start_magic = esc_magic+start
3139 else:
3170 else:
3140 start_magic = start
3171 start_magic = start
3141 # Look through the input history in reverse
3172 # Look through the input history in reverse
3142 for n in range(len(self.shell.input_hist)-2,0,-1):
3173 for n in range(len(self.shell.input_hist)-2,0,-1):
3143 input = self.shell.input_hist[n]
3174 input = self.shell.input_hist[n]
3144 # skip plain 'r' lines so we don't recurse to infinity
3175 # skip plain 'r' lines so we don't recurse to infinity
3145 if input != '_ip.magic("r")\n' and \
3176 if input != '_ip.magic("r")\n' and \
3146 (input.startswith(start) or input.startswith(start_magic)):
3177 (input.startswith(start) or input.startswith(start_magic)):
3147 #print 'match',`input` # dbg
3178 #print 'match',`input` # dbg
3148 print 'Executing:',input,
3179 print 'Executing:',input,
3149 self.shell.runlines(input)
3180 self.shell.runlines(input)
3150 return
3181 return
3151 print 'No previous input matching `%s` found.' % start
3182 print 'No previous input matching `%s` found.' % start
3152
3183
3153
3184
3154 def magic_bookmark(self, parameter_s=''):
3185 def magic_bookmark(self, parameter_s=''):
3155 """Manage IPython's bookmark system.
3186 """Manage IPython's bookmark system.
3156
3187
3157 %bookmark <name> - set bookmark to current dir
3188 %bookmark <name> - set bookmark to current dir
3158 %bookmark <name> <dir> - set bookmark to <dir>
3189 %bookmark <name> <dir> - set bookmark to <dir>
3159 %bookmark -l - list all bookmarks
3190 %bookmark -l - list all bookmarks
3160 %bookmark -d <name> - remove bookmark
3191 %bookmark -d <name> - remove bookmark
3161 %bookmark -r - remove all bookmarks
3192 %bookmark -r - remove all bookmarks
3162
3193
3163 You can later on access a bookmarked folder with:
3194 You can later on access a bookmarked folder with:
3164 %cd -b <name>
3195 %cd -b <name>
3165 or simply '%cd <name>' if there is no directory called <name> AND
3196 or simply '%cd <name>' if there is no directory called <name> AND
3166 there is such a bookmark defined.
3197 there is such a bookmark defined.
3167
3198
3168 Your bookmarks persist through IPython sessions, but they are
3199 Your bookmarks persist through IPython sessions, but they are
3169 associated with each profile."""
3200 associated with each profile."""
3170
3201
3171 opts,args = self.parse_options(parameter_s,'drl',mode='list')
3202 opts,args = self.parse_options(parameter_s,'drl',mode='list')
3172 if len(args) > 2:
3203 if len(args) > 2:
3173 raise UsageError("%bookmark: too many arguments")
3204 raise UsageError("%bookmark: too many arguments")
3174
3205
3175 bkms = self.db.get('bookmarks',{})
3206 bkms = self.db.get('bookmarks',{})
3176
3207
3177 if opts.has_key('d'):
3208 if opts.has_key('d'):
3178 try:
3209 try:
3179 todel = args[0]
3210 todel = args[0]
3180 except IndexError:
3211 except IndexError:
3181 raise UsageError(
3212 raise UsageError(
3182 "%bookmark -d: must provide a bookmark to delete")
3213 "%bookmark -d: must provide a bookmark to delete")
3183 else:
3214 else:
3184 try:
3215 try:
3185 del bkms[todel]
3216 del bkms[todel]
3186 except KeyError:
3217 except KeyError:
3187 raise UsageError(
3218 raise UsageError(
3188 "%%bookmark -d: Can't delete bookmark '%s'" % todel)
3219 "%%bookmark -d: Can't delete bookmark '%s'" % todel)
3189
3220
3190 elif opts.has_key('r'):
3221 elif opts.has_key('r'):
3191 bkms = {}
3222 bkms = {}
3192 elif opts.has_key('l'):
3223 elif opts.has_key('l'):
3193 bks = bkms.keys()
3224 bks = bkms.keys()
3194 bks.sort()
3225 bks.sort()
3195 if bks:
3226 if bks:
3196 size = max(map(len,bks))
3227 size = max(map(len,bks))
3197 else:
3228 else:
3198 size = 0
3229 size = 0
3199 fmt = '%-'+str(size)+'s -> %s'
3230 fmt = '%-'+str(size)+'s -> %s'
3200 print 'Current bookmarks:'
3231 print 'Current bookmarks:'
3201 for bk in bks:
3232 for bk in bks:
3202 print fmt % (bk,bkms[bk])
3233 print fmt % (bk,bkms[bk])
3203 else:
3234 else:
3204 if not args:
3235 if not args:
3205 raise UsageError("%bookmark: You must specify the bookmark name")
3236 raise UsageError("%bookmark: You must specify the bookmark name")
3206 elif len(args)==1:
3237 elif len(args)==1:
3207 bkms[args[0]] = os.getcwd()
3238 bkms[args[0]] = os.getcwd()
3208 elif len(args)==2:
3239 elif len(args)==2:
3209 bkms[args[0]] = args[1]
3240 bkms[args[0]] = args[1]
3210 self.db['bookmarks'] = bkms
3241 self.db['bookmarks'] = bkms
3211
3242
3212 def magic_pycat(self, parameter_s=''):
3243 def magic_pycat(self, parameter_s=''):
3213 """Show a syntax-highlighted file through a pager.
3244 """Show a syntax-highlighted file through a pager.
3214
3245
3215 This magic is similar to the cat utility, but it will assume the file
3246 This magic is similar to the cat utility, but it will assume the file
3216 to be Python source and will show it with syntax highlighting. """
3247 to be Python source and will show it with syntax highlighting. """
3217
3248
3218 try:
3249 try:
3219 filename = get_py_filename(parameter_s)
3250 filename = get_py_filename(parameter_s)
3220 cont = file_read(filename)
3251 cont = file_read(filename)
3221 except IOError:
3252 except IOError:
3222 try:
3253 try:
3223 cont = eval(parameter_s,self.user_ns)
3254 cont = eval(parameter_s,self.user_ns)
3224 except NameError:
3255 except NameError:
3225 cont = None
3256 cont = None
3226 if cont is None:
3257 if cont is None:
3227 print "Error: no such file or variable"
3258 print "Error: no such file or variable"
3228 return
3259 return
3229
3260
3230 page(self.shell.pycolorize(cont),
3261 page(self.shell.pycolorize(cont),
3231 screen_lines=self.shell.rc.screen_length)
3262 screen_lines=self.shell.rc.screen_length)
3232
3263
3233 def magic_cpaste(self, parameter_s=''):
3264 def magic_cpaste(self, parameter_s=''):
3234 """Allows you to paste & execute a pre-formatted code block from clipboard.
3265 """Allows you to paste & execute a pre-formatted code block from clipboard.
3235
3266
3236 You must terminate the block with '--' (two minus-signs) alone on the
3267 You must terminate the block with '--' (two minus-signs) alone on the
3237 line. You can also provide your own sentinel with '%paste -s %%' ('%%'
3268 line. You can also provide your own sentinel with '%paste -s %%' ('%%'
3238 is the new sentinel for this operation)
3269 is the new sentinel for this operation)
3239
3270
3240 The block is dedented prior to execution to enable execution of method
3271 The block is dedented prior to execution to enable execution of method
3241 definitions. '>' and '+' characters at the beginning of a line are
3272 definitions. '>' and '+' characters at the beginning of a line are
3242 ignored, to allow pasting directly from e-mails, diff files and
3273 ignored, to allow pasting directly from e-mails, diff files and
3243 doctests (the '...' continuation prompt is also stripped). The
3274 doctests (the '...' continuation prompt is also stripped). The
3244 executed block is also assigned to variable named 'pasted_block' for
3275 executed block is also assigned to variable named 'pasted_block' for
3245 later editing with '%edit pasted_block'.
3276 later editing with '%edit pasted_block'.
3246
3277
3247 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
3278 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
3248 This assigns the pasted block to variable 'foo' as string, without
3279 This assigns the pasted block to variable 'foo' as string, without
3249 dedenting or executing it (preceding >>> and + is still stripped)
3280 dedenting or executing it (preceding >>> and + is still stripped)
3250
3281
3251 '%cpaste -r' re-executes the block previously entered by cpaste.
3282 '%cpaste -r' re-executes the block previously entered by cpaste.
3252
3283
3253 Do not be alarmed by garbled output on Windows (it's a readline bug).
3284 Do not be alarmed by garbled output on Windows (it's a readline bug).
3254 Just press enter and type -- (and press enter again) and the block
3285 Just press enter and type -- (and press enter again) and the block
3255 will be what was just pasted.
3286 will be what was just pasted.
3256
3287
3257 IPython statements (magics, shell escapes) are not supported (yet).
3288 IPython statements (magics, shell escapes) are not supported (yet).
3258 """
3289 """
3259 opts,args = self.parse_options(parameter_s,'rs:',mode='string')
3290 opts,args = self.parse_options(parameter_s,'rs:',mode='string')
3260 par = args.strip()
3291 par = args.strip()
3261 if opts.has_key('r'):
3292 if opts.has_key('r'):
3262 b = self.user_ns.get('pasted_block', None)
3293 b = self.user_ns.get('pasted_block', None)
3263 if b is None:
3294 if b is None:
3264 raise UsageError('No previous pasted block available')
3295 raise UsageError('No previous pasted block available')
3265 print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))
3296 print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))
3266 exec b in self.user_ns
3297 exec b in self.user_ns
3267 return
3298 return
3268
3299
3269 sentinel = opts.get('s','--')
3300 sentinel = opts.get('s','--')
3270
3301
3271 # Regular expressions that declare text we strip from the input:
3302 # Regular expressions that declare text we strip from the input:
3272 strip_re = [r'^\s*In \[\d+\]:', # IPython input prompt
3303 strip_re = [r'^\s*In \[\d+\]:', # IPython input prompt
3273 r'^\s*(\s?>)+', # Python input prompt
3304 r'^\s*(\s?>)+', # Python input prompt
3274 r'^\s*\.{3,}', # Continuation prompts
3305 r'^\s*\.{3,}', # Continuation prompts
3275 r'^\++',
3306 r'^\++',
3276 ]
3307 ]
3277
3308
3278 strip_from_start = map(re.compile,strip_re)
3309 strip_from_start = map(re.compile,strip_re)
3279
3310
3280 from IPython import iplib
3311 from IPython import iplib
3281 lines = []
3312 lines = []
3282 print "Pasting code; enter '%s' alone on the line to stop." % sentinel
3313 print "Pasting code; enter '%s' alone on the line to stop." % sentinel
3283 while 1:
3314 while 1:
3284 l = iplib.raw_input_original(':')
3315 l = iplib.raw_input_original(':')
3285 if l ==sentinel:
3316 if l ==sentinel:
3286 break
3317 break
3287
3318
3288 for pat in strip_from_start:
3319 for pat in strip_from_start:
3289 l = pat.sub('',l)
3320 l = pat.sub('',l)
3290 lines.append(l)
3321 lines.append(l)
3291
3322
3292 block = "\n".join(lines) + '\n'
3323 block = "\n".join(lines) + '\n'
3293 #print "block:\n",block
3324 #print "block:\n",block
3294 if not par:
3325 if not par:
3295 b = textwrap.dedent(block)
3326 b = textwrap.dedent(block)
3296 self.user_ns['pasted_block'] = b
3327 self.user_ns['pasted_block'] = b
3297 exec b in self.user_ns
3328 exec b in self.user_ns
3298 else:
3329 else:
3299 self.user_ns[par] = SList(block.splitlines())
3330 self.user_ns[par] = SList(block.splitlines())
3300 print "Block assigned to '%s'" % par
3331 print "Block assigned to '%s'" % par
3301
3332
3302 def magic_quickref(self,arg):
3333 def magic_quickref(self,arg):
3303 """ Show a quick reference sheet """
3334 """ Show a quick reference sheet """
3304 import IPython.usage
3335 import IPython.usage
3305 qr = IPython.usage.quick_reference + self.magic_magic('-brief')
3336 qr = IPython.usage.quick_reference + self.magic_magic('-brief')
3306
3337
3307 page(qr)
3338 page(qr)
3308
3339
3309 def magic_upgrade(self,arg):
3340 def magic_upgrade(self,arg):
3310 """ Upgrade your IPython installation
3341 """ Upgrade your IPython installation
3311
3342
3312 This will copy the config files that don't yet exist in your
3343 This will copy the config files that don't yet exist in your
3313 ipython dir from the system config dir. Use this after upgrading
3344 ipython dir from the system config dir. Use this after upgrading
3314 IPython if you don't wish to delete your .ipython dir.
3345 IPython if you don't wish to delete your .ipython dir.
3315
3346
3316 Call with -nolegacy to get rid of ipythonrc* files (recommended for
3347 Call with -nolegacy to get rid of ipythonrc* files (recommended for
3317 new users)
3348 new users)
3318
3349
3319 """
3350 """
3320 ip = self.getapi()
3351 ip = self.getapi()
3321 ipinstallation = path(IPython.__file__).dirname()
3352 ipinstallation = path(IPython.__file__).dirname()
3322 upgrade_script = '%s "%s"' % (sys.executable,ipinstallation / 'upgrade_dir.py')
3353 upgrade_script = '%s "%s"' % (sys.executable,ipinstallation / 'upgrade_dir.py')
3323 src_config = ipinstallation / 'UserConfig'
3354 src_config = ipinstallation / 'UserConfig'
3324 userdir = path(ip.options.ipythondir)
3355 userdir = path(ip.options.ipythondir)
3325 cmd = '%s "%s" "%s"' % (upgrade_script, src_config, userdir)
3356 cmd = '%s "%s" "%s"' % (upgrade_script, src_config, userdir)
3326 print ">",cmd
3357 print ">",cmd
3327 shell(cmd)
3358 shell(cmd)
3328 if arg == '-nolegacy':
3359 if arg == '-nolegacy':
3329 legacy = userdir.files('ipythonrc*')
3360 legacy = userdir.files('ipythonrc*')
3330 print "Nuking legacy files:",legacy
3361 print "Nuking legacy files:",legacy
3331
3362
3332 [p.remove() for p in legacy]
3363 [p.remove() for p in legacy]
3333 suffix = (sys.platform == 'win32' and '.ini' or '')
3364 suffix = (sys.platform == 'win32' and '.ini' or '')
3334 (userdir / ('ipythonrc' + suffix)).write_text('# Empty, see ipy_user_conf.py\n')
3365 (userdir / ('ipythonrc' + suffix)).write_text('# Empty, see ipy_user_conf.py\n')
3335
3366
3336
3367
3337 def magic_doctest_mode(self,parameter_s=''):
3368 def magic_doctest_mode(self,parameter_s=''):
3338 """Toggle doctest mode on and off.
3369 """Toggle doctest mode on and off.
3339
3370
3340 This mode allows you to toggle the prompt behavior between normal
3371 This mode allows you to toggle the prompt behavior between normal
3341 IPython prompts and ones that are as similar to the default IPython
3372 IPython prompts and ones that are as similar to the default IPython
3342 interpreter as possible.
3373 interpreter as possible.
3343
3374
3344 It also supports the pasting of code snippets that have leading '>>>'
3375 It also supports the pasting of code snippets that have leading '>>>'
3345 and '...' prompts in them. This means that you can paste doctests from
3376 and '...' prompts in them. This means that you can paste doctests from
3346 files or docstrings (even if they have leading whitespace), and the
3377 files or docstrings (even if they have leading whitespace), and the
3347 code will execute correctly. You can then use '%history -tn' to see
3378 code will execute correctly. You can then use '%history -tn' to see
3348 the translated history without line numbers; this will give you the
3379 the translated history without line numbers; this will give you the
3349 input after removal of all the leading prompts and whitespace, which
3380 input after removal of all the leading prompts and whitespace, which
3350 can be pasted back into an editor.
3381 can be pasted back into an editor.
3351
3382
3352 With these features, you can switch into this mode easily whenever you
3383 With these features, you can switch into this mode easily whenever you
3353 need to do testing and changes to doctests, without having to leave
3384 need to do testing and changes to doctests, without having to leave
3354 your existing IPython session.
3385 your existing IPython session.
3355 """
3386 """
3356
3387
3357 # XXX - Fix this to have cleaner activate/deactivate calls.
3388 # XXX - Fix this to have cleaner activate/deactivate calls.
3358 from IPython.Extensions import InterpreterPasteInput as ipaste
3389 from IPython.Extensions import InterpreterPasteInput as ipaste
3359 from IPython.ipstruct import Struct
3390 from IPython.ipstruct import Struct
3360
3391
3361 # Shorthands
3392 # Shorthands
3362 shell = self.shell
3393 shell = self.shell
3363 oc = shell.outputcache
3394 oc = shell.outputcache
3364 rc = shell.rc
3395 rc = shell.rc
3365 meta = shell.meta
3396 meta = shell.meta
3366 # dstore is a data store kept in the instance metadata bag to track any
3397 # dstore is a data store kept in the instance metadata bag to track any
3367 # changes we make, so we can undo them later.
3398 # changes we make, so we can undo them later.
3368 dstore = meta.setdefault('doctest_mode',Struct())
3399 dstore = meta.setdefault('doctest_mode',Struct())
3369 save_dstore = dstore.setdefault
3400 save_dstore = dstore.setdefault
3370
3401
3371 # save a few values we'll need to recover later
3402 # save a few values we'll need to recover later
3372 mode = save_dstore('mode',False)
3403 mode = save_dstore('mode',False)
3373 save_dstore('rc_pprint',rc.pprint)
3404 save_dstore('rc_pprint',rc.pprint)
3374 save_dstore('xmode',shell.InteractiveTB.mode)
3405 save_dstore('xmode',shell.InteractiveTB.mode)
3375 save_dstore('rc_separate_out',rc.separate_out)
3406 save_dstore('rc_separate_out',rc.separate_out)
3376 save_dstore('rc_separate_out2',rc.separate_out2)
3407 save_dstore('rc_separate_out2',rc.separate_out2)
3377 save_dstore('rc_prompts_pad_left',rc.prompts_pad_left)
3408 save_dstore('rc_prompts_pad_left',rc.prompts_pad_left)
3378 save_dstore('rc_separate_in',rc.separate_in)
3409 save_dstore('rc_separate_in',rc.separate_in)
3379
3410
3380 if mode == False:
3411 if mode == False:
3381 # turn on
3412 # turn on
3382 ipaste.activate_prefilter()
3413 ipaste.activate_prefilter()
3383
3414
3384 oc.prompt1.p_template = '>>> '
3415 oc.prompt1.p_template = '>>> '
3385 oc.prompt2.p_template = '... '
3416 oc.prompt2.p_template = '... '
3386 oc.prompt_out.p_template = ''
3417 oc.prompt_out.p_template = ''
3387
3418
3388 # Prompt separators like plain python
3419 # Prompt separators like plain python
3389 oc.input_sep = oc.prompt1.sep = ''
3420 oc.input_sep = oc.prompt1.sep = ''
3390 oc.output_sep = ''
3421 oc.output_sep = ''
3391 oc.output_sep2 = ''
3422 oc.output_sep2 = ''
3392
3423
3393 oc.prompt1.pad_left = oc.prompt2.pad_left = \
3424 oc.prompt1.pad_left = oc.prompt2.pad_left = \
3394 oc.prompt_out.pad_left = False
3425 oc.prompt_out.pad_left = False
3395
3426
3396 rc.pprint = False
3427 rc.pprint = False
3397
3428
3398 shell.magic_xmode('Plain')
3429 shell.magic_xmode('Plain')
3399
3430
3400 else:
3431 else:
3401 # turn off
3432 # turn off
3402 ipaste.deactivate_prefilter()
3433 ipaste.deactivate_prefilter()
3403
3434
3404 oc.prompt1.p_template = rc.prompt_in1
3435 oc.prompt1.p_template = rc.prompt_in1
3405 oc.prompt2.p_template = rc.prompt_in2
3436 oc.prompt2.p_template = rc.prompt_in2
3406 oc.prompt_out.p_template = rc.prompt_out
3437 oc.prompt_out.p_template = rc.prompt_out
3407
3438
3408 oc.input_sep = oc.prompt1.sep = dstore.rc_separate_in
3439 oc.input_sep = oc.prompt1.sep = dstore.rc_separate_in
3409
3440
3410 oc.output_sep = dstore.rc_separate_out
3441 oc.output_sep = dstore.rc_separate_out
3411 oc.output_sep2 = dstore.rc_separate_out2
3442 oc.output_sep2 = dstore.rc_separate_out2
3412
3443
3413 oc.prompt1.pad_left = oc.prompt2.pad_left = \
3444 oc.prompt1.pad_left = oc.prompt2.pad_left = \
3414 oc.prompt_out.pad_left = dstore.rc_prompts_pad_left
3445 oc.prompt_out.pad_left = dstore.rc_prompts_pad_left
3415
3446
3416 rc.pprint = dstore.rc_pprint
3447 rc.pprint = dstore.rc_pprint
3417
3448
3418 shell.magic_xmode(dstore.xmode)
3449 shell.magic_xmode(dstore.xmode)
3419
3450
3420 # Store new mode and inform
3451 # Store new mode and inform
3421 dstore.mode = bool(1-int(mode))
3452 dstore.mode = bool(1-int(mode))
3422 print 'Doctest mode is:',
3453 print 'Doctest mode is:',
3423 print ['OFF','ON'][dstore.mode]
3454 print ['OFF','ON'][dstore.mode]
3424
3455
3425 # end Magic
3456 # end Magic
@@ -1,622 +1,626 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Classes for handling input/output prompts.
3 Classes for handling input/output prompts.
4 """
4 """
5
5
6 #*****************************************************************************
6 #*****************************************************************************
7 # Copyright (C) 2008-2009 The IPython Development Team
7 # Copyright (C) 2008-2009 The IPython Development Team
8 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
8 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #*****************************************************************************
12 #*****************************************************************************
13
13
14 #****************************************************************************
14 #****************************************************************************
15 # Required modules
15 # Required modules
16 import __builtin__
16 import __builtin__
17 import os
17 import os
18 import socket
18 import socket
19 import sys
19 import sys
20 import time
20 import time
21
21
22 # IPython's own
22 # IPython's own
23 from IPython import ColorANSI
23 from IPython import ColorANSI
24 from IPython import Release
24 from IPython import Release
25 from IPython.external.Itpl import ItplNS
25 from IPython.external.Itpl import ItplNS
26 from IPython.ipapi import TryNext
26 from IPython.ipapi import TryNext
27 from IPython.ipstruct import Struct
27 from IPython.ipstruct import Struct
28 from IPython.macro import Macro
28 from IPython.macro import Macro
29
29
30 from IPython.genutils import *
30 from IPython.genutils import *
31
31
32 #****************************************************************************
32 #****************************************************************************
33 #Color schemes for Prompts.
33 #Color schemes for Prompts.
34
34
35 PromptColors = ColorANSI.ColorSchemeTable()
35 PromptColors = ColorANSI.ColorSchemeTable()
36 InputColors = ColorANSI.InputTermColors # just a shorthand
36 InputColors = ColorANSI.InputTermColors # just a shorthand
37 Colors = ColorANSI.TermColors # just a shorthand
37 Colors = ColorANSI.TermColors # just a shorthand
38
38
39 PromptColors.add_scheme(ColorANSI.ColorScheme(
39 PromptColors.add_scheme(ColorANSI.ColorScheme(
40 'NoColor',
40 'NoColor',
41 in_prompt = InputColors.NoColor, # Input prompt
41 in_prompt = InputColors.NoColor, # Input prompt
42 in_number = InputColors.NoColor, # Input prompt number
42 in_number = InputColors.NoColor, # Input prompt number
43 in_prompt2 = InputColors.NoColor, # Continuation prompt
43 in_prompt2 = InputColors.NoColor, # Continuation prompt
44 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
44 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
45
45
46 out_prompt = Colors.NoColor, # Output prompt
46 out_prompt = Colors.NoColor, # Output prompt
47 out_number = Colors.NoColor, # Output prompt number
47 out_number = Colors.NoColor, # Output prompt number
48
48
49 normal = Colors.NoColor # color off (usu. Colors.Normal)
49 normal = Colors.NoColor # color off (usu. Colors.Normal)
50 ))
50 ))
51
51
52 # make some schemes as instances so we can copy them for modification easily:
52 # make some schemes as instances so we can copy them for modification easily:
53 __PColLinux = ColorANSI.ColorScheme(
53 __PColLinux = ColorANSI.ColorScheme(
54 'Linux',
54 'Linux',
55 in_prompt = InputColors.Green,
55 in_prompt = InputColors.Green,
56 in_number = InputColors.LightGreen,
56 in_number = InputColors.LightGreen,
57 in_prompt2 = InputColors.Green,
57 in_prompt2 = InputColors.Green,
58 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
58 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
59
59
60 out_prompt = Colors.Red,
60 out_prompt = Colors.Red,
61 out_number = Colors.LightRed,
61 out_number = Colors.LightRed,
62
62
63 normal = Colors.Normal
63 normal = Colors.Normal
64 )
64 )
65 # Don't forget to enter it into the table!
65 # Don't forget to enter it into the table!
66 PromptColors.add_scheme(__PColLinux)
66 PromptColors.add_scheme(__PColLinux)
67
67
68 # Slightly modified Linux for light backgrounds
68 # Slightly modified Linux for light backgrounds
69 __PColLightBG = __PColLinux.copy('LightBG')
69 __PColLightBG = __PColLinux.copy('LightBG')
70
70
71 __PColLightBG.colors.update(
71 __PColLightBG.colors.update(
72 in_prompt = InputColors.Blue,
72 in_prompt = InputColors.Blue,
73 in_number = InputColors.LightBlue,
73 in_number = InputColors.LightBlue,
74 in_prompt2 = InputColors.Blue
74 in_prompt2 = InputColors.Blue
75 )
75 )
76 PromptColors.add_scheme(__PColLightBG)
76 PromptColors.add_scheme(__PColLightBG)
77
77
78 del Colors,InputColors
78 del Colors,InputColors
79
79
80 #-----------------------------------------------------------------------------
80 #-----------------------------------------------------------------------------
81 def multiple_replace(dict, text):
81 def multiple_replace(dict, text):
82 """ Replace in 'text' all occurences of any key in the given
82 """ Replace in 'text' all occurences of any key in the given
83 dictionary by its corresponding value. Returns the new string."""
83 dictionary by its corresponding value. Returns the new string."""
84
84
85 # Function by Xavier Defrang, originally found at:
85 # Function by Xavier Defrang, originally found at:
86 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
86 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
87
87
88 # Create a regular expression from the dictionary keys
88 # Create a regular expression from the dictionary keys
89 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
89 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
90 # For each match, look-up corresponding value in dictionary
90 # For each match, look-up corresponding value in dictionary
91 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
91 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
92
92
93 #-----------------------------------------------------------------------------
93 #-----------------------------------------------------------------------------
94 # Special characters that can be used in prompt templates, mainly bash-like
94 # Special characters that can be used in prompt templates, mainly bash-like
95
95
96 # If $HOME isn't defined (Windows), make it an absurd string so that it can
96 # If $HOME isn't defined (Windows), make it an absurd string so that it can
97 # never be expanded out into '~'. Basically anything which can never be a
97 # never be expanded out into '~'. Basically anything which can never be a
98 # reasonable directory name will do, we just want the $HOME -> '~' operation
98 # reasonable directory name will do, we just want the $HOME -> '~' operation
99 # to become a no-op. We pre-compute $HOME here so it's not done on every
99 # to become a no-op. We pre-compute $HOME here so it's not done on every
100 # prompt call.
100 # prompt call.
101
101
102 # FIXME:
102 # FIXME:
103
103
104 # - This should be turned into a class which does proper namespace management,
104 # - This should be turned into a class which does proper namespace management,
105 # since the prompt specials need to be evaluated in a certain namespace.
105 # since the prompt specials need to be evaluated in a certain namespace.
106 # Currently it's just globals, which need to be managed manually by code
106 # Currently it's just globals, which need to be managed manually by code
107 # below.
107 # below.
108
108
109 # - I also need to split up the color schemes from the prompt specials
109 # - I also need to split up the color schemes from the prompt specials
110 # somehow. I don't have a clean design for that quite yet.
110 # somehow. I don't have a clean design for that quite yet.
111
111
112 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
112 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
113
113
114 # We precompute a few more strings here for the prompt_specials, which are
114 # We precompute a few more strings here for the prompt_specials, which are
115 # fixed once ipython starts. This reduces the runtime overhead of computing
115 # fixed once ipython starts. This reduces the runtime overhead of computing
116 # prompt strings.
116 # prompt strings.
117 USER = os.environ.get("USER")
117 USER = os.environ.get("USER")
118 HOSTNAME = socket.gethostname()
118 HOSTNAME = socket.gethostname()
119 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
119 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
120 ROOT_SYMBOL = "$#"[os.name=='nt' or os.getuid()==0]
120 ROOT_SYMBOL = "$#"[os.name=='nt' or os.getuid()==0]
121
121
122 prompt_specials_color = {
122 prompt_specials_color = {
123 # Prompt/history count
123 # Prompt/history count
124 '%n' : '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
124 '%n' : '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
125 r'\#': '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
125 r'\#': '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
126 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
126 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
127 # can get numbers displayed in whatever color they want.
127 # can get numbers displayed in whatever color they want.
128 r'\N': '${self.cache.prompt_count}',
128 r'\N': '${self.cache.prompt_count}',
129
129 # Prompt/history count, with the actual digits replaced by dots. Used
130 # Prompt/history count, with the actual digits replaced by dots. Used
130 # mainly in continuation prompts (prompt_in2)
131 # mainly in continuation prompts (prompt_in2)
131 r'\D': '${"."*len(str(self.cache.prompt_count))}',
132 #r'\D': '${"."*len(str(self.cache.prompt_count))}',
133 # More robust form of the above expression, that uses __builtins__
134 r'\D': '${"."*__builtins__.len(__builtins__.str(self.cache.prompt_count))}',
135
132 # Current working directory
136 # Current working directory
133 r'\w': '${os.getcwd()}',
137 r'\w': '${os.getcwd()}',
134 # Current time
138 # Current time
135 r'\t' : '${time.strftime("%H:%M:%S")}',
139 r'\t' : '${time.strftime("%H:%M:%S")}',
136 # Basename of current working directory.
140 # Basename of current working directory.
137 # (use os.sep to make this portable across OSes)
141 # (use os.sep to make this portable across OSes)
138 r'\W' : '${os.getcwd().split("%s")[-1]}' % os.sep,
142 r'\W' : '${os.getcwd().split("%s")[-1]}' % os.sep,
139 # These X<N> are an extension to the normal bash prompts. They return
143 # These X<N> are an extension to the normal bash prompts. They return
140 # N terms of the path, after replacing $HOME with '~'
144 # N terms of the path, after replacing $HOME with '~'
141 r'\X0': '${os.getcwd().replace("%s","~")}' % HOME,
145 r'\X0': '${os.getcwd().replace("%s","~")}' % HOME,
142 r'\X1': '${self.cwd_filt(1)}',
146 r'\X1': '${self.cwd_filt(1)}',
143 r'\X2': '${self.cwd_filt(2)}',
147 r'\X2': '${self.cwd_filt(2)}',
144 r'\X3': '${self.cwd_filt(3)}',
148 r'\X3': '${self.cwd_filt(3)}',
145 r'\X4': '${self.cwd_filt(4)}',
149 r'\X4': '${self.cwd_filt(4)}',
146 r'\X5': '${self.cwd_filt(5)}',
150 r'\X5': '${self.cwd_filt(5)}',
147 # Y<N> are similar to X<N>, but they show '~' if it's the directory
151 # Y<N> are similar to X<N>, but they show '~' if it's the directory
148 # N+1 in the list. Somewhat like %cN in tcsh.
152 # N+1 in the list. Somewhat like %cN in tcsh.
149 r'\Y0': '${self.cwd_filt2(0)}',
153 r'\Y0': '${self.cwd_filt2(0)}',
150 r'\Y1': '${self.cwd_filt2(1)}',
154 r'\Y1': '${self.cwd_filt2(1)}',
151 r'\Y2': '${self.cwd_filt2(2)}',
155 r'\Y2': '${self.cwd_filt2(2)}',
152 r'\Y3': '${self.cwd_filt2(3)}',
156 r'\Y3': '${self.cwd_filt2(3)}',
153 r'\Y4': '${self.cwd_filt2(4)}',
157 r'\Y4': '${self.cwd_filt2(4)}',
154 r'\Y5': '${self.cwd_filt2(5)}',
158 r'\Y5': '${self.cwd_filt2(5)}',
155 # Hostname up to first .
159 # Hostname up to first .
156 r'\h': HOSTNAME_SHORT,
160 r'\h': HOSTNAME_SHORT,
157 # Full hostname
161 # Full hostname
158 r'\H': HOSTNAME,
162 r'\H': HOSTNAME,
159 # Username of current user
163 # Username of current user
160 r'\u': USER,
164 r'\u': USER,
161 # Escaped '\'
165 # Escaped '\'
162 '\\\\': '\\',
166 '\\\\': '\\',
163 # Newline
167 # Newline
164 r'\n': '\n',
168 r'\n': '\n',
165 # Carriage return
169 # Carriage return
166 r'\r': '\r',
170 r'\r': '\r',
167 # Release version
171 # Release version
168 r'\v': Release.version,
172 r'\v': Release.version,
169 # Root symbol ($ or #)
173 # Root symbol ($ or #)
170 r'\$': ROOT_SYMBOL,
174 r'\$': ROOT_SYMBOL,
171 }
175 }
172
176
173 # A copy of the prompt_specials dictionary but with all color escapes removed,
177 # A copy of the prompt_specials dictionary but with all color escapes removed,
174 # so we can correctly compute the prompt length for the auto_rewrite method.
178 # so we can correctly compute the prompt length for the auto_rewrite method.
175 prompt_specials_nocolor = prompt_specials_color.copy()
179 prompt_specials_nocolor = prompt_specials_color.copy()
176 prompt_specials_nocolor['%n'] = '${self.cache.prompt_count}'
180 prompt_specials_nocolor['%n'] = '${self.cache.prompt_count}'
177 prompt_specials_nocolor[r'\#'] = '${self.cache.prompt_count}'
181 prompt_specials_nocolor[r'\#'] = '${self.cache.prompt_count}'
178
182
179 # Add in all the InputTermColors color escapes as valid prompt characters.
183 # Add in all the InputTermColors color escapes as valid prompt characters.
180 # They all get added as \\C_COLORNAME, so that we don't have any conflicts
184 # They all get added as \\C_COLORNAME, so that we don't have any conflicts
181 # with a color name which may begin with a letter used by any other of the
185 # with a color name which may begin with a letter used by any other of the
182 # allowed specials. This of course means that \\C will never be allowed for
186 # allowed specials. This of course means that \\C will never be allowed for
183 # anything else.
187 # anything else.
184 input_colors = ColorANSI.InputTermColors
188 input_colors = ColorANSI.InputTermColors
185 for _color in dir(input_colors):
189 for _color in dir(input_colors):
186 if _color[0] != '_':
190 if _color[0] != '_':
187 c_name = r'\C_'+_color
191 c_name = r'\C_'+_color
188 prompt_specials_color[c_name] = getattr(input_colors,_color)
192 prompt_specials_color[c_name] = getattr(input_colors,_color)
189 prompt_specials_nocolor[c_name] = ''
193 prompt_specials_nocolor[c_name] = ''
190
194
191 # we default to no color for safety. Note that prompt_specials is a global
195 # we default to no color for safety. Note that prompt_specials is a global
192 # variable used by all prompt objects.
196 # variable used by all prompt objects.
193 prompt_specials = prompt_specials_nocolor
197 prompt_specials = prompt_specials_nocolor
194
198
195 #-----------------------------------------------------------------------------
199 #-----------------------------------------------------------------------------
196 def str_safe(arg):
200 def str_safe(arg):
197 """Convert to a string, without ever raising an exception.
201 """Convert to a string, without ever raising an exception.
198
202
199 If str(arg) fails, <ERROR: ... > is returned, where ... is the exception
203 If str(arg) fails, <ERROR: ... > is returned, where ... is the exception
200 error message."""
204 error message."""
201
205
202 try:
206 try:
203 out = str(arg)
207 out = str(arg)
204 except UnicodeError:
208 except UnicodeError:
205 try:
209 try:
206 out = arg.encode('utf_8','replace')
210 out = arg.encode('utf_8','replace')
207 except Exception,msg:
211 except Exception,msg:
208 # let's keep this little duplication here, so that the most common
212 # let's keep this little duplication here, so that the most common
209 # case doesn't suffer from a double try wrapping.
213 # case doesn't suffer from a double try wrapping.
210 out = '<ERROR: %s>' % msg
214 out = '<ERROR: %s>' % msg
211 except Exception,msg:
215 except Exception,msg:
212 out = '<ERROR: %s>' % msg
216 out = '<ERROR: %s>' % msg
213 return out
217 return out
214
218
215 class BasePrompt(object):
219 class BasePrompt(object):
216 """Interactive prompt similar to Mathematica's."""
220 """Interactive prompt similar to Mathematica's."""
217
221
218 def _get_p_template(self):
222 def _get_p_template(self):
219 return self._p_template
223 return self._p_template
220
224
221 def _set_p_template(self,val):
225 def _set_p_template(self,val):
222 self._p_template = val
226 self._p_template = val
223 self.set_p_str()
227 self.set_p_str()
224
228
225 p_template = property(_get_p_template,_set_p_template,
229 p_template = property(_get_p_template,_set_p_template,
226 doc='Template for prompt string creation')
230 doc='Template for prompt string creation')
227
231
228 def __init__(self,cache,sep,prompt,pad_left=False):
232 def __init__(self,cache,sep,prompt,pad_left=False):
229
233
230 # Hack: we access information about the primary prompt through the
234 # Hack: we access information about the primary prompt through the
231 # cache argument. We need this, because we want the secondary prompt
235 # cache argument. We need this, because we want the secondary prompt
232 # to be aligned with the primary one. Color table info is also shared
236 # to be aligned with the primary one. Color table info is also shared
233 # by all prompt classes through the cache. Nice OO spaghetti code!
237 # by all prompt classes through the cache. Nice OO spaghetti code!
234 self.cache = cache
238 self.cache = cache
235 self.sep = sep
239 self.sep = sep
236
240
237 # regexp to count the number of spaces at the end of a prompt
241 # regexp to count the number of spaces at the end of a prompt
238 # expression, useful for prompt auto-rewriting
242 # expression, useful for prompt auto-rewriting
239 self.rspace = re.compile(r'(\s*)$')
243 self.rspace = re.compile(r'(\s*)$')
240 # Flag to left-pad prompt strings to match the length of the primary
244 # Flag to left-pad prompt strings to match the length of the primary
241 # prompt
245 # prompt
242 self.pad_left = pad_left
246 self.pad_left = pad_left
243
247
244 # Set template to create each actual prompt (where numbers change).
248 # Set template to create each actual prompt (where numbers change).
245 # Use a property
249 # Use a property
246 self.p_template = prompt
250 self.p_template = prompt
247 self.set_p_str()
251 self.set_p_str()
248
252
249 def set_p_str(self):
253 def set_p_str(self):
250 """ Set the interpolating prompt strings.
254 """ Set the interpolating prompt strings.
251
255
252 This must be called every time the color settings change, because the
256 This must be called every time the color settings change, because the
253 prompt_specials global may have changed."""
257 prompt_specials global may have changed."""
254
258
255 import os,time # needed in locals for prompt string handling
259 import os,time # needed in locals for prompt string handling
256 loc = locals()
260 loc = locals()
257 try:
261 try:
258 self.p_str = ItplNS('%s%s%s' %
262 self.p_str = ItplNS('%s%s%s' %
259 ('${self.sep}${self.col_p}',
263 ('${self.sep}${self.col_p}',
260 multiple_replace(prompt_specials, self.p_template),
264 multiple_replace(prompt_specials, self.p_template),
261 '${self.col_norm}'),self.cache.user_ns,loc)
265 '${self.col_norm}'),self.cache.user_ns,loc)
262
266
263 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
267 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
264 self.p_template),
268 self.p_template),
265 self.cache.user_ns,loc)
269 self.cache.user_ns,loc)
266 except:
270 except:
267 print "Illegal prompt template (check $ usage!):",self.p_template
271 print "Illegal prompt template (check $ usage!):",self.p_template
268 self.p_str = self.p_template
272 self.p_str = self.p_template
269 self.p_str_nocolor = self.p_template
273 self.p_str_nocolor = self.p_template
270
274
271 def write(self,msg): # dbg
275 def write(self,msg): # dbg
272 sys.stdout.write(msg)
276 sys.stdout.write(msg)
273 return ''
277 return ''
274
278
275 def __str__(self):
279 def __str__(self):
276 """Return a string form of the prompt.
280 """Return a string form of the prompt.
277
281
278 This for is useful for continuation and output prompts, since it is
282 This for is useful for continuation and output prompts, since it is
279 left-padded to match lengths with the primary one (if the
283 left-padded to match lengths with the primary one (if the
280 self.pad_left attribute is set)."""
284 self.pad_left attribute is set)."""
281
285
282 out_str = str_safe(self.p_str)
286 out_str = str_safe(self.p_str)
283 if self.pad_left:
287 if self.pad_left:
284 # We must find the amount of padding required to match lengths,
288 # We must find the amount of padding required to match lengths,
285 # taking the color escapes (which are invisible on-screen) into
289 # taking the color escapes (which are invisible on-screen) into
286 # account.
290 # account.
287 esc_pad = len(out_str) - len(str_safe(self.p_str_nocolor))
291 esc_pad = len(out_str) - len(str_safe(self.p_str_nocolor))
288 format = '%%%ss' % (len(str(self.cache.last_prompt))+esc_pad)
292 format = '%%%ss' % (len(str(self.cache.last_prompt))+esc_pad)
289 return format % out_str
293 return format % out_str
290 else:
294 else:
291 return out_str
295 return out_str
292
296
293 # these path filters are put in as methods so that we can control the
297 # these path filters are put in as methods so that we can control the
294 # namespace where the prompt strings get evaluated
298 # namespace where the prompt strings get evaluated
295 def cwd_filt(self,depth):
299 def cwd_filt(self,depth):
296 """Return the last depth elements of the current working directory.
300 """Return the last depth elements of the current working directory.
297
301
298 $HOME is always replaced with '~'.
302 $HOME is always replaced with '~'.
299 If depth==0, the full path is returned."""
303 If depth==0, the full path is returned."""
300
304
301 cwd = os.getcwd().replace(HOME,"~")
305 cwd = os.getcwd().replace(HOME,"~")
302 out = os.sep.join(cwd.split(os.sep)[-depth:])
306 out = os.sep.join(cwd.split(os.sep)[-depth:])
303 if out:
307 if out:
304 return out
308 return out
305 else:
309 else:
306 return os.sep
310 return os.sep
307
311
308 def cwd_filt2(self,depth):
312 def cwd_filt2(self,depth):
309 """Return the last depth elements of the current working directory.
313 """Return the last depth elements of the current working directory.
310
314
311 $HOME is always replaced with '~'.
315 $HOME is always replaced with '~'.
312 If depth==0, the full path is returned."""
316 If depth==0, the full path is returned."""
313
317
314 full_cwd = os.getcwd()
318 full_cwd = os.getcwd()
315 cwd = full_cwd.replace(HOME,"~").split(os.sep)
319 cwd = full_cwd.replace(HOME,"~").split(os.sep)
316 if '~' in cwd and len(cwd) == depth+1:
320 if '~' in cwd and len(cwd) == depth+1:
317 depth += 1
321 depth += 1
318 drivepart = ''
322 drivepart = ''
319 if sys.platform == 'win32' and len(cwd) > depth:
323 if sys.platform == 'win32' and len(cwd) > depth:
320 drivepart = os.path.splitdrive(full_cwd)[0]
324 drivepart = os.path.splitdrive(full_cwd)[0]
321 out = drivepart + '/'.join(cwd[-depth:])
325 out = drivepart + '/'.join(cwd[-depth:])
322
326
323 if out:
327 if out:
324 return out
328 return out
325 else:
329 else:
326 return os.sep
330 return os.sep
327
331
328 def __nonzero__(self):
332 def __nonzero__(self):
329 """Implement boolean behavior.
333 """Implement boolean behavior.
330
334
331 Checks whether the p_str attribute is non-empty"""
335 Checks whether the p_str attribute is non-empty"""
332
336
333 return bool(self.p_template)
337 return bool(self.p_template)
334
338
335 class Prompt1(BasePrompt):
339 class Prompt1(BasePrompt):
336 """Input interactive prompt similar to Mathematica's."""
340 """Input interactive prompt similar to Mathematica's."""
337
341
338 def __init__(self,cache,sep='\n',prompt='In [\\#]: ',pad_left=True):
342 def __init__(self,cache,sep='\n',prompt='In [\\#]: ',pad_left=True):
339 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
343 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
340
344
341 def set_colors(self):
345 def set_colors(self):
342 self.set_p_str()
346 self.set_p_str()
343 Colors = self.cache.color_table.active_colors # shorthand
347 Colors = self.cache.color_table.active_colors # shorthand
344 self.col_p = Colors.in_prompt
348 self.col_p = Colors.in_prompt
345 self.col_num = Colors.in_number
349 self.col_num = Colors.in_number
346 self.col_norm = Colors.in_normal
350 self.col_norm = Colors.in_normal
347 # We need a non-input version of these escapes for the '--->'
351 # We need a non-input version of these escapes for the '--->'
348 # auto-call prompts used in the auto_rewrite() method.
352 # auto-call prompts used in the auto_rewrite() method.
349 self.col_p_ni = self.col_p.replace('\001','').replace('\002','')
353 self.col_p_ni = self.col_p.replace('\001','').replace('\002','')
350 self.col_norm_ni = Colors.normal
354 self.col_norm_ni = Colors.normal
351
355
352 def __str__(self):
356 def __str__(self):
353 self.cache.prompt_count += 1
357 self.cache.prompt_count += 1
354 self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1]
358 self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1]
355 return str_safe(self.p_str)
359 return str_safe(self.p_str)
356
360
357 def auto_rewrite(self):
361 def auto_rewrite(self):
358 """Print a string of the form '--->' which lines up with the previous
362 """Print a string of the form '--->' which lines up with the previous
359 input string. Useful for systems which re-write the user input when
363 input string. Useful for systems which re-write the user input when
360 handling automatically special syntaxes."""
364 handling automatically special syntaxes."""
361
365
362 curr = str(self.cache.last_prompt)
366 curr = str(self.cache.last_prompt)
363 nrspaces = len(self.rspace.search(curr).group())
367 nrspaces = len(self.rspace.search(curr).group())
364 return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1),
368 return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1),
365 ' '*nrspaces,self.col_norm_ni)
369 ' '*nrspaces,self.col_norm_ni)
366
370
367 class PromptOut(BasePrompt):
371 class PromptOut(BasePrompt):
368 """Output interactive prompt similar to Mathematica's."""
372 """Output interactive prompt similar to Mathematica's."""
369
373
370 def __init__(self,cache,sep='',prompt='Out[\\#]: ',pad_left=True):
374 def __init__(self,cache,sep='',prompt='Out[\\#]: ',pad_left=True):
371 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
375 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
372 if not self.p_template:
376 if not self.p_template:
373 self.__str__ = lambda: ''
377 self.__str__ = lambda: ''
374
378
375 def set_colors(self):
379 def set_colors(self):
376 self.set_p_str()
380 self.set_p_str()
377 Colors = self.cache.color_table.active_colors # shorthand
381 Colors = self.cache.color_table.active_colors # shorthand
378 self.col_p = Colors.out_prompt
382 self.col_p = Colors.out_prompt
379 self.col_num = Colors.out_number
383 self.col_num = Colors.out_number
380 self.col_norm = Colors.normal
384 self.col_norm = Colors.normal
381
385
382 class Prompt2(BasePrompt):
386 class Prompt2(BasePrompt):
383 """Interactive continuation prompt."""
387 """Interactive continuation prompt."""
384
388
385 def __init__(self,cache,prompt=' .\\D.: ',pad_left=True):
389 def __init__(self,cache,prompt=' .\\D.: ',pad_left=True):
386 self.cache = cache
390 self.cache = cache
387 self.p_template = prompt
391 self.p_template = prompt
388 self.pad_left = pad_left
392 self.pad_left = pad_left
389 self.set_p_str()
393 self.set_p_str()
390
394
391 def set_p_str(self):
395 def set_p_str(self):
392 import os,time # needed in locals for prompt string handling
396 import os,time # needed in locals for prompt string handling
393 loc = locals()
397 loc = locals()
394 self.p_str = ItplNS('%s%s%s' %
398 self.p_str = ItplNS('%s%s%s' %
395 ('${self.col_p2}',
399 ('${self.col_p2}',
396 multiple_replace(prompt_specials, self.p_template),
400 multiple_replace(prompt_specials, self.p_template),
397 '$self.col_norm'),
401 '$self.col_norm'),
398 self.cache.user_ns,loc)
402 self.cache.user_ns,loc)
399 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
403 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
400 self.p_template),
404 self.p_template),
401 self.cache.user_ns,loc)
405 self.cache.user_ns,loc)
402
406
403 def set_colors(self):
407 def set_colors(self):
404 self.set_p_str()
408 self.set_p_str()
405 Colors = self.cache.color_table.active_colors
409 Colors = self.cache.color_table.active_colors
406 self.col_p2 = Colors.in_prompt2
410 self.col_p2 = Colors.in_prompt2
407 self.col_norm = Colors.in_normal
411 self.col_norm = Colors.in_normal
408 # FIXME (2004-06-16) HACK: prevent crashes for users who haven't
412 # FIXME (2004-06-16) HACK: prevent crashes for users who haven't
409 # updated their prompt_in2 definitions. Remove eventually.
413 # updated their prompt_in2 definitions. Remove eventually.
410 self.col_p = Colors.out_prompt
414 self.col_p = Colors.out_prompt
411 self.col_num = Colors.out_number
415 self.col_num = Colors.out_number
412
416
413
417
414 #-----------------------------------------------------------------------------
418 #-----------------------------------------------------------------------------
415 class CachedOutput:
419 class CachedOutput:
416 """Class for printing output from calculations while keeping a cache of
420 """Class for printing output from calculations while keeping a cache of
417 reults. It dynamically creates global variables prefixed with _ which
421 reults. It dynamically creates global variables prefixed with _ which
418 contain these results.
422 contain these results.
419
423
420 Meant to be used as a sys.displayhook replacement, providing numbered
424 Meant to be used as a sys.displayhook replacement, providing numbered
421 prompts and cache services.
425 prompts and cache services.
422
426
423 Initialize with initial and final values for cache counter (this defines
427 Initialize with initial and final values for cache counter (this defines
424 the maximum size of the cache."""
428 the maximum size of the cache."""
425
429
426 def __init__(self,shell,cache_size,Pprint,
430 def __init__(self,shell,cache_size,Pprint,
427 colors='NoColor',input_sep='\n',
431 colors='NoColor',input_sep='\n',
428 output_sep='\n',output_sep2='',
432 output_sep='\n',output_sep2='',
429 ps1 = None, ps2 = None,ps_out = None,pad_left=True):
433 ps1 = None, ps2 = None,ps_out = None,pad_left=True):
430
434
431 cache_size_min = 3
435 cache_size_min = 3
432 if cache_size <= 0:
436 if cache_size <= 0:
433 self.do_full_cache = 0
437 self.do_full_cache = 0
434 cache_size = 0
438 cache_size = 0
435 elif cache_size < cache_size_min:
439 elif cache_size < cache_size_min:
436 self.do_full_cache = 0
440 self.do_full_cache = 0
437 cache_size = 0
441 cache_size = 0
438 warn('caching was disabled (min value for cache size is %s).' %
442 warn('caching was disabled (min value for cache size is %s).' %
439 cache_size_min,level=3)
443 cache_size_min,level=3)
440 else:
444 else:
441 self.do_full_cache = 1
445 self.do_full_cache = 1
442
446
443 self.cache_size = cache_size
447 self.cache_size = cache_size
444 self.input_sep = input_sep
448 self.input_sep = input_sep
445
449
446 # we need a reference to the user-level namespace
450 # we need a reference to the user-level namespace
447 self.shell = shell
451 self.shell = shell
448 self.user_ns = shell.user_ns
452 self.user_ns = shell.user_ns
449 # and to the user's input
453 # and to the user's input
450 self.input_hist = shell.input_hist
454 self.input_hist = shell.input_hist
451 # and to the user's logger, for logging output
455 # and to the user's logger, for logging output
452 self.logger = shell.logger
456 self.logger = shell.logger
453
457
454 # Set input prompt strings and colors
458 # Set input prompt strings and colors
455 if cache_size == 0:
459 if cache_size == 0:
456 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
460 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
457 or ps1.find(r'\N') > -1:
461 or ps1.find(r'\N') > -1:
458 ps1 = '>>> '
462 ps1 = '>>> '
459 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
463 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
460 or ps2.find(r'\N') > -1:
464 or ps2.find(r'\N') > -1:
461 ps2 = '... '
465 ps2 = '... '
462 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
466 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
463 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
467 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
464 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
468 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
465
469
466 self.color_table = PromptColors
470 self.color_table = PromptColors
467 self.prompt1 = Prompt1(self,sep=input_sep,prompt=self.ps1_str,
471 self.prompt1 = Prompt1(self,sep=input_sep,prompt=self.ps1_str,
468 pad_left=pad_left)
472 pad_left=pad_left)
469 self.prompt2 = Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
473 self.prompt2 = Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
470 self.prompt_out = PromptOut(self,sep='',prompt=self.ps_out_str,
474 self.prompt_out = PromptOut(self,sep='',prompt=self.ps_out_str,
471 pad_left=pad_left)
475 pad_left=pad_left)
472 self.set_colors(colors)
476 self.set_colors(colors)
473
477
474 # other more normal stuff
478 # other more normal stuff
475 # b/c each call to the In[] prompt raises it by 1, even the first.
479 # b/c each call to the In[] prompt raises it by 1, even the first.
476 self.prompt_count = 0
480 self.prompt_count = 0
477 # Store the last prompt string each time, we need it for aligning
481 # Store the last prompt string each time, we need it for aligning
478 # continuation and auto-rewrite prompts
482 # continuation and auto-rewrite prompts
479 self.last_prompt = ''
483 self.last_prompt = ''
480 self.Pprint = Pprint
484 self.Pprint = Pprint
481 self.output_sep = output_sep
485 self.output_sep = output_sep
482 self.output_sep2 = output_sep2
486 self.output_sep2 = output_sep2
483 self._,self.__,self.___ = '','',''
487 self._,self.__,self.___ = '','',''
484 self.pprint_types = map(type,[(),[],{}])
488 self.pprint_types = map(type,[(),[],{}])
485
489
486 # these are deliberately global:
490 # these are deliberately global:
487 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
491 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
488 self.user_ns.update(to_user_ns)
492 self.user_ns.update(to_user_ns)
489
493
490 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
494 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
491 if p_str is None:
495 if p_str is None:
492 if self.do_full_cache:
496 if self.do_full_cache:
493 return cache_def
497 return cache_def
494 else:
498 else:
495 return no_cache_def
499 return no_cache_def
496 else:
500 else:
497 return p_str
501 return p_str
498
502
499 def set_colors(self,colors):
503 def set_colors(self,colors):
500 """Set the active color scheme and configure colors for the three
504 """Set the active color scheme and configure colors for the three
501 prompt subsystems."""
505 prompt subsystems."""
502
506
503 # FIXME: the prompt_specials global should be gobbled inside this
507 # FIXME: the prompt_specials global should be gobbled inside this
504 # class instead. Do it when cleaning up the whole 3-prompt system.
508 # class instead. Do it when cleaning up the whole 3-prompt system.
505 global prompt_specials
509 global prompt_specials
506 if colors.lower()=='nocolor':
510 if colors.lower()=='nocolor':
507 prompt_specials = prompt_specials_nocolor
511 prompt_specials = prompt_specials_nocolor
508 else:
512 else:
509 prompt_specials = prompt_specials_color
513 prompt_specials = prompt_specials_color
510
514
511 self.color_table.set_active_scheme(colors)
515 self.color_table.set_active_scheme(colors)
512 self.prompt1.set_colors()
516 self.prompt1.set_colors()
513 self.prompt2.set_colors()
517 self.prompt2.set_colors()
514 self.prompt_out.set_colors()
518 self.prompt_out.set_colors()
515
519
516 def __call__(self,arg=None):
520 def __call__(self,arg=None):
517 """Printing with history cache management.
521 """Printing with history cache management.
518
522
519 This is invoked everytime the interpreter needs to print, and is
523 This is invoked everytime the interpreter needs to print, and is
520 activated by setting the variable sys.displayhook to it."""
524 activated by setting the variable sys.displayhook to it."""
521
525
522 # If something injected a '_' variable in __builtin__, delete
526 # If something injected a '_' variable in __builtin__, delete
523 # ipython's automatic one so we don't clobber that. gettext() in
527 # ipython's automatic one so we don't clobber that. gettext() in
524 # particular uses _, so we need to stay away from it.
528 # particular uses _, so we need to stay away from it.
525 if '_' in __builtin__.__dict__:
529 if '_' in __builtin__.__dict__:
526 try:
530 try:
527 del self.user_ns['_']
531 del self.user_ns['_']
528 except KeyError:
532 except KeyError:
529 pass
533 pass
530 if arg is not None:
534 if arg is not None:
531 cout_write = Term.cout.write # fast lookup
535 cout_write = Term.cout.write # fast lookup
532 # first handle the cache and counters
536 # first handle the cache and counters
533
537
534 # do not print output if input ends in ';'
538 # do not print output if input ends in ';'
535 try:
539 try:
536 if self.input_hist[self.prompt_count].endswith(';\n'):
540 if self.input_hist[self.prompt_count].endswith(';\n'):
537 return
541 return
538 except IndexError:
542 except IndexError:
539 # some uses of ipshellembed may fail here
543 # some uses of ipshellembed may fail here
540 pass
544 pass
541 # don't use print, puts an extra space
545 # don't use print, puts an extra space
542 cout_write(self.output_sep)
546 cout_write(self.output_sep)
543 outprompt = self.shell.hooks.generate_output_prompt()
547 outprompt = self.shell.hooks.generate_output_prompt()
544 if self.do_full_cache:
548 if self.do_full_cache:
545 cout_write(outprompt)
549 cout_write(outprompt)
546
550
547 # and now call a possibly user-defined print mechanism
551 # and now call a possibly user-defined print mechanism
548 manipulated_val = self.display(arg)
552 manipulated_val = self.display(arg)
549
553
550 # user display hooks can change the variable to be stored in
554 # user display hooks can change the variable to be stored in
551 # output history
555 # output history
552
556
553 if manipulated_val is not None:
557 if manipulated_val is not None:
554 arg = manipulated_val
558 arg = manipulated_val
555
559
556 # avoid recursive reference when displaying _oh/Out
560 # avoid recursive reference when displaying _oh/Out
557 if arg is not self.user_ns['_oh']:
561 if arg is not self.user_ns['_oh']:
558 self.update(arg)
562 self.update(arg)
559
563
560 if self.logger.log_output:
564 if self.logger.log_output:
561 self.logger.log_write(repr(arg),'output')
565 self.logger.log_write(repr(arg),'output')
562 cout_write(self.output_sep2)
566 cout_write(self.output_sep2)
563 Term.cout.flush()
567 Term.cout.flush()
564
568
565 def _display(self,arg):
569 def _display(self,arg):
566 """Default printer method, uses pprint.
570 """Default printer method, uses pprint.
567
571
568 Do ip.set_hook("result_display", my_displayhook) for custom result
572 Do ip.set_hook("result_display", my_displayhook) for custom result
569 display, e.g. when your own objects need special formatting.
573 display, e.g. when your own objects need special formatting.
570 """
574 """
571 try:
575 try:
572 return IPython.generics.result_display(arg)
576 return IPython.generics.result_display(arg)
573 except TryNext:
577 except TryNext:
574 return self.shell.hooks.result_display(arg)
578 return self.shell.hooks.result_display(arg)
575
579
576 # Assign the default display method:
580 # Assign the default display method:
577 display = _display
581 display = _display
578
582
579 def update(self,arg):
583 def update(self,arg):
580 #print '***cache_count', self.cache_count # dbg
584 #print '***cache_count', self.cache_count # dbg
581 if len(self.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
585 if len(self.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
582 warn('Output cache limit (currently '+
586 warn('Output cache limit (currently '+
583 `self.cache_size`+' entries) hit.\n'
587 `self.cache_size`+' entries) hit.\n'
584 'Flushing cache and resetting history counter...\n'
588 'Flushing cache and resetting history counter...\n'
585 'The only history variables available will be _,__,___ and _1\n'
589 'The only history variables available will be _,__,___ and _1\n'
586 'with the current result.')
590 'with the current result.')
587
591
588 self.flush()
592 self.flush()
589 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
593 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
590 # we cause buggy behavior for things like gettext).
594 # we cause buggy behavior for things like gettext).
591 if '_' not in __builtin__.__dict__:
595 if '_' not in __builtin__.__dict__:
592 self.___ = self.__
596 self.___ = self.__
593 self.__ = self._
597 self.__ = self._
594 self._ = arg
598 self._ = arg
595 self.user_ns.update({'_':self._,'__':self.__,'___':self.___})
599 self.user_ns.update({'_':self._,'__':self.__,'___':self.___})
596
600
597 # hackish access to top-level namespace to create _1,_2... dynamically
601 # hackish access to top-level namespace to create _1,_2... dynamically
598 to_main = {}
602 to_main = {}
599 if self.do_full_cache:
603 if self.do_full_cache:
600 new_result = '_'+`self.prompt_count`
604 new_result = '_'+`self.prompt_count`
601 to_main[new_result] = arg
605 to_main[new_result] = arg
602 self.user_ns.update(to_main)
606 self.user_ns.update(to_main)
603 self.user_ns['_oh'][self.prompt_count] = arg
607 self.user_ns['_oh'][self.prompt_count] = arg
604
608
605 def flush(self):
609 def flush(self):
606 if not self.do_full_cache:
610 if not self.do_full_cache:
607 raise ValueError,"You shouldn't have reached the cache flush "\
611 raise ValueError,"You shouldn't have reached the cache flush "\
608 "if full caching is not enabled!"
612 "if full caching is not enabled!"
609 # delete auto-generated vars from global namespace
613 # delete auto-generated vars from global namespace
610
614
611 for n in range(1,self.prompt_count + 1):
615 for n in range(1,self.prompt_count + 1):
612 key = '_'+`n`
616 key = '_'+`n`
613 try:
617 try:
614 del self.user_ns[key]
618 del self.user_ns[key]
615 except: pass
619 except: pass
616 self.user_ns['_oh'].clear()
620 self.user_ns['_oh'].clear()
617
621
618 if '_' not in __builtin__.__dict__:
622 if '_' not in __builtin__.__dict__:
619 self.user_ns.update({'_':None,'__':None, '___':None})
623 self.user_ns.update({'_':None,'__':None, '___':None})
620 import gc
624 import gc
621 gc.collect() # xxx needed?
625 gc.collect() # xxx needed?
622
626
@@ -1,121 +1,121 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Release data for the IPython project."""
2 """Release data for the IPython project."""
3
3
4 #*****************************************************************************
4 #*****************************************************************************
5 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
5 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
6 #
6 #
7 # Copyright (c) 2001 Janko Hauser <jhauser@zscout.de> and Nathaniel Gray
7 # Copyright (c) 2001 Janko Hauser <jhauser@zscout.de> and Nathaniel Gray
8 # <n8gray@caltech.edu>
8 # <n8gray@caltech.edu>
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #*****************************************************************************
12 #*****************************************************************************
13
13
14 # Name of the package for release purposes. This is the name which labels
14 # Name of the package for release purposes. This is the name which labels
15 # the tarballs and RPMs made by distutils, so it's best to lowercase it.
15 # the tarballs and RPMs made by distutils, so it's best to lowercase it.
16 name = 'ipython'
16 name = 'ipython'
17
17
18 # For versions with substrings (like 0.6.16.svn), use an extra . to separate
18 # For versions with substrings (like 0.6.16.svn), use an extra . to separate
19 # the new substring. We have to avoid using either dashes or underscores,
19 # the new substring. We have to avoid using either dashes or underscores,
20 # because bdist_rpm does not accept dashes (an RPM) convention, and
20 # because bdist_rpm does not accept dashes (an RPM) convention, and
21 # bdist_deb does not accept underscores (a Debian convention).
21 # bdist_deb does not accept underscores (a Debian convention).
22
22
23 development = False # change this to False to do a release
23 development = True # change this to False to do a release
24 version_base = '0.9.1'
24 version_base = '0.10'
25 branch = 'ipython'
25 branch = 'ipython'
26 revision = '1143'
26 revision = '1163'
27
27
28 if development:
28 if development:
29 if branch == 'ipython':
29 if branch == 'ipython':
30 version = '%s.bzr.r%s' % (version_base, revision)
30 version = '%s.bzr.r%s' % (version_base, revision)
31 else:
31 else:
32 version = '%s.bzr.r%s.%s' % (version_base, revision, branch)
32 version = '%s.bzr.r%s.%s' % (version_base, revision, branch)
33 else:
33 else:
34 version = version_base
34 version = version_base
35
35
36
36
37 description = "An interactive computing environment for Python"
37 description = "An interactive computing environment for Python"
38
38
39 long_description = \
39 long_description = \
40 """
40 """
41 The goal of IPython is to create a comprehensive environment for
41 The goal of IPython is to create a comprehensive environment for
42 interactive and exploratory computing. To support this goal, IPython
42 interactive and exploratory computing. To support this goal, IPython
43 has two main components:
43 has two main components:
44
44
45 * An enhanced interactive Python shell.
45 * An enhanced interactive Python shell.
46
46
47 * An architecture for interactive parallel computing.
47 * An architecture for interactive parallel computing.
48
48
49 The enhanced interactive Python shell has the following main features:
49 The enhanced interactive Python shell has the following main features:
50
50
51 * Comprehensive object introspection.
51 * Comprehensive object introspection.
52
52
53 * Input history, persistent across sessions.
53 * Input history, persistent across sessions.
54
54
55 * Caching of output results during a session with automatically generated
55 * Caching of output results during a session with automatically generated
56 references.
56 references.
57
57
58 * Readline based name completion.
58 * Readline based name completion.
59
59
60 * Extensible system of 'magic' commands for controlling the environment and
60 * Extensible system of 'magic' commands for controlling the environment and
61 performing many tasks related either to IPython or the operating system.
61 performing many tasks related either to IPython or the operating system.
62
62
63 * Configuration system with easy switching between different setups (simpler
63 * Configuration system with easy switching between different setups (simpler
64 than changing $PYTHONSTARTUP environment variables every time).
64 than changing $PYTHONSTARTUP environment variables every time).
65
65
66 * Session logging and reloading.
66 * Session logging and reloading.
67
67
68 * Extensible syntax processing for special purpose situations.
68 * Extensible syntax processing for special purpose situations.
69
69
70 * Access to the system shell with user-extensible alias system.
70 * Access to the system shell with user-extensible alias system.
71
71
72 * Easily embeddable in other Python programs and wxPython GUIs.
72 * Easily embeddable in other Python programs and wxPython GUIs.
73
73
74 * Integrated access to the pdb debugger and the Python profiler.
74 * Integrated access to the pdb debugger and the Python profiler.
75
75
76 The parallel computing architecture has the following main features:
76 The parallel computing architecture has the following main features:
77
77
78 * Quickly parallelize Python code from an interactive Python/IPython session.
78 * Quickly parallelize Python code from an interactive Python/IPython session.
79
79
80 * A flexible and dynamic process model that be deployed on anything from
80 * A flexible and dynamic process model that be deployed on anything from
81 multicore workstations to supercomputers.
81 multicore workstations to supercomputers.
82
82
83 * An architecture that supports many different styles of parallelism, from
83 * An architecture that supports many different styles of parallelism, from
84 message passing to task farming.
84 message passing to task farming.
85
85
86 * Both blocking and fully asynchronous interfaces.
86 * Both blocking and fully asynchronous interfaces.
87
87
88 * High level APIs that enable many things to be parallelized in a few lines
88 * High level APIs that enable many things to be parallelized in a few lines
89 of code.
89 of code.
90
90
91 * Share live parallel jobs with other users securely.
91 * Share live parallel jobs with other users securely.
92
92
93 * Dynamically load balanced task farming system.
93 * Dynamically load balanced task farming system.
94
94
95 * Robust error handling in parallel code.
95 * Robust error handling in parallel code.
96
96
97 The latest development version is always available from IPython's `Launchpad
97 The latest development version is always available from IPython's `Launchpad
98 site <http://launchpad.net/ipython>`_.
98 site <http://launchpad.net/ipython>`_.
99 """
99 """
100
100
101 license = 'BSD'
101 license = 'BSD'
102
102
103 authors = {'Fernando' : ('Fernando Perez','fperez@colorado.edu'),
103 authors = {'Fernando' : ('Fernando Perez','fperez@colorado.edu'),
104 'Janko' : ('Janko Hauser','jhauser@zscout.de'),
104 'Janko' : ('Janko Hauser','jhauser@zscout.de'),
105 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'),
105 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'),
106 'Ville' : ('Ville Vainio','vivainio@gmail.com'),
106 'Ville' : ('Ville Vainio','vivainio@gmail.com'),
107 'Brian' : ('Brian E Granger', 'ellisonbg@gmail.com'),
107 'Brian' : ('Brian E Granger', 'ellisonbg@gmail.com'),
108 'Min' : ('Min Ragan-Kelley', 'benjaminrk@gmail.com')
108 'Min' : ('Min Ragan-Kelley', 'benjaminrk@gmail.com')
109 }
109 }
110
110
111 author = 'The IPython Development Team'
111 author = 'The IPython Development Team'
112
112
113 author_email = 'ipython-dev@scipy.org'
113 author_email = 'ipython-dev@scipy.org'
114
114
115 url = 'http://ipython.scipy.org'
115 url = 'http://ipython.scipy.org'
116
116
117 download_url = 'http://ipython.scipy.org/dist'
117 download_url = 'http://ipython.scipy.org/dist'
118
118
119 platforms = ['Linux','Mac OSX','Windows XP/2000/NT','Windows 95/98/ME']
119 platforms = ['Linux','Mac OSX','Windows XP/2000/NT','Windows 95/98/ME']
120
120
121 keywords = ['Interactive','Interpreter','Shell','Parallel','Distributed']
121 keywords = ['Interactive','Interpreter','Shell','Parallel','Distributed']
@@ -1,1244 +1,1246 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """IPython Shell classes.
2 """IPython Shell classes.
3
3
4 All the matplotlib support code was co-developed with John Hunter,
4 All the matplotlib support code was co-developed with John Hunter,
5 matplotlib's author.
5 matplotlib's author.
6 """
6 """
7
7
8 #*****************************************************************************
8 #*****************************************************************************
9 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
9 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #*****************************************************************************
13 #*****************************************************************************
14
14
15 # Code begins
15 # Code begins
16 # Stdlib imports
16 # Stdlib imports
17 import __builtin__
17 import __builtin__
18 import __main__
18 import __main__
19 import Queue
19 import Queue
20 import inspect
20 import inspect
21 import os
21 import os
22 import sys
22 import sys
23 import thread
23 import thread
24 import threading
24 import threading
25 import time
25 import time
26
26
27 from signal import signal, SIGINT
27 from signal import signal, SIGINT
28
28
29 try:
29 try:
30 import ctypes
30 import ctypes
31 HAS_CTYPES = True
31 HAS_CTYPES = True
32 except ImportError:
32 except ImportError:
33 HAS_CTYPES = False
33 HAS_CTYPES = False
34
34
35 # IPython imports
35 # IPython imports
36 import IPython
36 import IPython
37 from IPython import ultraTB, ipapi
37 from IPython import ultraTB, ipapi
38 from IPython.Magic import Magic
38 from IPython.Magic import Magic
39 from IPython.genutils import Term,warn,error,flag_calls, ask_yes_no
39 from IPython.genutils import Term,warn,error,flag_calls, ask_yes_no
40 from IPython.iplib import InteractiveShell
40 from IPython.iplib import InteractiveShell
41 from IPython.ipmaker import make_IPython
41 from IPython.ipmaker import make_IPython
42 from IPython.ipstruct import Struct
42 from IPython.ipstruct import Struct
43 from IPython.testing import decorators as testdec
43 from IPython.testing import decorators as testdec
44
44
45 # Globals
45 # Globals
46 # global flag to pass around information about Ctrl-C without exceptions
46 # global flag to pass around information about Ctrl-C without exceptions
47 KBINT = False
47 KBINT = False
48
48
49 # global flag to turn on/off Tk support.
49 # global flag to turn on/off Tk support.
50 USE_TK = False
50 USE_TK = False
51
51
52 # ID for the main thread, used for cross-thread exceptions
52 # ID for the main thread, used for cross-thread exceptions
53 MAIN_THREAD_ID = thread.get_ident()
53 MAIN_THREAD_ID = thread.get_ident()
54
54
55 # Tag when runcode() is active, for exception handling
55 # Tag when runcode() is active, for exception handling
56 CODE_RUN = None
56 CODE_RUN = None
57
57
58 # Default timeout for waiting for multithreaded shells (in seconds)
58 # Default timeout for waiting for multithreaded shells (in seconds)
59 GUI_TIMEOUT = 10
59 GUI_TIMEOUT = 10
60
60
61 #-----------------------------------------------------------------------------
61 #-----------------------------------------------------------------------------
62 # This class is trivial now, but I want to have it in to publish a clean
62 # This class is trivial now, but I want to have it in to publish a clean
63 # interface. Later when the internals are reorganized, code that uses this
63 # interface. Later when the internals are reorganized, code that uses this
64 # shouldn't have to change.
64 # shouldn't have to change.
65
65
66 class IPShell:
66 class IPShell:
67 """Create an IPython instance."""
67 """Create an IPython instance."""
68
68
69 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
69 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
70 debug=1,shell_class=InteractiveShell):
70 debug=1,shell_class=InteractiveShell):
71 self.IP = make_IPython(argv,user_ns=user_ns,
71 self.IP = make_IPython(argv,user_ns=user_ns,
72 user_global_ns=user_global_ns,
72 user_global_ns=user_global_ns,
73 debug=debug,shell_class=shell_class)
73 debug=debug,shell_class=shell_class)
74
74
75 def mainloop(self,sys_exit=0,banner=None):
75 def mainloop(self,sys_exit=0,banner=None):
76 self.IP.mainloop(banner)
76 self.IP.mainloop(banner)
77 if sys_exit:
77 if sys_exit:
78 sys.exit()
78 sys.exit()
79
79
80 #-----------------------------------------------------------------------------
80 #-----------------------------------------------------------------------------
81 def kill_embedded(self,parameter_s=''):
81 def kill_embedded(self,parameter_s=''):
82 """%kill_embedded : deactivate for good the current embedded IPython.
82 """%kill_embedded : deactivate for good the current embedded IPython.
83
83
84 This function (after asking for confirmation) sets an internal flag so that
84 This function (after asking for confirmation) sets an internal flag so that
85 an embedded IPython will never activate again. This is useful to
85 an embedded IPython will never activate again. This is useful to
86 permanently disable a shell that is being called inside a loop: once you've
86 permanently disable a shell that is being called inside a loop: once you've
87 figured out what you needed from it, you may then kill it and the program
87 figured out what you needed from it, you may then kill it and the program
88 will then continue to run without the interactive shell interfering again.
88 will then continue to run without the interactive shell interfering again.
89 """
89 """
90
90
91 kill = ask_yes_no("Are you sure you want to kill this embedded instance "
91 kill = ask_yes_no("Are you sure you want to kill this embedded instance "
92 "(y/n)? [y/N] ",'n')
92 "(y/n)? [y/N] ",'n')
93 if kill:
93 if kill:
94 self.shell.embedded_active = False
94 self.shell.embedded_active = False
95 print "This embedded IPython will not reactivate anymore once you exit."
95 print "This embedded IPython will not reactivate anymore once you exit."
96
96
97 class IPShellEmbed:
97 class IPShellEmbed:
98 """Allow embedding an IPython shell into a running program.
98 """Allow embedding an IPython shell into a running program.
99
99
100 Instances of this class are callable, with the __call__ method being an
100 Instances of this class are callable, with the __call__ method being an
101 alias to the embed() method of an InteractiveShell instance.
101 alias to the embed() method of an InteractiveShell instance.
102
102
103 Usage (see also the example-embed.py file for a running example):
103 Usage (see also the example-embed.py file for a running example):
104
104
105 ipshell = IPShellEmbed([argv,banner,exit_msg,rc_override])
105 ipshell = IPShellEmbed([argv,banner,exit_msg,rc_override])
106
106
107 - argv: list containing valid command-line options for IPython, as they
107 - argv: list containing valid command-line options for IPython, as they
108 would appear in sys.argv[1:].
108 would appear in sys.argv[1:].
109
109
110 For example, the following command-line options:
110 For example, the following command-line options:
111
111
112 $ ipython -prompt_in1 'Input <\\#>' -colors LightBG
112 $ ipython -prompt_in1 'Input <\\#>' -colors LightBG
113
113
114 would be passed in the argv list as:
114 would be passed in the argv list as:
115
115
116 ['-prompt_in1','Input <\\#>','-colors','LightBG']
116 ['-prompt_in1','Input <\\#>','-colors','LightBG']
117
117
118 - banner: string which gets printed every time the interpreter starts.
118 - banner: string which gets printed every time the interpreter starts.
119
119
120 - exit_msg: string which gets printed every time the interpreter exits.
120 - exit_msg: string which gets printed every time the interpreter exits.
121
121
122 - rc_override: a dict or Struct of configuration options such as those
122 - rc_override: a dict or Struct of configuration options such as those
123 used by IPython. These options are read from your ~/.ipython/ipythonrc
123 used by IPython. These options are read from your ~/.ipython/ipythonrc
124 file when the Shell object is created. Passing an explicit rc_override
124 file when the Shell object is created. Passing an explicit rc_override
125 dict with any options you want allows you to override those values at
125 dict with any options you want allows you to override those values at
126 creation time without having to modify the file. This way you can create
126 creation time without having to modify the file. This way you can create
127 embeddable instances configured in any way you want without editing any
127 embeddable instances configured in any way you want without editing any
128 global files (thus keeping your interactive IPython configuration
128 global files (thus keeping your interactive IPython configuration
129 unchanged).
129 unchanged).
130
130
131 Then the ipshell instance can be called anywhere inside your code:
131 Then the ipshell instance can be called anywhere inside your code:
132
132
133 ipshell(header='') -> Opens up an IPython shell.
133 ipshell(header='') -> Opens up an IPython shell.
134
134
135 - header: string printed by the IPython shell upon startup. This can let
135 - header: string printed by the IPython shell upon startup. This can let
136 you know where in your code you are when dropping into the shell. Note
136 you know where in your code you are when dropping into the shell. Note
137 that 'banner' gets prepended to all calls, so header is used for
137 that 'banner' gets prepended to all calls, so header is used for
138 location-specific information.
138 location-specific information.
139
139
140 For more details, see the __call__ method below.
140 For more details, see the __call__ method below.
141
141
142 When the IPython shell is exited with Ctrl-D, normal program execution
142 When the IPython shell is exited with Ctrl-D, normal program execution
143 resumes.
143 resumes.
144
144
145 This functionality was inspired by a posting on comp.lang.python by cmkl
145 This functionality was inspired by a posting on comp.lang.python by cmkl
146 <cmkleffner@gmx.de> on Dec. 06/01 concerning similar uses of pyrepl, and
146 <cmkleffner@gmx.de> on Dec. 06/01 concerning similar uses of pyrepl, and
147 by the IDL stop/continue commands."""
147 by the IDL stop/continue commands."""
148
148
149 def __init__(self,argv=None,banner='',exit_msg=None,rc_override=None,
149 def __init__(self,argv=None,banner='',exit_msg=None,rc_override=None,
150 user_ns=None):
150 user_ns=None):
151 """Note that argv here is a string, NOT a list."""
151 """Note that argv here is a string, NOT a list."""
152 self.set_banner(banner)
152 self.set_banner(banner)
153 self.set_exit_msg(exit_msg)
153 self.set_exit_msg(exit_msg)
154 self.set_dummy_mode(0)
154 self.set_dummy_mode(0)
155
155
156 # sys.displayhook is a global, we need to save the user's original
156 # sys.displayhook is a global, we need to save the user's original
157 # Don't rely on __displayhook__, as the user may have changed that.
157 # Don't rely on __displayhook__, as the user may have changed that.
158 self.sys_displayhook_ori = sys.displayhook
158 self.sys_displayhook_ori = sys.displayhook
159
159
160 # save readline completer status
160 # save readline completer status
161 try:
161 try:
162 #print 'Save completer',sys.ipcompleter # dbg
162 #print 'Save completer',sys.ipcompleter # dbg
163 self.sys_ipcompleter_ori = sys.ipcompleter
163 self.sys_ipcompleter_ori = sys.ipcompleter
164 except:
164 except:
165 pass # not nested with IPython
165 pass # not nested with IPython
166
166
167 self.IP = make_IPython(argv,rc_override=rc_override,
167 self.IP = make_IPython(argv,rc_override=rc_override,
168 embedded=True,
168 embedded=True,
169 user_ns=user_ns)
169 user_ns=user_ns)
170
170
171 ip = ipapi.IPApi(self.IP)
171 ip = ipapi.IPApi(self.IP)
172 ip.expose_magic("kill_embedded",kill_embedded)
172 ip.expose_magic("kill_embedded",kill_embedded)
173
173
174 # copy our own displayhook also
174 # copy our own displayhook also
175 self.sys_displayhook_embed = sys.displayhook
175 self.sys_displayhook_embed = sys.displayhook
176 # and leave the system's display hook clean
176 # and leave the system's display hook clean
177 sys.displayhook = self.sys_displayhook_ori
177 sys.displayhook = self.sys_displayhook_ori
178 # don't use the ipython crash handler so that user exceptions aren't
178 # don't use the ipython crash handler so that user exceptions aren't
179 # trapped
179 # trapped
180 sys.excepthook = ultraTB.FormattedTB(color_scheme = self.IP.rc.colors,
180 sys.excepthook = ultraTB.FormattedTB(color_scheme = self.IP.rc.colors,
181 mode = self.IP.rc.xmode,
181 mode = self.IP.rc.xmode,
182 call_pdb = self.IP.rc.pdb)
182 call_pdb = self.IP.rc.pdb)
183 self.restore_system_completer()
183 self.restore_system_completer()
184
184
185 def restore_system_completer(self):
185 def restore_system_completer(self):
186 """Restores the readline completer which was in place.
186 """Restores the readline completer which was in place.
187
187
188 This allows embedded IPython within IPython not to disrupt the
188 This allows embedded IPython within IPython not to disrupt the
189 parent's completion.
189 parent's completion.
190 """
190 """
191
191
192 try:
192 try:
193 self.IP.readline.set_completer(self.sys_ipcompleter_ori)
193 self.IP.readline.set_completer(self.sys_ipcompleter_ori)
194 sys.ipcompleter = self.sys_ipcompleter_ori
194 sys.ipcompleter = self.sys_ipcompleter_ori
195 except:
195 except:
196 pass
196 pass
197
197
198 def __call__(self,header='',local_ns=None,global_ns=None,dummy=None):
198 def __call__(self,header='',local_ns=None,global_ns=None,dummy=None):
199 """Activate the interactive interpreter.
199 """Activate the interactive interpreter.
200
200
201 __call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start
201 __call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start
202 the interpreter shell with the given local and global namespaces, and
202 the interpreter shell with the given local and global namespaces, and
203 optionally print a header string at startup.
203 optionally print a header string at startup.
204
204
205 The shell can be globally activated/deactivated using the
205 The shell can be globally activated/deactivated using the
206 set/get_dummy_mode methods. This allows you to turn off a shell used
206 set/get_dummy_mode methods. This allows you to turn off a shell used
207 for debugging globally.
207 for debugging globally.
208
208
209 However, *each* time you call the shell you can override the current
209 However, *each* time you call the shell you can override the current
210 state of dummy_mode with the optional keyword parameter 'dummy'. For
210 state of dummy_mode with the optional keyword parameter 'dummy'. For
211 example, if you set dummy mode on with IPShell.set_dummy_mode(1), you
211 example, if you set dummy mode on with IPShell.set_dummy_mode(1), you
212 can still have a specific call work by making it as IPShell(dummy=0).
212 can still have a specific call work by making it as IPShell(dummy=0).
213
213
214 The optional keyword parameter dummy controls whether the call
214 The optional keyword parameter dummy controls whether the call
215 actually does anything. """
215 actually does anything. """
216
216
217 # If the user has turned it off, go away
217 # If the user has turned it off, go away
218 if not self.IP.embedded_active:
218 if not self.IP.embedded_active:
219 return
219 return
220
220
221 # Normal exits from interactive mode set this flag, so the shell can't
221 # Normal exits from interactive mode set this flag, so the shell can't
222 # re-enter (it checks this variable at the start of interactive mode).
222 # re-enter (it checks this variable at the start of interactive mode).
223 self.IP.exit_now = False
223 self.IP.exit_now = False
224
224
225 # Allow the dummy parameter to override the global __dummy_mode
225 # Allow the dummy parameter to override the global __dummy_mode
226 if dummy or (dummy != 0 and self.__dummy_mode):
226 if dummy or (dummy != 0 and self.__dummy_mode):
227 return
227 return
228
228
229 # Set global subsystems (display,completions) to our values
229 # Set global subsystems (display,completions) to our values
230 sys.displayhook = self.sys_displayhook_embed
230 sys.displayhook = self.sys_displayhook_embed
231 if self.IP.has_readline:
231 if self.IP.has_readline:
232 self.IP.set_completer()
232 self.IP.set_completer()
233
233
234 if self.banner and header:
234 if self.banner and header:
235 format = '%s\n%s\n'
235 format = '%s\n%s\n'
236 else:
236 else:
237 format = '%s%s\n'
237 format = '%s%s\n'
238 banner = format % (self.banner,header)
238 banner = format % (self.banner,header)
239
239
240 # Call the embedding code with a stack depth of 1 so it can skip over
240 # Call the embedding code with a stack depth of 1 so it can skip over
241 # our call and get the original caller's namespaces.
241 # our call and get the original caller's namespaces.
242 self.IP.embed_mainloop(banner,local_ns,global_ns,stack_depth=1)
242 self.IP.embed_mainloop(banner,local_ns,global_ns,stack_depth=1)
243
243
244 if self.exit_msg:
244 if self.exit_msg:
245 print self.exit_msg
245 print self.exit_msg
246
246
247 # Restore global systems (display, completion)
247 # Restore global systems (display, completion)
248 sys.displayhook = self.sys_displayhook_ori
248 sys.displayhook = self.sys_displayhook_ori
249 self.restore_system_completer()
249 self.restore_system_completer()
250
250
251 def set_dummy_mode(self,dummy):
251 def set_dummy_mode(self,dummy):
252 """Sets the embeddable shell's dummy mode parameter.
252 """Sets the embeddable shell's dummy mode parameter.
253
253
254 set_dummy_mode(dummy): dummy = 0 or 1.
254 set_dummy_mode(dummy): dummy = 0 or 1.
255
255
256 This parameter is persistent and makes calls to the embeddable shell
256 This parameter is persistent and makes calls to the embeddable shell
257 silently return without performing any action. This allows you to
257 silently return without performing any action. This allows you to
258 globally activate or deactivate a shell you're using with a single call.
258 globally activate or deactivate a shell you're using with a single call.
259
259
260 If you need to manually"""
260 If you need to manually"""
261
261
262 if dummy not in [0,1,False,True]:
262 if dummy not in [0,1,False,True]:
263 raise ValueError,'dummy parameter must be boolean'
263 raise ValueError,'dummy parameter must be boolean'
264 self.__dummy_mode = dummy
264 self.__dummy_mode = dummy
265
265
266 def get_dummy_mode(self):
266 def get_dummy_mode(self):
267 """Return the current value of the dummy mode parameter.
267 """Return the current value of the dummy mode parameter.
268 """
268 """
269 return self.__dummy_mode
269 return self.__dummy_mode
270
270
271 def set_banner(self,banner):
271 def set_banner(self,banner):
272 """Sets the global banner.
272 """Sets the global banner.
273
273
274 This banner gets prepended to every header printed when the shell
274 This banner gets prepended to every header printed when the shell
275 instance is called."""
275 instance is called."""
276
276
277 self.banner = banner
277 self.banner = banner
278
278
279 def set_exit_msg(self,exit_msg):
279 def set_exit_msg(self,exit_msg):
280 """Sets the global exit_msg.
280 """Sets the global exit_msg.
281
281
282 This exit message gets printed upon exiting every time the embedded
282 This exit message gets printed upon exiting every time the embedded
283 shell is called. It is None by default. """
283 shell is called. It is None by default. """
284
284
285 self.exit_msg = exit_msg
285 self.exit_msg = exit_msg
286
286
287 #-----------------------------------------------------------------------------
287 #-----------------------------------------------------------------------------
288 if HAS_CTYPES:
288 if HAS_CTYPES:
289 # Add async exception support. Trick taken from:
289 # Add async exception support. Trick taken from:
290 # http://sebulba.wikispaces.com/recipe+thread2
290 # http://sebulba.wikispaces.com/recipe+thread2
291 def _async_raise(tid, exctype):
291 def _async_raise(tid, exctype):
292 """raises the exception, performs cleanup if needed"""
292 """raises the exception, performs cleanup if needed"""
293 if not inspect.isclass(exctype):
293 if not inspect.isclass(exctype):
294 raise TypeError("Only types can be raised (not instances)")
294 raise TypeError("Only types can be raised (not instances)")
295 res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,
295 # Explicit cast to c_long is necessary for 64-bit support:
296 # See https://bugs.launchpad.net/ipython/+bug/237073
297 res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid),
296 ctypes.py_object(exctype))
298 ctypes.py_object(exctype))
297 if res == 0:
299 if res == 0:
298 raise ValueError("invalid thread id")
300 raise ValueError("invalid thread id")
299 elif res != 1:
301 elif res != 1:
300 # """if it returns a number greater than one, you're in trouble,
302 # If it returns a number greater than one, you're in trouble,
301 # and you should call it again with exc=NULL to revert the effect"""
303 # and you should call it again with exc=NULL to revert the effect
302 ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
304 ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
303 raise SystemError("PyThreadState_SetAsyncExc failed")
305 raise SystemError("PyThreadState_SetAsyncExc failed")
304
306
305 def sigint_handler (signum,stack_frame):
307 def sigint_handler(signum,stack_frame):
306 """Sigint handler for threaded apps.
308 """Sigint handler for threaded apps.
307
309
308 This is a horrible hack to pass information about SIGINT _without_
310 This is a horrible hack to pass information about SIGINT _without_
309 using exceptions, since I haven't been able to properly manage
311 using exceptions, since I haven't been able to properly manage
310 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
312 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
311 done (or at least that's my understanding from a c.l.py thread where
313 done (or at least that's my understanding from a c.l.py thread where
312 this was discussed)."""
314 this was discussed)."""
313
315
314 global KBINT
316 global KBINT
315
317
316 if CODE_RUN:
318 if CODE_RUN:
317 _async_raise(MAIN_THREAD_ID,KeyboardInterrupt)
319 _async_raise(MAIN_THREAD_ID,KeyboardInterrupt)
318 else:
320 else:
319 KBINT = True
321 KBINT = True
320 print '\nKeyboardInterrupt - Press <Enter> to continue.',
322 print '\nKeyboardInterrupt - Press <Enter> to continue.',
321 Term.cout.flush()
323 Term.cout.flush()
322
324
323 else:
325 else:
324 def sigint_handler (signum,stack_frame):
326 def sigint_handler(signum,stack_frame):
325 """Sigint handler for threaded apps.
327 """Sigint handler for threaded apps.
326
328
327 This is a horrible hack to pass information about SIGINT _without_
329 This is a horrible hack to pass information about SIGINT _without_
328 using exceptions, since I haven't been able to properly manage
330 using exceptions, since I haven't been able to properly manage
329 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
331 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
330 done (or at least that's my understanding from a c.l.py thread where
332 done (or at least that's my understanding from a c.l.py thread where
331 this was discussed)."""
333 this was discussed)."""
332
334
333 global KBINT
335 global KBINT
334
336
335 print '\nKeyboardInterrupt - Press <Enter> to continue.',
337 print '\nKeyboardInterrupt - Press <Enter> to continue.',
336 Term.cout.flush()
338 Term.cout.flush()
337 # Set global flag so that runsource can know that Ctrl-C was hit
339 # Set global flag so that runsource can know that Ctrl-C was hit
338 KBINT = True
340 KBINT = True
339
341
340
342
341 class MTInteractiveShell(InteractiveShell):
343 class MTInteractiveShell(InteractiveShell):
342 """Simple multi-threaded shell."""
344 """Simple multi-threaded shell."""
343
345
344 # Threading strategy taken from:
346 # Threading strategy taken from:
345 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65109, by Brian
347 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65109, by Brian
346 # McErlean and John Finlay. Modified with corrections by Antoon Pardon,
348 # McErlean and John Finlay. Modified with corrections by Antoon Pardon,
347 # from the pygtk mailing list, to avoid lockups with system calls.
349 # from the pygtk mailing list, to avoid lockups with system calls.
348
350
349 # class attribute to indicate whether the class supports threads or not.
351 # class attribute to indicate whether the class supports threads or not.
350 # Subclasses with thread support should override this as needed.
352 # Subclasses with thread support should override this as needed.
351 isthreaded = True
353 isthreaded = True
352
354
353 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
355 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
354 user_ns=None,user_global_ns=None,banner2='',
356 user_ns=None,user_global_ns=None,banner2='',
355 gui_timeout=GUI_TIMEOUT,**kw):
357 gui_timeout=GUI_TIMEOUT,**kw):
356 """Similar to the normal InteractiveShell, but with threading control"""
358 """Similar to the normal InteractiveShell, but with threading control"""
357
359
358 InteractiveShell.__init__(self,name,usage,rc,user_ns,
360 InteractiveShell.__init__(self,name,usage,rc,user_ns,
359 user_global_ns,banner2)
361 user_global_ns,banner2)
360
362
361 # Timeout we wait for GUI thread
363 # Timeout we wait for GUI thread
362 self.gui_timeout = gui_timeout
364 self.gui_timeout = gui_timeout
363
365
364 # A queue to hold the code to be executed.
366 # A queue to hold the code to be executed.
365 self.code_queue = Queue.Queue()
367 self.code_queue = Queue.Queue()
366
368
367 # Stuff to do at closing time
369 # Stuff to do at closing time
368 self._kill = None
370 self._kill = None
369 on_kill = kw.get('on_kill', [])
371 on_kill = kw.get('on_kill', [])
370 # Check that all things to kill are callable:
372 # Check that all things to kill are callable:
371 for t in on_kill:
373 for t in on_kill:
372 if not callable(t):
374 if not callable(t):
373 raise TypeError,'on_kill must be a list of callables'
375 raise TypeError,'on_kill must be a list of callables'
374 self.on_kill = on_kill
376 self.on_kill = on_kill
375 # thread identity of the "worker thread" (that may execute code directly)
377 # thread identity of the "worker thread" (that may execute code directly)
376 self.worker_ident = None
378 self.worker_ident = None
377
379
378 def runsource(self, source, filename="<input>", symbol="single"):
380 def runsource(self, source, filename="<input>", symbol="single"):
379 """Compile and run some source in the interpreter.
381 """Compile and run some source in the interpreter.
380
382
381 Modified version of code.py's runsource(), to handle threading issues.
383 Modified version of code.py's runsource(), to handle threading issues.
382 See the original for full docstring details."""
384 See the original for full docstring details."""
383
385
384 global KBINT
386 global KBINT
385
387
386 # If Ctrl-C was typed, we reset the flag and return right away
388 # If Ctrl-C was typed, we reset the flag and return right away
387 if KBINT:
389 if KBINT:
388 KBINT = False
390 KBINT = False
389 return False
391 return False
390
392
391 if self._kill:
393 if self._kill:
392 # can't queue new code if we are being killed
394 # can't queue new code if we are being killed
393 return True
395 return True
394
396
395 try:
397 try:
396 code = self.compile(source, filename, symbol)
398 code = self.compile(source, filename, symbol)
397 except (OverflowError, SyntaxError, ValueError):
399 except (OverflowError, SyntaxError, ValueError):
398 # Case 1
400 # Case 1
399 self.showsyntaxerror(filename)
401 self.showsyntaxerror(filename)
400 return False
402 return False
401
403
402 if code is None:
404 if code is None:
403 # Case 2
405 # Case 2
404 return True
406 return True
405
407
406 # shortcut - if we are in worker thread, or the worker thread is not
408 # shortcut - if we are in worker thread, or the worker thread is not
407 # running, execute directly (to allow recursion and prevent deadlock if
409 # running, execute directly (to allow recursion and prevent deadlock if
408 # code is run early in IPython construction)
410 # code is run early in IPython construction)
409
411
410 if (self.worker_ident is None
412 if (self.worker_ident is None
411 or self.worker_ident == thread.get_ident() ):
413 or self.worker_ident == thread.get_ident() ):
412 InteractiveShell.runcode(self,code)
414 InteractiveShell.runcode(self,code)
413 return False
415 return False
414
416
415 # Case 3
417 # Case 3
416 # Store code in queue, so the execution thread can handle it.
418 # Store code in queue, so the execution thread can handle it.
417
419
418 completed_ev, received_ev = threading.Event(), threading.Event()
420 completed_ev, received_ev = threading.Event(), threading.Event()
419
421
420 self.code_queue.put((code,completed_ev, received_ev))
422 self.code_queue.put((code,completed_ev, received_ev))
421 # first make sure the message was received, with timeout
423 # first make sure the message was received, with timeout
422 received_ev.wait(self.gui_timeout)
424 received_ev.wait(self.gui_timeout)
423 if not received_ev.isSet():
425 if not received_ev.isSet():
424 # the mainloop is dead, start executing code directly
426 # the mainloop is dead, start executing code directly
425 print "Warning: Timeout for mainloop thread exceeded"
427 print "Warning: Timeout for mainloop thread exceeded"
426 print "switching to nonthreaded mode (until mainloop wakes up again)"
428 print "switching to nonthreaded mode (until mainloop wakes up again)"
427 self.worker_ident = None
429 self.worker_ident = None
428 else:
430 else:
429 completed_ev.wait()
431 completed_ev.wait()
430 return False
432 return False
431
433
432 def runcode(self):
434 def runcode(self):
433 """Execute a code object.
435 """Execute a code object.
434
436
435 Multithreaded wrapper around IPython's runcode()."""
437 Multithreaded wrapper around IPython's runcode()."""
436
438
437 global CODE_RUN
439 global CODE_RUN
438
440
439 # we are in worker thread, stash out the id for runsource()
441 # we are in worker thread, stash out the id for runsource()
440 self.worker_ident = thread.get_ident()
442 self.worker_ident = thread.get_ident()
441
443
442 if self._kill:
444 if self._kill:
443 print >>Term.cout, 'Closing threads...',
445 print >>Term.cout, 'Closing threads...',
444 Term.cout.flush()
446 Term.cout.flush()
445 for tokill in self.on_kill:
447 for tokill in self.on_kill:
446 tokill()
448 tokill()
447 print >>Term.cout, 'Done.'
449 print >>Term.cout, 'Done.'
448 # allow kill() to return
450 # allow kill() to return
449 self._kill.set()
451 self._kill.set()
450 return True
452 return True
451
453
452 # Install sigint handler. We do it every time to ensure that if user
454 # Install sigint handler. We do it every time to ensure that if user
453 # code modifies it, we restore our own handling.
455 # code modifies it, we restore our own handling.
454 try:
456 try:
455 signal(SIGINT,sigint_handler)
457 signal(SIGINT,sigint_handler)
456 except SystemError:
458 except SystemError:
457 # This happens under Windows, which seems to have all sorts
459 # This happens under Windows, which seems to have all sorts
458 # of problems with signal handling. Oh well...
460 # of problems with signal handling. Oh well...
459 pass
461 pass
460
462
461 # Flush queue of pending code by calling the run methood of the parent
463 # Flush queue of pending code by calling the run methood of the parent
462 # class with all items which may be in the queue.
464 # class with all items which may be in the queue.
463 code_to_run = None
465 code_to_run = None
464 while 1:
466 while 1:
465 try:
467 try:
466 code_to_run, completed_ev, received_ev = self.code_queue.get_nowait()
468 code_to_run, completed_ev, received_ev = self.code_queue.get_nowait()
467 except Queue.Empty:
469 except Queue.Empty:
468 break
470 break
469 received_ev.set()
471 received_ev.set()
470
472
471 # Exceptions need to be raised differently depending on which
473 # Exceptions need to be raised differently depending on which
472 # thread is active. This convoluted try/except is only there to
474 # thread is active. This convoluted try/except is only there to
473 # protect against asynchronous exceptions, to ensure that a KBINT
475 # protect against asynchronous exceptions, to ensure that a KBINT
474 # at the wrong time doesn't deadlock everything. The global
476 # at the wrong time doesn't deadlock everything. The global
475 # CODE_TO_RUN is set to true/false as close as possible to the
477 # CODE_TO_RUN is set to true/false as close as possible to the
476 # runcode() call, so that the KBINT handler is correctly informed.
478 # runcode() call, so that the KBINT handler is correctly informed.
477 try:
479 try:
478 try:
480 try:
479 CODE_RUN = True
481 CODE_RUN = True
480 InteractiveShell.runcode(self,code_to_run)
482 InteractiveShell.runcode(self,code_to_run)
481 except KeyboardInterrupt:
483 except KeyboardInterrupt:
482 print "Keyboard interrupted in mainloop"
484 print "Keyboard interrupted in mainloop"
483 while not self.code_queue.empty():
485 while not self.code_queue.empty():
484 code, ev1,ev2 = self.code_queue.get_nowait()
486 code, ev1,ev2 = self.code_queue.get_nowait()
485 ev1.set()
487 ev1.set()
486 ev2.set()
488 ev2.set()
487 break
489 break
488 finally:
490 finally:
489 CODE_RUN = False
491 CODE_RUN = False
490 # allow runsource() return from wait
492 # allow runsource() return from wait
491 completed_ev.set()
493 completed_ev.set()
492
494
493
495
494 # This MUST return true for gtk threading to work
496 # This MUST return true for gtk threading to work
495 return True
497 return True
496
498
497 def kill(self):
499 def kill(self):
498 """Kill the thread, returning when it has been shut down."""
500 """Kill the thread, returning when it has been shut down."""
499 self._kill = threading.Event()
501 self._kill = threading.Event()
500 self._kill.wait()
502 self._kill.wait()
501
503
502 class MatplotlibShellBase:
504 class MatplotlibShellBase:
503 """Mixin class to provide the necessary modifications to regular IPython
505 """Mixin class to provide the necessary modifications to regular IPython
504 shell classes for matplotlib support.
506 shell classes for matplotlib support.
505
507
506 Given Python's MRO, this should be used as the FIRST class in the
508 Given Python's MRO, this should be used as the FIRST class in the
507 inheritance hierarchy, so that it overrides the relevant methods."""
509 inheritance hierarchy, so that it overrides the relevant methods."""
508
510
509 def _matplotlib_config(self,name,user_ns,user_global_ns=None):
511 def _matplotlib_config(self,name,user_ns,user_global_ns=None):
510 """Return items needed to setup the user's shell with matplotlib"""
512 """Return items needed to setup the user's shell with matplotlib"""
511
513
512 # Initialize matplotlib to interactive mode always
514 # Initialize matplotlib to interactive mode always
513 import matplotlib
515 import matplotlib
514 from matplotlib import backends
516 from matplotlib import backends
515 matplotlib.interactive(True)
517 matplotlib.interactive(True)
516
518
517 def use(arg):
519 def use(arg):
518 """IPython wrapper for matplotlib's backend switcher.
520 """IPython wrapper for matplotlib's backend switcher.
519
521
520 In interactive use, we can not allow switching to a different
522 In interactive use, we can not allow switching to a different
521 interactive backend, since thread conflicts will most likely crash
523 interactive backend, since thread conflicts will most likely crash
522 the python interpreter. This routine does a safety check first,
524 the python interpreter. This routine does a safety check first,
523 and refuses to perform a dangerous switch. It still allows
525 and refuses to perform a dangerous switch. It still allows
524 switching to non-interactive backends."""
526 switching to non-interactive backends."""
525
527
526 if arg in backends.interactive_bk and arg != self.mpl_backend:
528 if arg in backends.interactive_bk and arg != self.mpl_backend:
527 m=('invalid matplotlib backend switch.\n'
529 m=('invalid matplotlib backend switch.\n'
528 'This script attempted to switch to the interactive '
530 'This script attempted to switch to the interactive '
529 'backend: `%s`\n'
531 'backend: `%s`\n'
530 'Your current choice of interactive backend is: `%s`\n\n'
532 'Your current choice of interactive backend is: `%s`\n\n'
531 'Switching interactive matplotlib backends at runtime\n'
533 'Switching interactive matplotlib backends at runtime\n'
532 'would crash the python interpreter, '
534 'would crash the python interpreter, '
533 'and IPython has blocked it.\n\n'
535 'and IPython has blocked it.\n\n'
534 'You need to either change your choice of matplotlib backend\n'
536 'You need to either change your choice of matplotlib backend\n'
535 'by editing your .matplotlibrc file, or run this script as a \n'
537 'by editing your .matplotlibrc file, or run this script as a \n'
536 'standalone file from the command line, not using IPython.\n' %
538 'standalone file from the command line, not using IPython.\n' %
537 (arg,self.mpl_backend) )
539 (arg,self.mpl_backend) )
538 raise RuntimeError, m
540 raise RuntimeError, m
539 else:
541 else:
540 self.mpl_use(arg)
542 self.mpl_use(arg)
541 self.mpl_use._called = True
543 self.mpl_use._called = True
542
544
543 self.matplotlib = matplotlib
545 self.matplotlib = matplotlib
544 self.mpl_backend = matplotlib.rcParams['backend']
546 self.mpl_backend = matplotlib.rcParams['backend']
545
547
546 # we also need to block switching of interactive backends by use()
548 # we also need to block switching of interactive backends by use()
547 self.mpl_use = matplotlib.use
549 self.mpl_use = matplotlib.use
548 self.mpl_use._called = False
550 self.mpl_use._called = False
549 # overwrite the original matplotlib.use with our wrapper
551 # overwrite the original matplotlib.use with our wrapper
550 matplotlib.use = use
552 matplotlib.use = use
551
553
552 # This must be imported last in the matplotlib series, after
554 # This must be imported last in the matplotlib series, after
553 # backend/interactivity choices have been made
555 # backend/interactivity choices have been made
554 import matplotlib.pylab as pylab
556 import matplotlib.pylab as pylab
555 self.pylab = pylab
557 self.pylab = pylab
556
558
557 self.pylab.show._needmain = False
559 self.pylab.show._needmain = False
558 # We need to detect at runtime whether show() is called by the user.
560 # We need to detect at runtime whether show() is called by the user.
559 # For this, we wrap it into a decorator which adds a 'called' flag.
561 # For this, we wrap it into a decorator which adds a 'called' flag.
560 self.pylab.draw_if_interactive = flag_calls(self.pylab.draw_if_interactive)
562 self.pylab.draw_if_interactive = flag_calls(self.pylab.draw_if_interactive)
561
563
562 # Build a user namespace initialized with matplotlib/matlab features.
564 # Build a user namespace initialized with matplotlib/matlab features.
563 user_ns, user_global_ns = IPython.ipapi.make_user_namespaces(user_ns,
565 user_ns, user_global_ns = IPython.ipapi.make_user_namespaces(user_ns,
564 user_global_ns)
566 user_global_ns)
565
567
566 # Import numpy as np/pyplot as plt are conventions we're trying to
568 # Import numpy as np/pyplot as plt are conventions we're trying to
567 # somewhat standardize on. Making them available to users by default
569 # somewhat standardize on. Making them available to users by default
568 # will greatly help this.
570 # will greatly help this.
569 exec ("import numpy\n"
571 exec ("import numpy\n"
570 "import numpy as np\n"
572 "import numpy as np\n"
571 "import matplotlib\n"
573 "import matplotlib\n"
572 "import matplotlib.pylab as pylab\n"
574 "import matplotlib.pylab as pylab\n"
573 "try:\n"
575 "try:\n"
574 " import matplotlib.pyplot as plt\n"
576 " import matplotlib.pyplot as plt\n"
575 "except ImportError:\n"
577 "except ImportError:\n"
576 " pass\n"
578 " pass\n"
577 ) in user_ns
579 ) in user_ns
578
580
579 # Build matplotlib info banner
581 # Build matplotlib info banner
580 b="""
582 b="""
581 Welcome to pylab, a matplotlib-based Python environment.
583 Welcome to pylab, a matplotlib-based Python environment.
582 For more information, type 'help(pylab)'.
584 For more information, type 'help(pylab)'.
583 """
585 """
584 return user_ns,user_global_ns,b
586 return user_ns,user_global_ns,b
585
587
586 def mplot_exec(self,fname,*where,**kw):
588 def mplot_exec(self,fname,*where,**kw):
587 """Execute a matplotlib script.
589 """Execute a matplotlib script.
588
590
589 This is a call to execfile(), but wrapped in safeties to properly
591 This is a call to execfile(), but wrapped in safeties to properly
590 handle interactive rendering and backend switching."""
592 handle interactive rendering and backend switching."""
591
593
592 #print '*** Matplotlib runner ***' # dbg
594 #print '*** Matplotlib runner ***' # dbg
593 # turn off rendering until end of script
595 # turn off rendering until end of script
594 isInteractive = self.matplotlib.rcParams['interactive']
596 isInteractive = self.matplotlib.rcParams['interactive']
595 self.matplotlib.interactive(False)
597 self.matplotlib.interactive(False)
596 self.safe_execfile(fname,*where,**kw)
598 self.safe_execfile(fname,*where,**kw)
597 self.matplotlib.interactive(isInteractive)
599 self.matplotlib.interactive(isInteractive)
598 # make rendering call now, if the user tried to do it
600 # make rendering call now, if the user tried to do it
599 if self.pylab.draw_if_interactive.called:
601 if self.pylab.draw_if_interactive.called:
600 self.pylab.draw()
602 self.pylab.draw()
601 self.pylab.draw_if_interactive.called = False
603 self.pylab.draw_if_interactive.called = False
602
604
603 # if a backend switch was performed, reverse it now
605 # if a backend switch was performed, reverse it now
604 if self.mpl_use._called:
606 if self.mpl_use._called:
605 self.matplotlib.rcParams['backend'] = self.mpl_backend
607 self.matplotlib.rcParams['backend'] = self.mpl_backend
606
608
607 @testdec.skip_doctest
609 @testdec.skip_doctest
608 def magic_run(self,parameter_s=''):
610 def magic_run(self,parameter_s=''):
609 Magic.magic_run(self,parameter_s,runner=self.mplot_exec)
611 Magic.magic_run(self,parameter_s,runner=self.mplot_exec)
610
612
611 # Fix the docstring so users see the original as well
613 # Fix the docstring so users see the original as well
612 magic_run.__doc__ = "%s\n%s" % (Magic.magic_run.__doc__,
614 magic_run.__doc__ = "%s\n%s" % (Magic.magic_run.__doc__,
613 "\n *** Modified %run for Matplotlib,"
615 "\n *** Modified %run for Matplotlib,"
614 " with proper interactive handling ***")
616 " with proper interactive handling ***")
615
617
616 # Now we provide 2 versions of a matplotlib-aware IPython base shells, single
618 # Now we provide 2 versions of a matplotlib-aware IPython base shells, single
617 # and multithreaded. Note that these are meant for internal use, the IPShell*
619 # and multithreaded. Note that these are meant for internal use, the IPShell*
618 # classes below are the ones meant for public consumption.
620 # classes below are the ones meant for public consumption.
619
621
620 class MatplotlibShell(MatplotlibShellBase,InteractiveShell):
622 class MatplotlibShell(MatplotlibShellBase,InteractiveShell):
621 """Single-threaded shell with matplotlib support."""
623 """Single-threaded shell with matplotlib support."""
622
624
623 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
625 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
624 user_ns=None,user_global_ns=None,**kw):
626 user_ns=None,user_global_ns=None,**kw):
625 user_ns,user_global_ns,b2 = self._matplotlib_config(name,user_ns,user_global_ns)
627 user_ns,user_global_ns,b2 = self._matplotlib_config(name,user_ns,user_global_ns)
626 InteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
628 InteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
627 banner2=b2,**kw)
629 banner2=b2,**kw)
628
630
629 class MatplotlibMTShell(MatplotlibShellBase,MTInteractiveShell):
631 class MatplotlibMTShell(MatplotlibShellBase,MTInteractiveShell):
630 """Multi-threaded shell with matplotlib support."""
632 """Multi-threaded shell with matplotlib support."""
631
633
632 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
634 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
633 user_ns=None,user_global_ns=None, **kw):
635 user_ns=None,user_global_ns=None, **kw):
634 user_ns,user_global_ns,b2 = self._matplotlib_config(name,user_ns,user_global_ns)
636 user_ns,user_global_ns,b2 = self._matplotlib_config(name,user_ns,user_global_ns)
635 MTInteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
637 MTInteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
636 banner2=b2,**kw)
638 banner2=b2,**kw)
637
639
638 #-----------------------------------------------------------------------------
640 #-----------------------------------------------------------------------------
639 # Utility functions for the different GUI enabled IPShell* classes.
641 # Utility functions for the different GUI enabled IPShell* classes.
640
642
641 def get_tk():
643 def get_tk():
642 """Tries to import Tkinter and returns a withdrawn Tkinter root
644 """Tries to import Tkinter and returns a withdrawn Tkinter root
643 window. If Tkinter is already imported or not available, this
645 window. If Tkinter is already imported or not available, this
644 returns None. This function calls `hijack_tk` underneath.
646 returns None. This function calls `hijack_tk` underneath.
645 """
647 """
646 if not USE_TK or sys.modules.has_key('Tkinter'):
648 if not USE_TK or sys.modules.has_key('Tkinter'):
647 return None
649 return None
648 else:
650 else:
649 try:
651 try:
650 import Tkinter
652 import Tkinter
651 except ImportError:
653 except ImportError:
652 return None
654 return None
653 else:
655 else:
654 hijack_tk()
656 hijack_tk()
655 r = Tkinter.Tk()
657 r = Tkinter.Tk()
656 r.withdraw()
658 r.withdraw()
657 return r
659 return r
658
660
659 def hijack_tk():
661 def hijack_tk():
660 """Modifies Tkinter's mainloop with a dummy so when a module calls
662 """Modifies Tkinter's mainloop with a dummy so when a module calls
661 mainloop, it does not block.
663 mainloop, it does not block.
662
664
663 """
665 """
664 def misc_mainloop(self, n=0):
666 def misc_mainloop(self, n=0):
665 pass
667 pass
666 def tkinter_mainloop(n=0):
668 def tkinter_mainloop(n=0):
667 pass
669 pass
668
670
669 import Tkinter
671 import Tkinter
670 Tkinter.Misc.mainloop = misc_mainloop
672 Tkinter.Misc.mainloop = misc_mainloop
671 Tkinter.mainloop = tkinter_mainloop
673 Tkinter.mainloop = tkinter_mainloop
672
674
673 def update_tk(tk):
675 def update_tk(tk):
674 """Updates the Tkinter event loop. This is typically called from
676 """Updates the Tkinter event loop. This is typically called from
675 the respective WX or GTK mainloops.
677 the respective WX or GTK mainloops.
676 """
678 """
677 if tk:
679 if tk:
678 tk.update()
680 tk.update()
679
681
680 def hijack_wx():
682 def hijack_wx():
681 """Modifies wxPython's MainLoop with a dummy so user code does not
683 """Modifies wxPython's MainLoop with a dummy so user code does not
682 block IPython. The hijacked mainloop function is returned.
684 block IPython. The hijacked mainloop function is returned.
683 """
685 """
684 def dummy_mainloop(*args, **kw):
686 def dummy_mainloop(*args, **kw):
685 pass
687 pass
686
688
687 try:
689 try:
688 import wx
690 import wx
689 except ImportError:
691 except ImportError:
690 # For very old versions of WX
692 # For very old versions of WX
691 import wxPython as wx
693 import wxPython as wx
692
694
693 ver = wx.__version__
695 ver = wx.__version__
694 orig_mainloop = None
696 orig_mainloop = None
695 if ver[:3] >= '2.5':
697 if ver[:3] >= '2.5':
696 import wx
698 import wx
697 if hasattr(wx, '_core_'): core = getattr(wx, '_core_')
699 if hasattr(wx, '_core_'): core = getattr(wx, '_core_')
698 elif hasattr(wx, '_core'): core = getattr(wx, '_core')
700 elif hasattr(wx, '_core'): core = getattr(wx, '_core')
699 else: raise AttributeError('Could not find wx core module')
701 else: raise AttributeError('Could not find wx core module')
700 orig_mainloop = core.PyApp_MainLoop
702 orig_mainloop = core.PyApp_MainLoop
701 core.PyApp_MainLoop = dummy_mainloop
703 core.PyApp_MainLoop = dummy_mainloop
702 elif ver[:3] == '2.4':
704 elif ver[:3] == '2.4':
703 orig_mainloop = wx.wxc.wxPyApp_MainLoop
705 orig_mainloop = wx.wxc.wxPyApp_MainLoop
704 wx.wxc.wxPyApp_MainLoop = dummy_mainloop
706 wx.wxc.wxPyApp_MainLoop = dummy_mainloop
705 else:
707 else:
706 warn("Unable to find either wxPython version 2.4 or >= 2.5.")
708 warn("Unable to find either wxPython version 2.4 or >= 2.5.")
707 return orig_mainloop
709 return orig_mainloop
708
710
709 def hijack_gtk():
711 def hijack_gtk():
710 """Modifies pyGTK's mainloop with a dummy so user code does not
712 """Modifies pyGTK's mainloop with a dummy so user code does not
711 block IPython. This function returns the original `gtk.mainloop`
713 block IPython. This function returns the original `gtk.mainloop`
712 function that has been hijacked.
714 function that has been hijacked.
713 """
715 """
714 def dummy_mainloop(*args, **kw):
716 def dummy_mainloop(*args, **kw):
715 pass
717 pass
716 import gtk
718 import gtk
717 if gtk.pygtk_version >= (2,4,0): orig_mainloop = gtk.main
719 if gtk.pygtk_version >= (2,4,0): orig_mainloop = gtk.main
718 else: orig_mainloop = gtk.mainloop
720 else: orig_mainloop = gtk.mainloop
719 gtk.mainloop = dummy_mainloop
721 gtk.mainloop = dummy_mainloop
720 gtk.main = dummy_mainloop
722 gtk.main = dummy_mainloop
721 return orig_mainloop
723 return orig_mainloop
722
724
723 def hijack_qt():
725 def hijack_qt():
724 """Modifies PyQt's mainloop with a dummy so user code does not
726 """Modifies PyQt's mainloop with a dummy so user code does not
725 block IPython. This function returns the original
727 block IPython. This function returns the original
726 `qt.qApp.exec_loop` function that has been hijacked.
728 `qt.qApp.exec_loop` function that has been hijacked.
727 """
729 """
728 def dummy_mainloop(*args, **kw):
730 def dummy_mainloop(*args, **kw):
729 pass
731 pass
730 import qt
732 import qt
731 orig_mainloop = qt.qApp.exec_loop
733 orig_mainloop = qt.qApp.exec_loop
732 qt.qApp.exec_loop = dummy_mainloop
734 qt.qApp.exec_loop = dummy_mainloop
733 qt.QApplication.exec_loop = dummy_mainloop
735 qt.QApplication.exec_loop = dummy_mainloop
734 return orig_mainloop
736 return orig_mainloop
735
737
736 def hijack_qt4():
738 def hijack_qt4():
737 """Modifies PyQt4's mainloop with a dummy so user code does not
739 """Modifies PyQt4's mainloop with a dummy so user code does not
738 block IPython. This function returns the original
740 block IPython. This function returns the original
739 `QtGui.qApp.exec_` function that has been hijacked.
741 `QtGui.qApp.exec_` function that has been hijacked.
740 """
742 """
741 def dummy_mainloop(*args, **kw):
743 def dummy_mainloop(*args, **kw):
742 pass
744 pass
743 from PyQt4 import QtGui, QtCore
745 from PyQt4 import QtGui, QtCore
744 orig_mainloop = QtGui.qApp.exec_
746 orig_mainloop = QtGui.qApp.exec_
745 QtGui.qApp.exec_ = dummy_mainloop
747 QtGui.qApp.exec_ = dummy_mainloop
746 QtGui.QApplication.exec_ = dummy_mainloop
748 QtGui.QApplication.exec_ = dummy_mainloop
747 QtCore.QCoreApplication.exec_ = dummy_mainloop
749 QtCore.QCoreApplication.exec_ = dummy_mainloop
748 return orig_mainloop
750 return orig_mainloop
749
751
750 #-----------------------------------------------------------------------------
752 #-----------------------------------------------------------------------------
751 # The IPShell* classes below are the ones meant to be run by external code as
753 # The IPShell* classes below are the ones meant to be run by external code as
752 # IPython instances. Note that unless a specific threading strategy is
754 # IPython instances. Note that unless a specific threading strategy is
753 # desired, the factory function start() below should be used instead (it
755 # desired, the factory function start() below should be used instead (it
754 # selects the proper threaded class).
756 # selects the proper threaded class).
755
757
756 class IPThread(threading.Thread):
758 class IPThread(threading.Thread):
757 def run(self):
759 def run(self):
758 self.IP.mainloop(self._banner)
760 self.IP.mainloop(self._banner)
759 self.IP.kill()
761 self.IP.kill()
760
762
761 class IPShellGTK(IPThread):
763 class IPShellGTK(IPThread):
762 """Run a gtk mainloop() in a separate thread.
764 """Run a gtk mainloop() in a separate thread.
763
765
764 Python commands can be passed to the thread where they will be executed.
766 Python commands can be passed to the thread where they will be executed.
765 This is implemented by periodically checking for passed code using a
767 This is implemented by periodically checking for passed code using a
766 GTK timeout callback."""
768 GTK timeout callback."""
767
769
768 TIMEOUT = 100 # Millisecond interval between timeouts.
770 TIMEOUT = 100 # Millisecond interval between timeouts.
769
771
770 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
772 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
771 debug=1,shell_class=MTInteractiveShell):
773 debug=1,shell_class=MTInteractiveShell):
772
774
773 import gtk
775 import gtk
774 # Check for set_interactive, coming up in new pygtk.
776 # Check for set_interactive, coming up in new pygtk.
775 # Disable it so that this code works, but notify
777 # Disable it so that this code works, but notify
776 # the user that he has a better option as well.
778 # the user that he has a better option as well.
777 # XXX TODO better support when set_interactive is released
779 # XXX TODO better support when set_interactive is released
778 try:
780 try:
779 gtk.set_interactive(False)
781 gtk.set_interactive(False)
780 print "Your PyGtk has set_interactive(), so you can use the"
782 print "Your PyGtk has set_interactive(), so you can use the"
781 print "more stable single-threaded Gtk mode."
783 print "more stable single-threaded Gtk mode."
782 print "See https://bugs.launchpad.net/ipython/+bug/270856"
784 print "See https://bugs.launchpad.net/ipython/+bug/270856"
783 except AttributeError:
785 except AttributeError:
784 pass
786 pass
785
787
786 self.gtk = gtk
788 self.gtk = gtk
787 self.gtk_mainloop = hijack_gtk()
789 self.gtk_mainloop = hijack_gtk()
788
790
789 # Allows us to use both Tk and GTK.
791 # Allows us to use both Tk and GTK.
790 self.tk = get_tk()
792 self.tk = get_tk()
791
793
792 if gtk.pygtk_version >= (2,4,0): mainquit = self.gtk.main_quit
794 if gtk.pygtk_version >= (2,4,0): mainquit = self.gtk.main_quit
793 else: mainquit = self.gtk.mainquit
795 else: mainquit = self.gtk.mainquit
794
796
795 self.IP = make_IPython(argv,user_ns=user_ns,
797 self.IP = make_IPython(argv,user_ns=user_ns,
796 user_global_ns=user_global_ns,
798 user_global_ns=user_global_ns,
797 debug=debug,
799 debug=debug,
798 shell_class=shell_class,
800 shell_class=shell_class,
799 on_kill=[mainquit])
801 on_kill=[mainquit])
800
802
801 # HACK: slot for banner in self; it will be passed to the mainloop
803 # HACK: slot for banner in self; it will be passed to the mainloop
802 # method only and .run() needs it. The actual value will be set by
804 # method only and .run() needs it. The actual value will be set by
803 # .mainloop().
805 # .mainloop().
804 self._banner = None
806 self._banner = None
805
807
806 threading.Thread.__init__(self)
808 threading.Thread.__init__(self)
807
809
808 def mainloop(self,sys_exit=0,banner=None):
810 def mainloop(self,sys_exit=0,banner=None):
809
811
810 self._banner = banner
812 self._banner = banner
811
813
812 if self.gtk.pygtk_version >= (2,4,0):
814 if self.gtk.pygtk_version >= (2,4,0):
813 import gobject
815 import gobject
814 gobject.idle_add(self.on_timer)
816 gobject.idle_add(self.on_timer)
815 else:
817 else:
816 self.gtk.idle_add(self.on_timer)
818 self.gtk.idle_add(self.on_timer)
817
819
818 if sys.platform != 'win32':
820 if sys.platform != 'win32':
819 try:
821 try:
820 if self.gtk.gtk_version[0] >= 2:
822 if self.gtk.gtk_version[0] >= 2:
821 self.gtk.gdk.threads_init()
823 self.gtk.gdk.threads_init()
822 except AttributeError:
824 except AttributeError:
823 pass
825 pass
824 except RuntimeError:
826 except RuntimeError:
825 error('Your pyGTK likely has not been compiled with '
827 error('Your pyGTK likely has not been compiled with '
826 'threading support.\n'
828 'threading support.\n'
827 'The exception printout is below.\n'
829 'The exception printout is below.\n'
828 'You can either rebuild pyGTK with threads, or '
830 'You can either rebuild pyGTK with threads, or '
829 'try using \n'
831 'try using \n'
830 'matplotlib with a different backend (like Tk or WX).\n'
832 'matplotlib with a different backend (like Tk or WX).\n'
831 'Note that matplotlib will most likely not work in its '
833 'Note that matplotlib will most likely not work in its '
832 'current state!')
834 'current state!')
833 self.IP.InteractiveTB()
835 self.IP.InteractiveTB()
834
836
835 self.start()
837 self.start()
836 self.gtk.gdk.threads_enter()
838 self.gtk.gdk.threads_enter()
837 self.gtk_mainloop()
839 self.gtk_mainloop()
838 self.gtk.gdk.threads_leave()
840 self.gtk.gdk.threads_leave()
839 self.join()
841 self.join()
840
842
841 def on_timer(self):
843 def on_timer(self):
842 """Called when GTK is idle.
844 """Called when GTK is idle.
843
845
844 Must return True always, otherwise GTK stops calling it"""
846 Must return True always, otherwise GTK stops calling it"""
845
847
846 update_tk(self.tk)
848 update_tk(self.tk)
847 self.IP.runcode()
849 self.IP.runcode()
848 time.sleep(0.01)
850 time.sleep(0.01)
849 return True
851 return True
850
852
851
853
852 class IPShellWX(IPThread):
854 class IPShellWX(IPThread):
853 """Run a wx mainloop() in a separate thread.
855 """Run a wx mainloop() in a separate thread.
854
856
855 Python commands can be passed to the thread where they will be executed.
857 Python commands can be passed to the thread where they will be executed.
856 This is implemented by periodically checking for passed code using a
858 This is implemented by periodically checking for passed code using a
857 GTK timeout callback."""
859 GTK timeout callback."""
858
860
859 TIMEOUT = 100 # Millisecond interval between timeouts.
861 TIMEOUT = 100 # Millisecond interval between timeouts.
860
862
861 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
863 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
862 debug=1,shell_class=MTInteractiveShell):
864 debug=1,shell_class=MTInteractiveShell):
863
865
864 self.IP = make_IPython(argv,user_ns=user_ns,
866 self.IP = make_IPython(argv,user_ns=user_ns,
865 user_global_ns=user_global_ns,
867 user_global_ns=user_global_ns,
866 debug=debug,
868 debug=debug,
867 shell_class=shell_class,
869 shell_class=shell_class,
868 on_kill=[self.wxexit])
870 on_kill=[self.wxexit])
869
871
870 wantedwxversion=self.IP.rc.wxversion
872 wantedwxversion=self.IP.rc.wxversion
871 if wantedwxversion!="0":
873 if wantedwxversion!="0":
872 try:
874 try:
873 import wxversion
875 import wxversion
874 except ImportError:
876 except ImportError:
875 error('The wxversion module is needed for WX version selection')
877 error('The wxversion module is needed for WX version selection')
876 else:
878 else:
877 try:
879 try:
878 wxversion.select(wantedwxversion)
880 wxversion.select(wantedwxversion)
879 except:
881 except:
880 self.IP.InteractiveTB()
882 self.IP.InteractiveTB()
881 error('Requested wxPython version %s could not be loaded' %
883 error('Requested wxPython version %s could not be loaded' %
882 wantedwxversion)
884 wantedwxversion)
883
885
884 import wx
886 import wx
885
887
886 threading.Thread.__init__(self)
888 threading.Thread.__init__(self)
887 self.wx = wx
889 self.wx = wx
888 self.wx_mainloop = hijack_wx()
890 self.wx_mainloop = hijack_wx()
889
891
890 # Allows us to use both Tk and GTK.
892 # Allows us to use both Tk and GTK.
891 self.tk = get_tk()
893 self.tk = get_tk()
892
894
893 # HACK: slot for banner in self; it will be passed to the mainloop
895 # HACK: slot for banner in self; it will be passed to the mainloop
894 # method only and .run() needs it. The actual value will be set by
896 # method only and .run() needs it. The actual value will be set by
895 # .mainloop().
897 # .mainloop().
896 self._banner = None
898 self._banner = None
897
899
898 self.app = None
900 self.app = None
899
901
900 def wxexit(self, *args):
902 def wxexit(self, *args):
901 if self.app is not None:
903 if self.app is not None:
902 self.app.agent.timer.Stop()
904 self.app.agent.timer.Stop()
903 self.app.ExitMainLoop()
905 self.app.ExitMainLoop()
904
906
905 def mainloop(self,sys_exit=0,banner=None):
907 def mainloop(self,sys_exit=0,banner=None):
906
908
907 self._banner = banner
909 self._banner = banner
908
910
909 self.start()
911 self.start()
910
912
911 class TimerAgent(self.wx.MiniFrame):
913 class TimerAgent(self.wx.MiniFrame):
912 wx = self.wx
914 wx = self.wx
913 IP = self.IP
915 IP = self.IP
914 tk = self.tk
916 tk = self.tk
915 def __init__(self, parent, interval):
917 def __init__(self, parent, interval):
916 style = self.wx.DEFAULT_FRAME_STYLE | self.wx.TINY_CAPTION_HORIZ
918 style = self.wx.DEFAULT_FRAME_STYLE | self.wx.TINY_CAPTION_HORIZ
917 self.wx.MiniFrame.__init__(self, parent, -1, ' ', pos=(200, 200),
919 self.wx.MiniFrame.__init__(self, parent, -1, ' ', pos=(200, 200),
918 size=(100, 100),style=style)
920 size=(100, 100),style=style)
919 self.Show(False)
921 self.Show(False)
920 self.interval = interval
922 self.interval = interval
921 self.timerId = self.wx.NewId()
923 self.timerId = self.wx.NewId()
922
924
923 def StartWork(self):
925 def StartWork(self):
924 self.timer = self.wx.Timer(self, self.timerId)
926 self.timer = self.wx.Timer(self, self.timerId)
925 self.wx.EVT_TIMER(self, self.timerId, self.OnTimer)
927 self.wx.EVT_TIMER(self, self.timerId, self.OnTimer)
926 self.timer.Start(self.interval)
928 self.timer.Start(self.interval)
927
929
928 def OnTimer(self, event):
930 def OnTimer(self, event):
929 update_tk(self.tk)
931 update_tk(self.tk)
930 self.IP.runcode()
932 self.IP.runcode()
931
933
932 class App(self.wx.App):
934 class App(self.wx.App):
933 wx = self.wx
935 wx = self.wx
934 TIMEOUT = self.TIMEOUT
936 TIMEOUT = self.TIMEOUT
935 def OnInit(self):
937 def OnInit(self):
936 'Create the main window and insert the custom frame'
938 'Create the main window and insert the custom frame'
937 self.agent = TimerAgent(None, self.TIMEOUT)
939 self.agent = TimerAgent(None, self.TIMEOUT)
938 self.agent.Show(False)
940 self.agent.Show(False)
939 self.agent.StartWork()
941 self.agent.StartWork()
940 return True
942 return True
941
943
942 self.app = App(redirect=False)
944 self.app = App(redirect=False)
943 self.wx_mainloop(self.app)
945 self.wx_mainloop(self.app)
944 self.join()
946 self.join()
945
947
946
948
947 class IPShellQt(IPThread):
949 class IPShellQt(IPThread):
948 """Run a Qt event loop in a separate thread.
950 """Run a Qt event loop in a separate thread.
949
951
950 Python commands can be passed to the thread where they will be executed.
952 Python commands can be passed to the thread where they will be executed.
951 This is implemented by periodically checking for passed code using a
953 This is implemented by periodically checking for passed code using a
952 Qt timer / slot."""
954 Qt timer / slot."""
953
955
954 TIMEOUT = 100 # Millisecond interval between timeouts.
956 TIMEOUT = 100 # Millisecond interval between timeouts.
955
957
956 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
958 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
957 debug=0, shell_class=MTInteractiveShell):
959 debug=0, shell_class=MTInteractiveShell):
958
960
959 import qt
961 import qt
960
962
961 self.exec_loop = hijack_qt()
963 self.exec_loop = hijack_qt()
962
964
963 # Allows us to use both Tk and QT.
965 # Allows us to use both Tk and QT.
964 self.tk = get_tk()
966 self.tk = get_tk()
965
967
966 self.IP = make_IPython(argv,
968 self.IP = make_IPython(argv,
967 user_ns=user_ns,
969 user_ns=user_ns,
968 user_global_ns=user_global_ns,
970 user_global_ns=user_global_ns,
969 debug=debug,
971 debug=debug,
970 shell_class=shell_class,
972 shell_class=shell_class,
971 on_kill=[qt.qApp.exit])
973 on_kill=[qt.qApp.exit])
972
974
973 # HACK: slot for banner in self; it will be passed to the mainloop
975 # HACK: slot for banner in self; it will be passed to the mainloop
974 # method only and .run() needs it. The actual value will be set by
976 # method only and .run() needs it. The actual value will be set by
975 # .mainloop().
977 # .mainloop().
976 self._banner = None
978 self._banner = None
977
979
978 threading.Thread.__init__(self)
980 threading.Thread.__init__(self)
979
981
980 def mainloop(self, sys_exit=0, banner=None):
982 def mainloop(self, sys_exit=0, banner=None):
981
983
982 import qt
984 import qt
983
985
984 self._banner = banner
986 self._banner = banner
985
987
986 if qt.QApplication.startingUp():
988 if qt.QApplication.startingUp():
987 a = qt.QApplication(sys.argv)
989 a = qt.QApplication(sys.argv)
988
990
989 self.timer = qt.QTimer()
991 self.timer = qt.QTimer()
990 qt.QObject.connect(self.timer,
992 qt.QObject.connect(self.timer,
991 qt.SIGNAL('timeout()'),
993 qt.SIGNAL('timeout()'),
992 self.on_timer)
994 self.on_timer)
993
995
994 self.start()
996 self.start()
995 self.timer.start(self.TIMEOUT, True)
997 self.timer.start(self.TIMEOUT, True)
996 while True:
998 while True:
997 if self.IP._kill: break
999 if self.IP._kill: break
998 self.exec_loop()
1000 self.exec_loop()
999 self.join()
1001 self.join()
1000
1002
1001 def on_timer(self):
1003 def on_timer(self):
1002 update_tk(self.tk)
1004 update_tk(self.tk)
1003 result = self.IP.runcode()
1005 result = self.IP.runcode()
1004 self.timer.start(self.TIMEOUT, True)
1006 self.timer.start(self.TIMEOUT, True)
1005 return result
1007 return result
1006
1008
1007
1009
1008 class IPShellQt4(IPThread):
1010 class IPShellQt4(IPThread):
1009 """Run a Qt event loop in a separate thread.
1011 """Run a Qt event loop in a separate thread.
1010
1012
1011 Python commands can be passed to the thread where they will be executed.
1013 Python commands can be passed to the thread where they will be executed.
1012 This is implemented by periodically checking for passed code using a
1014 This is implemented by periodically checking for passed code using a
1013 Qt timer / slot."""
1015 Qt timer / slot."""
1014
1016
1015 TIMEOUT = 100 # Millisecond interval between timeouts.
1017 TIMEOUT = 100 # Millisecond interval between timeouts.
1016
1018
1017 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
1019 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
1018 debug=0, shell_class=MTInteractiveShell):
1020 debug=0, shell_class=MTInteractiveShell):
1019
1021
1020 from PyQt4 import QtCore, QtGui
1022 from PyQt4 import QtCore, QtGui
1021
1023
1022 try:
1024 try:
1023 # present in PyQt4-4.2.1 or later
1025 # present in PyQt4-4.2.1 or later
1024 QtCore.pyqtRemoveInputHook()
1026 QtCore.pyqtRemoveInputHook()
1025 except AttributeError:
1027 except AttributeError:
1026 pass
1028 pass
1027
1029
1028 if QtCore.PYQT_VERSION_STR == '4.3':
1030 if QtCore.PYQT_VERSION_STR == '4.3':
1029 warn('''PyQt4 version 4.3 detected.
1031 warn('''PyQt4 version 4.3 detected.
1030 If you experience repeated threading warnings, please update PyQt4.
1032 If you experience repeated threading warnings, please update PyQt4.
1031 ''')
1033 ''')
1032
1034
1033 self.exec_ = hijack_qt4()
1035 self.exec_ = hijack_qt4()
1034
1036
1035 # Allows us to use both Tk and QT.
1037 # Allows us to use both Tk and QT.
1036 self.tk = get_tk()
1038 self.tk = get_tk()
1037
1039
1038 self.IP = make_IPython(argv,
1040 self.IP = make_IPython(argv,
1039 user_ns=user_ns,
1041 user_ns=user_ns,
1040 user_global_ns=user_global_ns,
1042 user_global_ns=user_global_ns,
1041 debug=debug,
1043 debug=debug,
1042 shell_class=shell_class,
1044 shell_class=shell_class,
1043 on_kill=[QtGui.qApp.exit])
1045 on_kill=[QtGui.qApp.exit])
1044
1046
1045 # HACK: slot for banner in self; it will be passed to the mainloop
1047 # HACK: slot for banner in self; it will be passed to the mainloop
1046 # method only and .run() needs it. The actual value will be set by
1048 # method only and .run() needs it. The actual value will be set by
1047 # .mainloop().
1049 # .mainloop().
1048 self._banner = None
1050 self._banner = None
1049
1051
1050 threading.Thread.__init__(self)
1052 threading.Thread.__init__(self)
1051
1053
1052 def mainloop(self, sys_exit=0, banner=None):
1054 def mainloop(self, sys_exit=0, banner=None):
1053
1055
1054 from PyQt4 import QtCore, QtGui
1056 from PyQt4 import QtCore, QtGui
1055
1057
1056 self._banner = banner
1058 self._banner = banner
1057
1059
1058 if QtGui.QApplication.startingUp():
1060 if QtGui.QApplication.startingUp():
1059 a = QtGui.QApplication(sys.argv)
1061 a = QtGui.QApplication(sys.argv)
1060
1062
1061 self.timer = QtCore.QTimer()
1063 self.timer = QtCore.QTimer()
1062 QtCore.QObject.connect(self.timer,
1064 QtCore.QObject.connect(self.timer,
1063 QtCore.SIGNAL('timeout()'),
1065 QtCore.SIGNAL('timeout()'),
1064 self.on_timer)
1066 self.on_timer)
1065
1067
1066 self.start()
1068 self.start()
1067 self.timer.start(self.TIMEOUT)
1069 self.timer.start(self.TIMEOUT)
1068 while True:
1070 while True:
1069 if self.IP._kill: break
1071 if self.IP._kill: break
1070 self.exec_()
1072 self.exec_()
1071 self.join()
1073 self.join()
1072
1074
1073 def on_timer(self):
1075 def on_timer(self):
1074 update_tk(self.tk)
1076 update_tk(self.tk)
1075 result = self.IP.runcode()
1077 result = self.IP.runcode()
1076 self.timer.start(self.TIMEOUT)
1078 self.timer.start(self.TIMEOUT)
1077 return result
1079 return result
1078
1080
1079
1081
1080 # A set of matplotlib public IPython shell classes, for single-threaded (Tk*
1082 # A set of matplotlib public IPython shell classes, for single-threaded (Tk*
1081 # and FLTK*) and multithreaded (GTK*, WX* and Qt*) backends to use.
1083 # and FLTK*) and multithreaded (GTK*, WX* and Qt*) backends to use.
1082 def _load_pylab(user_ns):
1084 def _load_pylab(user_ns):
1083 """Allow users to disable pulling all of pylab into the top-level
1085 """Allow users to disable pulling all of pylab into the top-level
1084 namespace.
1086 namespace.
1085
1087
1086 This little utility must be called AFTER the actual ipython instance is
1088 This little utility must be called AFTER the actual ipython instance is
1087 running, since only then will the options file have been fully parsed."""
1089 running, since only then will the options file have been fully parsed."""
1088
1090
1089 ip = IPython.ipapi.get()
1091 ip = IPython.ipapi.get()
1090 if ip.options.pylab_import_all:
1092 if ip.options.pylab_import_all:
1091 ip.ex("from matplotlib.pylab import *")
1093 ip.ex("from matplotlib.pylab import *")
1092 ip.IP.user_config_ns.update(ip.user_ns)
1094 ip.IP.user_config_ns.update(ip.user_ns)
1093
1095
1094
1096
1095 class IPShellMatplotlib(IPShell):
1097 class IPShellMatplotlib(IPShell):
1096 """Subclass IPShell with MatplotlibShell as the internal shell.
1098 """Subclass IPShell with MatplotlibShell as the internal shell.
1097
1099
1098 Single-threaded class, meant for the Tk* and FLTK* backends.
1100 Single-threaded class, meant for the Tk* and FLTK* backends.
1099
1101
1100 Having this on a separate class simplifies the external driver code."""
1102 Having this on a separate class simplifies the external driver code."""
1101
1103
1102 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1104 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1103 IPShell.__init__(self,argv,user_ns,user_global_ns,debug,
1105 IPShell.__init__(self,argv,user_ns,user_global_ns,debug,
1104 shell_class=MatplotlibShell)
1106 shell_class=MatplotlibShell)
1105 _load_pylab(self.IP.user_ns)
1107 _load_pylab(self.IP.user_ns)
1106
1108
1107 class IPShellMatplotlibGTK(IPShellGTK):
1109 class IPShellMatplotlibGTK(IPShellGTK):
1108 """Subclass IPShellGTK with MatplotlibMTShell as the internal shell.
1110 """Subclass IPShellGTK with MatplotlibMTShell as the internal shell.
1109
1111
1110 Multi-threaded class, meant for the GTK* backends."""
1112 Multi-threaded class, meant for the GTK* backends."""
1111
1113
1112 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1114 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1113 IPShellGTK.__init__(self,argv,user_ns,user_global_ns,debug,
1115 IPShellGTK.__init__(self,argv,user_ns,user_global_ns,debug,
1114 shell_class=MatplotlibMTShell)
1116 shell_class=MatplotlibMTShell)
1115 _load_pylab(self.IP.user_ns)
1117 _load_pylab(self.IP.user_ns)
1116
1118
1117 class IPShellMatplotlibWX(IPShellWX):
1119 class IPShellMatplotlibWX(IPShellWX):
1118 """Subclass IPShellWX with MatplotlibMTShell as the internal shell.
1120 """Subclass IPShellWX with MatplotlibMTShell as the internal shell.
1119
1121
1120 Multi-threaded class, meant for the WX* backends."""
1122 Multi-threaded class, meant for the WX* backends."""
1121
1123
1122 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1124 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1123 IPShellWX.__init__(self,argv,user_ns,user_global_ns,debug,
1125 IPShellWX.__init__(self,argv,user_ns,user_global_ns,debug,
1124 shell_class=MatplotlibMTShell)
1126 shell_class=MatplotlibMTShell)
1125 _load_pylab(self.IP.user_ns)
1127 _load_pylab(self.IP.user_ns)
1126
1128
1127 class IPShellMatplotlibQt(IPShellQt):
1129 class IPShellMatplotlibQt(IPShellQt):
1128 """Subclass IPShellQt with MatplotlibMTShell as the internal shell.
1130 """Subclass IPShellQt with MatplotlibMTShell as the internal shell.
1129
1131
1130 Multi-threaded class, meant for the Qt* backends."""
1132 Multi-threaded class, meant for the Qt* backends."""
1131
1133
1132 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1134 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1133 IPShellQt.__init__(self,argv,user_ns,user_global_ns,debug,
1135 IPShellQt.__init__(self,argv,user_ns,user_global_ns,debug,
1134 shell_class=MatplotlibMTShell)
1136 shell_class=MatplotlibMTShell)
1135 _load_pylab(self.IP.user_ns)
1137 _load_pylab(self.IP.user_ns)
1136
1138
1137 class IPShellMatplotlibQt4(IPShellQt4):
1139 class IPShellMatplotlibQt4(IPShellQt4):
1138 """Subclass IPShellQt4 with MatplotlibMTShell as the internal shell.
1140 """Subclass IPShellQt4 with MatplotlibMTShell as the internal shell.
1139
1141
1140 Multi-threaded class, meant for the Qt4* backends."""
1142 Multi-threaded class, meant for the Qt4* backends."""
1141
1143
1142 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1144 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1143 IPShellQt4.__init__(self,argv,user_ns,user_global_ns,debug,
1145 IPShellQt4.__init__(self,argv,user_ns,user_global_ns,debug,
1144 shell_class=MatplotlibMTShell)
1146 shell_class=MatplotlibMTShell)
1145 _load_pylab(self.IP.user_ns)
1147 _load_pylab(self.IP.user_ns)
1146
1148
1147 #-----------------------------------------------------------------------------
1149 #-----------------------------------------------------------------------------
1148 # Factory functions to actually start the proper thread-aware shell
1150 # Factory functions to actually start the proper thread-aware shell
1149
1151
1150 def _select_shell(argv):
1152 def _select_shell(argv):
1151 """Select a shell from the given argv vector.
1153 """Select a shell from the given argv vector.
1152
1154
1153 This function implements the threading selection policy, allowing runtime
1155 This function implements the threading selection policy, allowing runtime
1154 control of the threading mode, both for general users and for matplotlib.
1156 control of the threading mode, both for general users and for matplotlib.
1155
1157
1156 Return:
1158 Return:
1157 Shell class to be instantiated for runtime operation.
1159 Shell class to be instantiated for runtime operation.
1158 """
1160 """
1159
1161
1160 global USE_TK
1162 global USE_TK
1161
1163
1162 mpl_shell = {'gthread' : IPShellMatplotlibGTK,
1164 mpl_shell = {'gthread' : IPShellMatplotlibGTK,
1163 'wthread' : IPShellMatplotlibWX,
1165 'wthread' : IPShellMatplotlibWX,
1164 'qthread' : IPShellMatplotlibQt,
1166 'qthread' : IPShellMatplotlibQt,
1165 'q4thread' : IPShellMatplotlibQt4,
1167 'q4thread' : IPShellMatplotlibQt4,
1166 'tkthread' : IPShellMatplotlib, # Tk is built-in
1168 'tkthread' : IPShellMatplotlib, # Tk is built-in
1167 }
1169 }
1168
1170
1169 th_shell = {'gthread' : IPShellGTK,
1171 th_shell = {'gthread' : IPShellGTK,
1170 'wthread' : IPShellWX,
1172 'wthread' : IPShellWX,
1171 'qthread' : IPShellQt,
1173 'qthread' : IPShellQt,
1172 'q4thread' : IPShellQt4,
1174 'q4thread' : IPShellQt4,
1173 'tkthread' : IPShell, # Tk is built-in
1175 'tkthread' : IPShell, # Tk is built-in
1174 }
1176 }
1175
1177
1176 backends = {'gthread' : 'GTKAgg',
1178 backends = {'gthread' : 'GTKAgg',
1177 'wthread' : 'WXAgg',
1179 'wthread' : 'WXAgg',
1178 'qthread' : 'QtAgg',
1180 'qthread' : 'QtAgg',
1179 'q4thread' :'Qt4Agg',
1181 'q4thread' :'Qt4Agg',
1180 'tkthread' :'TkAgg',
1182 'tkthread' :'TkAgg',
1181 }
1183 }
1182
1184
1183 all_opts = set(['tk','pylab','gthread','qthread','q4thread','wthread',
1185 all_opts = set(['tk','pylab','gthread','qthread','q4thread','wthread',
1184 'tkthread'])
1186 'tkthread'])
1185 user_opts = set([s.replace('-','') for s in argv[:3]])
1187 user_opts = set([s.replace('-','') for s in argv[:3]])
1186 special_opts = user_opts & all_opts
1188 special_opts = user_opts & all_opts
1187
1189
1188 if 'tk' in special_opts:
1190 if 'tk' in special_opts:
1189 USE_TK = True
1191 USE_TK = True
1190 special_opts.remove('tk')
1192 special_opts.remove('tk')
1191
1193
1192 if 'pylab' in special_opts:
1194 if 'pylab' in special_opts:
1193
1195
1194 try:
1196 try:
1195 import matplotlib
1197 import matplotlib
1196 except ImportError:
1198 except ImportError:
1197 error('matplotlib could NOT be imported! Starting normal IPython.')
1199 error('matplotlib could NOT be imported! Starting normal IPython.')
1198 return IPShell
1200 return IPShell
1199
1201
1200 special_opts.remove('pylab')
1202 special_opts.remove('pylab')
1201 # If there's any option left, it means the user wants to force the
1203 # If there's any option left, it means the user wants to force the
1202 # threading backend, else it's auto-selected from the rc file
1204 # threading backend, else it's auto-selected from the rc file
1203 if special_opts:
1205 if special_opts:
1204 th_mode = special_opts.pop()
1206 th_mode = special_opts.pop()
1205 matplotlib.rcParams['backend'] = backends[th_mode]
1207 matplotlib.rcParams['backend'] = backends[th_mode]
1206 else:
1208 else:
1207 backend = matplotlib.rcParams['backend']
1209 backend = matplotlib.rcParams['backend']
1208 if backend.startswith('GTK'):
1210 if backend.startswith('GTK'):
1209 th_mode = 'gthread'
1211 th_mode = 'gthread'
1210 elif backend.startswith('WX'):
1212 elif backend.startswith('WX'):
1211 th_mode = 'wthread'
1213 th_mode = 'wthread'
1212 elif backend.startswith('Qt4'):
1214 elif backend.startswith('Qt4'):
1213 th_mode = 'q4thread'
1215 th_mode = 'q4thread'
1214 elif backend.startswith('Qt'):
1216 elif backend.startswith('Qt'):
1215 th_mode = 'qthread'
1217 th_mode = 'qthread'
1216 else:
1218 else:
1217 # Any other backend, use plain Tk
1219 # Any other backend, use plain Tk
1218 th_mode = 'tkthread'
1220 th_mode = 'tkthread'
1219
1221
1220 return mpl_shell[th_mode]
1222 return mpl_shell[th_mode]
1221 else:
1223 else:
1222 # No pylab requested, just plain threads
1224 # No pylab requested, just plain threads
1223 try:
1225 try:
1224 th_mode = special_opts.pop()
1226 th_mode = special_opts.pop()
1225 except KeyError:
1227 except KeyError:
1226 th_mode = 'tkthread'
1228 th_mode = 'tkthread'
1227 return th_shell[th_mode]
1229 return th_shell[th_mode]
1228
1230
1229
1231
1230 # This is the one which should be called by external code.
1232 # This is the one which should be called by external code.
1231 def start(user_ns = None):
1233 def start(user_ns = None):
1232 """Return a running shell instance, dealing with threading options.
1234 """Return a running shell instance, dealing with threading options.
1233
1235
1234 This is a factory function which will instantiate the proper IPython shell
1236 This is a factory function which will instantiate the proper IPython shell
1235 based on the user's threading choice. Such a selector is needed because
1237 based on the user's threading choice. Such a selector is needed because
1236 different GUI toolkits require different thread handling details."""
1238 different GUI toolkits require different thread handling details."""
1237
1239
1238 shell = _select_shell(sys.argv)
1240 shell = _select_shell(sys.argv)
1239 return shell(user_ns = user_ns)
1241 return shell(user_ns = user_ns)
1240
1242
1241 # Some aliases for backwards compatibility
1243 # Some aliases for backwards compatibility
1242 IPythonShell = IPShell
1244 IPythonShell = IPShell
1243 IPythonShellEmbed = IPShellEmbed
1245 IPythonShellEmbed = IPShellEmbed
1244 #************************ End of file <Shell.py> ***************************
1246 #************************ End of file <Shell.py> ***************************
@@ -1,116 +1,114 b''
1 """ User configuration file for IPython
1 """ User configuration file for IPython
2
2
3 This is a more flexible and safe way to configure ipython than *rc files
3 This is a more flexible and safe way to configure ipython than *rc files
4 (ipythonrc, ipythonrc-pysh etc.)
4 (ipythonrc, ipythonrc-pysh etc.)
5
5
6 This file is always imported on ipython startup. You can import the
6 This file is always imported on ipython startup. You can import the
7 ipython extensions you need here (see IPython/Extensions directory).
7 ipython extensions you need here (see IPython/Extensions directory).
8
8
9 Feel free to edit this file to customize your ipython experience.
9 Feel free to edit this file to customize your ipython experience.
10
10
11 Note that as such this file does nothing, for backwards compatibility.
11 Note that as such this file does nothing, for backwards compatibility.
12 Consult e.g. file 'ipy_profile_sh.py' for an example of the things
12 Consult e.g. file 'ipy_profile_sh.py' for an example of the things
13 you can do here.
13 you can do here.
14
14
15 See http://ipython.scipy.org/moin/IpythonExtensionApi for detailed
15 See http://ipython.scipy.org/moin/IpythonExtensionApi for detailed
16 description on what you could do here.
16 description on what you could do here.
17 """
17 """
18
18
19 # Most of your config files and extensions will probably start with this import
19 # Most of your config files and extensions will probably start with this import
20
20
21 import IPython.ipapi
21 import IPython.ipapi
22 ip = IPython.ipapi.get()
22 ip = IPython.ipapi.get()
23
23
24 # You probably want to uncomment this if you did %upgrade -nolegacy
24 # You probably want to uncomment this if you did %upgrade -nolegacy
25 # import ipy_defaults
25 # import ipy_defaults
26
26
27 import os
27 import os
28
28
29 def main():
29 def main():
30
30
31 # uncomment if you want to get ipython -p sh behaviour
31 # uncomment if you want to get ipython -p sh behaviour
32 # without having to use command line switches
32 # without having to use command line switches
33 # import ipy_profile_sh
33 # import ipy_profile_sh
34
34
35 # Configure your favourite editor?
35 # Configure your favourite editor?
36 # Good idea e.g. for %edit os.path.isfile
36 # Good idea e.g. for %edit os.path.isfile
37
37
38 #import ipy_editors
38 #import ipy_editors
39
39
40 # Choose one of these:
40 # Choose one of these:
41
41
42 #ipy_editors.scite()
42 #ipy_editors.scite()
43 #ipy_editors.scite('c:/opt/scite/scite.exe')
43 #ipy_editors.scite('c:/opt/scite/scite.exe')
44 #ipy_editors.komodo()
44 #ipy_editors.komodo()
45 #ipy_editors.idle()
45 #ipy_editors.idle()
46 # ... or many others, try 'ipy_editors??' after import to see them
46 # ... or many others, try 'ipy_editors??' after import to see them
47
47
48 # Or roll your own:
48 # Or roll your own:
49 #ipy_editors.install_editor("c:/opt/jed +$line $file")
49 #ipy_editors.install_editor("c:/opt/jed +$line $file")
50
50
51
51
52 o = ip.options
52 o = ip.options
53 # An example on how to set options
53 # An example on how to set options
54 #o.autocall = 1
54 #o.autocall = 1
55 o.system_verbose = 0
55 o.system_verbose = 0
56
56
57 #import_all("os sys")
57 #import_all("os sys")
58 #execf('~/_ipython/ns.py')
58 #execf('~/_ipython/ns.py')
59
59
60
60
61 # -- prompt
61 # -- prompt
62 # A different, more compact set of prompts from the default ones, that
62 # A different, more compact set of prompts from the default ones, that
63 # always show your current location in the filesystem:
63 # always show your current location in the filesystem:
64
64
65 #o.prompt_in1 = r'\C_LightBlue[\C_LightCyan\Y2\C_LightBlue]\C_Normal\n\C_Green|\#>'
65 #o.prompt_in1 = r'\C_LightBlue[\C_LightCyan\Y2\C_LightBlue]\C_Normal\n\C_Green|\#>'
66 #o.prompt_in2 = r'.\D: '
66 #o.prompt_in2 = r'.\D: '
67 #o.prompt_out = r'[\#] '
67 #o.prompt_out = r'[\#] '
68
68
69 # Try one of these color settings if you can't read the text easily
69 # Try one of these color settings if you can't read the text easily
70 # autoexec is a list of IPython commands to execute on startup
70 # autoexec is a list of IPython commands to execute on startup
71 #o.autoexec.append('%colors LightBG')
71 #o.autoexec.append('%colors LightBG')
72 #o.autoexec.append('%colors NoColor')
72 #o.autoexec.append('%colors NoColor')
73 #o.autoexec.append('%colors Linux')
73 #o.autoexec.append('%colors Linux')
74
74
75 # for sane integer division that converts to float (1/2 == 0.5)
75 # for sane integer division that converts to float (1/2 == 0.5)
76 #o.autoexec.append('from __future__ import division')
76 #o.autoexec.append('from __future__ import division')
77
77
78 # For %tasks and %kill
78 # For %tasks and %kill
79 #import jobctrl
79 #import jobctrl
80
80
81 # For autoreloading of modules (%autoreload, %aimport)
81 # For autoreloading of modules (%autoreload, %aimport)
82 #import ipy_autoreload
82 #import ipy_autoreload
83
83
84 # For winpdb support (%wdb)
84 # For winpdb support (%wdb)
85 #import ipy_winpdb
85 #import ipy_winpdb
86
86
87 # For bzr completer, requires bzrlib (the python installation of bzr)
87 # For bzr completer, requires bzrlib (the python installation of bzr)
88 #ip.load('ipy_bzr')
88 #ip.load('ipy_bzr')
89
89
90 # Tab completer that is not quite so picky (i.e.
90 # Tab completer that is not quite so picky (i.e.
91 # "foo".<TAB> and str(2).<TAB> will work). Complete
91 # "foo".<TAB> and str(2).<TAB> will work). Complete
92 # at your own risk!
92 # at your own risk!
93 #import ipy_greedycompleter
93 #import ipy_greedycompleter
94
94
95 # If you are on Linux, you may be annoyed by
95 # If you are on Linux, you may be annoyed by
96 # "Display all N possibilities? (y or n)" on tab completion,
96 # "Display all N possibilities? (y or n)" on tab completion,
97 # as well as the paging through "more". Uncomment the following
97 # as well as the paging through "more". Uncomment the following
98 # lines to disable that behaviour
98 # lines to disable that behaviour
99 #import readline
99 #import readline
100 #readline.parse_and_bind('set completion-query-items 1000')
100 #readline.parse_and_bind('set completion-query-items 1000')
101 #readline.parse_and_bind('set page-completions no')
101 #readline.parse_and_bind('set page-completions no')
102
102
103
103
104
105
106 # some config helper functions you can use
104 # some config helper functions you can use
107 def import_all(modules):
105 def import_all(modules):
108 """ Usage: import_all("os sys") """
106 """ Usage: import_all("os sys") """
109 for m in modules.split():
107 for m in modules.split():
110 ip.ex("from %s import *" % m)
108 ip.ex("from %s import *" % m)
111
109
112 def execf(fname):
110 def execf(fname):
113 """ Execute a file in user namespace """
111 """ Execute a file in user namespace """
114 ip.ex('execfile("%s")' % os.path.expanduser(fname))
112 ip.ex('execfile("%s")' % os.path.expanduser(fname))
115
113
116 main()
114 main()
@@ -1,490 +1,490 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Manage background (threaded) jobs conveniently from an interactive shell.
2 """Manage background (threaded) jobs conveniently from an interactive shell.
3
3
4 This module provides a BackgroundJobManager class. This is the main class
4 This module provides a BackgroundJobManager class. This is the main class
5 meant for public usage, it implements an object which can create and manage
5 meant for public usage, it implements an object which can create and manage
6 new background jobs.
6 new background jobs.
7
7
8 It also provides the actual job classes managed by these BackgroundJobManager
8 It also provides the actual job classes managed by these BackgroundJobManager
9 objects, see their docstrings below.
9 objects, see their docstrings below.
10
10
11
11
12 This system was inspired by discussions with B. Granger and the
12 This system was inspired by discussions with B. Granger and the
13 BackgroundCommand class described in the book Python Scripting for
13 BackgroundCommand class described in the book Python Scripting for
14 Computational Science, by H. P. Langtangen:
14 Computational Science, by H. P. Langtangen:
15
15
16 http://folk.uio.no/hpl/scripting
16 http://folk.uio.no/hpl/scripting
17
17
18 (although ultimately no code from this text was used, as IPython's system is a
18 (although ultimately no code from this text was used, as IPython's system is a
19 separate implementation).
19 separate implementation).
20 """
20 """
21
21
22 #*****************************************************************************
22 #*****************************************************************************
23 # Copyright (C) 2005-2006 Fernando Perez <fperez@colorado.edu>
23 # Copyright (C) 2005-2006 Fernando Perez <fperez@colorado.edu>
24 #
24 #
25 # Distributed under the terms of the BSD License. The full license is in
25 # Distributed under the terms of the BSD License. The full license is in
26 # the file COPYING, distributed as part of this software.
26 # the file COPYING, distributed as part of this software.
27 #*****************************************************************************
27 #*****************************************************************************
28
28
29 # Code begins
29 # Code begins
30 import sys
30 import sys
31 import threading
31 import threading
32
32
33 from IPython.ultraTB import AutoFormattedTB
33 from IPython.ultraTB import AutoFormattedTB
34 from IPython.genutils import warn,error
34 from IPython.genutils import warn,error
35
35
36 class BackgroundJobManager:
36 class BackgroundJobManager:
37 """Class to manage a pool of backgrounded threaded jobs.
37 """Class to manage a pool of backgrounded threaded jobs.
38
38
39 Below, we assume that 'jobs' is a BackgroundJobManager instance.
39 Below, we assume that 'jobs' is a BackgroundJobManager instance.
40
40
41 Usage summary (see the method docstrings for details):
41 Usage summary (see the method docstrings for details):
42
42
43 jobs.new(...) -> start a new job
43 jobs.new(...) -> start a new job
44
44
45 jobs() or jobs.status() -> print status summary of all jobs
45 jobs() or jobs.status() -> print status summary of all jobs
46
46
47 jobs[N] -> returns job number N.
47 jobs[N] -> returns job number N.
48
48
49 foo = jobs[N].result -> assign to variable foo the result of job N
49 foo = jobs[N].result -> assign to variable foo the result of job N
50
50
51 jobs[N].traceback() -> print the traceback of dead job N
51 jobs[N].traceback() -> print the traceback of dead job N
52
52
53 jobs.remove(N) -> remove (finished) job N
53 jobs.remove(N) -> remove (finished) job N
54
54
55 jobs.flush_finished() -> remove all finished jobs
55 jobs.flush_finished() -> remove all finished jobs
56
56
57 As a convenience feature, BackgroundJobManager instances provide the
57 As a convenience feature, BackgroundJobManager instances provide the
58 utility result and traceback methods which retrieve the corresponding
58 utility result and traceback methods which retrieve the corresponding
59 information from the jobs list:
59 information from the jobs list:
60
60
61 jobs.result(N) <--> jobs[N].result
61 jobs.result(N) <--> jobs[N].result
62 jobs.traceback(N) <--> jobs[N].traceback()
62 jobs.traceback(N) <--> jobs[N].traceback()
63
63
64 While this appears minor, it allows you to use tab completion
64 While this appears minor, it allows you to use tab completion
65 interactively on the job manager instance.
65 interactively on the job manager instance.
66
66
67 In interactive mode, IPython provides the magic fuction %bg for quick
67 In interactive mode, IPython provides the magic fuction %bg for quick
68 creation of backgrounded expression-based jobs. Type bg? for details."""
68 creation of backgrounded expression-based jobs. Type bg? for details."""
69
69
70 def __init__(self):
70 def __init__(self):
71 # Lists for job management
71 # Lists for job management
72 self.jobs_run = []
72 self.jobs_run = []
73 self.jobs_comp = []
73 self.jobs_comp = []
74 self.jobs_dead = []
74 self.jobs_dead = []
75 # A dict of all jobs, so users can easily access any of them
75 # A dict of all jobs, so users can easily access any of them
76 self.jobs_all = {}
76 self.jobs_all = {}
77 # For reporting
77 # For reporting
78 self._comp_report = []
78 self._comp_report = []
79 self._dead_report = []
79 self._dead_report = []
80 # Store status codes locally for fast lookups
80 # Store status codes locally for fast lookups
81 self._s_created = BackgroundJobBase.stat_created_c
81 self._s_created = BackgroundJobBase.stat_created_c
82 self._s_running = BackgroundJobBase.stat_running_c
82 self._s_running = BackgroundJobBase.stat_running_c
83 self._s_completed = BackgroundJobBase.stat_completed_c
83 self._s_completed = BackgroundJobBase.stat_completed_c
84 self._s_dead = BackgroundJobBase.stat_dead_c
84 self._s_dead = BackgroundJobBase.stat_dead_c
85
85
86 def new(self,func_or_exp,*args,**kwargs):
86 def new(self,func_or_exp,*args,**kwargs):
87 """Add a new background job and start it in a separate thread.
87 """Add a new background job and start it in a separate thread.
88
88
89 There are two types of jobs which can be created:
89 There are two types of jobs which can be created:
90
90
91 1. Jobs based on expressions which can be passed to an eval() call.
91 1. Jobs based on expressions which can be passed to an eval() call.
92 The expression must be given as a string. For example:
92 The expression must be given as a string. For example:
93
93
94 job_manager.new('myfunc(x,y,z=1)'[,glob[,loc]])
94 job_manager.new('myfunc(x,y,z=1)'[,glob[,loc]])
95
95
96 The given expression is passed to eval(), along with the optional
96 The given expression is passed to eval(), along with the optional
97 global/local dicts provided. If no dicts are given, they are
97 global/local dicts provided. If no dicts are given, they are
98 extracted automatically from the caller's frame.
98 extracted automatically from the caller's frame.
99
99
100 A Python statement is NOT a valid eval() expression. Basically, you
100 A Python statement is NOT a valid eval() expression. Basically, you
101 can only use as an eval() argument something which can go on the right
101 can only use as an eval() argument something which can go on the right
102 of an '=' sign and be assigned to a variable.
102 of an '=' sign and be assigned to a variable.
103
103
104 For example,"print 'hello'" is not valid, but '2+3' is.
104 For example,"print 'hello'" is not valid, but '2+3' is.
105
105
106 2. Jobs given a function object, optionally passing additional
106 2. Jobs given a function object, optionally passing additional
107 positional arguments:
107 positional arguments:
108
108
109 job_manager.new(myfunc,x,y)
109 job_manager.new(myfunc,x,y)
110
110
111 The function is called with the given arguments.
111 The function is called with the given arguments.
112
112
113 If you need to pass keyword arguments to your function, you must
113 If you need to pass keyword arguments to your function, you must
114 supply them as a dict named kw:
114 supply them as a dict named kw:
115
115
116 job_manager.new(myfunc,x,y,kw=dict(z=1))
116 job_manager.new(myfunc,x,y,kw=dict(z=1))
117
117
118 The reason for this assymmetry is that the new() method needs to
118 The reason for this assymmetry is that the new() method needs to
119 maintain access to its own keywords, and this prevents name collisions
119 maintain access to its own keywords, and this prevents name collisions
120 between arguments to new() and arguments to your own functions.
120 between arguments to new() and arguments to your own functions.
121
121
122 In both cases, the result is stored in the job.result field of the
122 In both cases, the result is stored in the job.result field of the
123 background job object.
123 background job object.
124
124
125
125
126 Notes and caveats:
126 Notes and caveats:
127
127
128 1. All threads running share the same standard output. Thus, if your
128 1. All threads running share the same standard output. Thus, if your
129 background jobs generate output, it will come out on top of whatever
129 background jobs generate output, it will come out on top of whatever
130 you are currently writing. For this reason, background jobs are best
130 you are currently writing. For this reason, background jobs are best
131 used with silent functions which simply return their output.
131 used with silent functions which simply return their output.
132
132
133 2. Threads also all work within the same global namespace, and this
133 2. Threads also all work within the same global namespace, and this
134 system does not lock interactive variables. So if you send job to the
134 system does not lock interactive variables. So if you send job to the
135 background which operates on a mutable object for a long time, and
135 background which operates on a mutable object for a long time, and
136 start modifying that same mutable object interactively (or in another
136 start modifying that same mutable object interactively (or in another
137 backgrounded job), all sorts of bizarre behaviour will occur.
137 backgrounded job), all sorts of bizarre behaviour will occur.
138
138
139 3. If a background job is spending a lot of time inside a C extension
139 3. If a background job is spending a lot of time inside a C extension
140 module which does not release the Python Global Interpreter Lock
140 module which does not release the Python Global Interpreter Lock
141 (GIL), this will block the IPython prompt. This is simply because the
141 (GIL), this will block the IPython prompt. This is simply because the
142 Python interpreter can only switch between threads at Python
142 Python interpreter can only switch between threads at Python
143 bytecodes. While the execution is inside C code, the interpreter must
143 bytecodes. While the execution is inside C code, the interpreter must
144 simply wait unless the extension module releases the GIL.
144 simply wait unless the extension module releases the GIL.
145
145
146 4. There is no way, due to limitations in the Python threads library,
146 4. There is no way, due to limitations in the Python threads library,
147 to kill a thread once it has started."""
147 to kill a thread once it has started."""
148
148
149 if callable(func_or_exp):
149 if callable(func_or_exp):
150 kw = kwargs.get('kw',{})
150 kw = kwargs.get('kw',{})
151 job = BackgroundJobFunc(func_or_exp,*args,**kw)
151 job = BackgroundJobFunc(func_or_exp,*args,**kw)
152 elif isinstance(func_or_exp,basestring):
152 elif isinstance(func_or_exp,basestring):
153 if not args:
153 if not args:
154 frame = sys._getframe(1)
154 frame = sys._getframe(1)
155 glob, loc = frame.f_globals, frame.f_locals
155 glob, loc = frame.f_globals, frame.f_locals
156 elif len(args)==1:
156 elif len(args)==1:
157 glob = loc = args[0]
157 glob = loc = args[0]
158 elif len(args)==2:
158 elif len(args)==2:
159 glob,loc = args
159 glob,loc = args
160 else:
160 else:
161 raise ValueError,\
161 raise ValueError,\
162 'Expression jobs take at most 2 args (globals,locals)'
162 'Expression jobs take at most 2 args (globals,locals)'
163 job = BackgroundJobExpr(func_or_exp,glob,loc)
163 job = BackgroundJobExpr(func_or_exp,glob,loc)
164 else:
164 else:
165 raise
165 raise
166 jkeys = self.jobs_all.keys()
166 jkeys = self.jobs_all.keys()
167 if jkeys:
167 if jkeys:
168 job.num = max(jkeys)+1
168 job.num = max(jkeys)+1
169 else:
169 else:
170 job.num = 0
170 job.num = 0
171 self.jobs_run.append(job)
171 self.jobs_run.append(job)
172 self.jobs_all[job.num] = job
172 self.jobs_all[job.num] = job
173 print 'Starting job # %s in a separate thread.' % job.num
173 print 'Starting job # %s in a separate thread.' % job.num
174 job.start()
174 job.start()
175 return job
175 return job
176
176
177 def __getitem__(self,key):
177 def __getitem__(self,key):
178 return self.jobs_all[key]
178 return self.jobs_all[key]
179
179
180 def __call__(self):
180 def __call__(self):
181 """An alias to self.status(),
181 """An alias to self.status(),
182
182
183 This allows you to simply call a job manager instance much like the
183 This allows you to simply call a job manager instance much like the
184 Unix jobs shell command."""
184 Unix jobs shell command."""
185
185
186 return self.status()
186 return self.status()
187
187
188 def _update_status(self):
188 def _update_status(self):
189 """Update the status of the job lists.
189 """Update the status of the job lists.
190
190
191 This method moves finished jobs to one of two lists:
191 This method moves finished jobs to one of two lists:
192 - self.jobs_comp: jobs which completed successfully
192 - self.jobs_comp: jobs which completed successfully
193 - self.jobs_dead: jobs which finished but died.
193 - self.jobs_dead: jobs which finished but died.
194
194
195 It also copies those jobs to corresponding _report lists. These lists
195 It also copies those jobs to corresponding _report lists. These lists
196 are used to report jobs completed/dead since the last update, and are
196 are used to report jobs completed/dead since the last update, and are
197 then cleared by the reporting function after each call."""
197 then cleared by the reporting function after each call."""
198
198
199 run,comp,dead = self._s_running,self._s_completed,self._s_dead
199 run,comp,dead = self._s_running,self._s_completed,self._s_dead
200 jobs_run = self.jobs_run
200 jobs_run = self.jobs_run
201 for num in range(len(jobs_run)):
201 for num in range(len(jobs_run)):
202 job = jobs_run[num]
202 job = jobs_run[num]
203 stat = job.stat_code
203 stat = job.stat_code
204 if stat == run:
204 if stat == run:
205 continue
205 continue
206 elif stat == comp:
206 elif stat == comp:
207 self.jobs_comp.append(job)
207 self.jobs_comp.append(job)
208 self._comp_report.append(job)
208 self._comp_report.append(job)
209 jobs_run[num] = False
209 jobs_run[num] = False
210 elif stat == dead:
210 elif stat == dead:
211 self.jobs_dead.append(job)
211 self.jobs_dead.append(job)
212 self._dead_report.append(job)
212 self._dead_report.append(job)
213 jobs_run[num] = False
213 jobs_run[num] = False
214 self.jobs_run = filter(None,self.jobs_run)
214 self.jobs_run = filter(None,self.jobs_run)
215
215
216 def _group_report(self,group,name):
216 def _group_report(self,group,name):
217 """Report summary for a given job group.
217 """Report summary for a given job group.
218
218
219 Return True if the group had any elements."""
219 Return True if the group had any elements."""
220
220
221 if group:
221 if group:
222 print '%s jobs:' % name
222 print '%s jobs:' % name
223 for job in group:
223 for job in group:
224 print '%s : %s' % (job.num,job)
224 print '%s : %s' % (job.num,job)
225 print
225 print
226 return True
226 return True
227
227
228 def _group_flush(self,group,name):
228 def _group_flush(self,group,name):
229 """Flush a given job group
229 """Flush a given job group
230
230
231 Return True if the group had any elements."""
231 Return True if the group had any elements."""
232
232
233 njobs = len(group)
233 njobs = len(group)
234 if njobs:
234 if njobs:
235 plural = {1:''}.setdefault(njobs,'s')
235 plural = {1:''}.setdefault(njobs,'s')
236 print 'Flushing %s %s job%s.' % (njobs,name,plural)
236 print 'Flushing %s %s job%s.' % (njobs,name,plural)
237 group[:] = []
237 group[:] = []
238 return True
238 return True
239
239
240 def _status_new(self):
240 def _status_new(self):
241 """Print the status of newly finished jobs.
241 """Print the status of newly finished jobs.
242
242
243 Return True if any new jobs are reported.
243 Return True if any new jobs are reported.
244
244
245 This call resets its own state every time, so it only reports jobs
245 This call resets its own state every time, so it only reports jobs
246 which have finished since the last time it was called."""
246 which have finished since the last time it was called."""
247
247
248 self._update_status()
248 self._update_status()
249 new_comp = self._group_report(self._comp_report,'Completed')
249 new_comp = self._group_report(self._comp_report,'Completed')
250 new_dead = self._group_report(self._dead_report,
250 new_dead = self._group_report(self._dead_report,
251 'Dead, call job.traceback() for details')
251 'Dead, call jobs.traceback() for details')
252 self._comp_report[:] = []
252 self._comp_report[:] = []
253 self._dead_report[:] = []
253 self._dead_report[:] = []
254 return new_comp or new_dead
254 return new_comp or new_dead
255
255
256 def status(self,verbose=0):
256 def status(self,verbose=0):
257 """Print a status of all jobs currently being managed."""
257 """Print a status of all jobs currently being managed."""
258
258
259 self._update_status()
259 self._update_status()
260 self._group_report(self.jobs_run,'Running')
260 self._group_report(self.jobs_run,'Running')
261 self._group_report(self.jobs_comp,'Completed')
261 self._group_report(self.jobs_comp,'Completed')
262 self._group_report(self.jobs_dead,'Dead')
262 self._group_report(self.jobs_dead,'Dead')
263 # Also flush the report queues
263 # Also flush the report queues
264 self._comp_report[:] = []
264 self._comp_report[:] = []
265 self._dead_report[:] = []
265 self._dead_report[:] = []
266
266
267 def remove(self,num):
267 def remove(self,num):
268 """Remove a finished (completed or dead) job."""
268 """Remove a finished (completed or dead) job."""
269
269
270 try:
270 try:
271 job = self.jobs_all[num]
271 job = self.jobs_all[num]
272 except KeyError:
272 except KeyError:
273 error('Job #%s not found' % num)
273 error('Job #%s not found' % num)
274 else:
274 else:
275 stat_code = job.stat_code
275 stat_code = job.stat_code
276 if stat_code == self._s_running:
276 if stat_code == self._s_running:
277 error('Job #%s is still running, it can not be removed.' % num)
277 error('Job #%s is still running, it can not be removed.' % num)
278 return
278 return
279 elif stat_code == self._s_completed:
279 elif stat_code == self._s_completed:
280 self.jobs_comp.remove(job)
280 self.jobs_comp.remove(job)
281 elif stat_code == self._s_dead:
281 elif stat_code == self._s_dead:
282 self.jobs_dead.remove(job)
282 self.jobs_dead.remove(job)
283
283
284 def flush_finished(self):
284 def flush_finished(self):
285 """Flush all jobs finished (completed and dead) from lists.
285 """Flush all jobs finished (completed and dead) from lists.
286
286
287 Running jobs are never flushed.
287 Running jobs are never flushed.
288
288
289 It first calls _status_new(), to update info. If any jobs have
289 It first calls _status_new(), to update info. If any jobs have
290 completed since the last _status_new() call, the flush operation
290 completed since the last _status_new() call, the flush operation
291 aborts."""
291 aborts."""
292
292
293 if self._status_new():
293 if self._status_new():
294 error('New jobs completed since last '\
294 error('New jobs completed since last '\
295 '_status_new(), aborting flush.')
295 '_status_new(), aborting flush.')
296 return
296 return
297
297
298 # Remove the finished jobs from the master dict
298 # Remove the finished jobs from the master dict
299 jobs_all = self.jobs_all
299 jobs_all = self.jobs_all
300 for job in self.jobs_comp+self.jobs_dead:
300 for job in self.jobs_comp+self.jobs_dead:
301 del(jobs_all[job.num])
301 del(jobs_all[job.num])
302
302
303 # Now flush these lists completely
303 # Now flush these lists completely
304 fl_comp = self._group_flush(self.jobs_comp,'Completed')
304 fl_comp = self._group_flush(self.jobs_comp,'Completed')
305 fl_dead = self._group_flush(self.jobs_dead,'Dead')
305 fl_dead = self._group_flush(self.jobs_dead,'Dead')
306 if not (fl_comp or fl_dead):
306 if not (fl_comp or fl_dead):
307 print 'No jobs to flush.'
307 print 'No jobs to flush.'
308
308
309 def result(self,num):
309 def result(self,num):
310 """result(N) -> return the result of job N."""
310 """result(N) -> return the result of job N."""
311 try:
311 try:
312 return self.jobs_all[num].result
312 return self.jobs_all[num].result
313 except KeyError:
313 except KeyError:
314 error('Job #%s not found' % num)
314 error('Job #%s not found' % num)
315
315
316 def traceback(self,num):
316 def traceback(self,num):
317 try:
317 try:
318 self.jobs_all[num].traceback()
318 self.jobs_all[num].traceback()
319 except KeyError:
319 except KeyError:
320 error('Job #%s not found' % num)
320 error('Job #%s not found' % num)
321
321
322
322
323 class BackgroundJobBase(threading.Thread):
323 class BackgroundJobBase(threading.Thread):
324 """Base class to build BackgroundJob classes.
324 """Base class to build BackgroundJob classes.
325
325
326 The derived classes must implement:
326 The derived classes must implement:
327
327
328 - Their own __init__, since the one here raises NotImplementedError. The
328 - Their own __init__, since the one here raises NotImplementedError. The
329 derived constructor must call self._init() at the end, to provide common
329 derived constructor must call self._init() at the end, to provide common
330 initialization.
330 initialization.
331
331
332 - A strform attribute used in calls to __str__.
332 - A strform attribute used in calls to __str__.
333
333
334 - A call() method, which will make the actual execution call and must
334 - A call() method, which will make the actual execution call and must
335 return a value to be held in the 'result' field of the job object."""
335 return a value to be held in the 'result' field of the job object."""
336
336
337 # Class constants for status, in string and as numerical codes (when
337 # Class constants for status, in string and as numerical codes (when
338 # updating jobs lists, we don't want to do string comparisons). This will
338 # updating jobs lists, we don't want to do string comparisons). This will
339 # be done at every user prompt, so it has to be as fast as possible
339 # be done at every user prompt, so it has to be as fast as possible
340 stat_created = 'Created'; stat_created_c = 0
340 stat_created = 'Created'; stat_created_c = 0
341 stat_running = 'Running'; stat_running_c = 1
341 stat_running = 'Running'; stat_running_c = 1
342 stat_completed = 'Completed'; stat_completed_c = 2
342 stat_completed = 'Completed'; stat_completed_c = 2
343 stat_dead = 'Dead (Exception), call job.traceback() for details'
343 stat_dead = 'Dead (Exception), call jobs.traceback() for details'
344 stat_dead_c = -1
344 stat_dead_c = -1
345
345
346 def __init__(self):
346 def __init__(self):
347 raise NotImplementedError, \
347 raise NotImplementedError, \
348 "This class can not be instantiated directly."
348 "This class can not be instantiated directly."
349
349
350 def _init(self):
350 def _init(self):
351 """Common initialization for all BackgroundJob objects"""
351 """Common initialization for all BackgroundJob objects"""
352
352
353 for attr in ['call','strform']:
353 for attr in ['call','strform']:
354 assert hasattr(self,attr), "Missing attribute <%s>" % attr
354 assert hasattr(self,attr), "Missing attribute <%s>" % attr
355
355
356 # The num tag can be set by an external job manager
356 # The num tag can be set by an external job manager
357 self.num = None
357 self.num = None
358
358
359 self.status = BackgroundJobBase.stat_created
359 self.status = BackgroundJobBase.stat_created
360 self.stat_code = BackgroundJobBase.stat_created_c
360 self.stat_code = BackgroundJobBase.stat_created_c
361 self.finished = False
361 self.finished = False
362 self.result = '<BackgroundJob has not completed>'
362 self.result = '<BackgroundJob has not completed>'
363 # reuse the ipython traceback handler if we can get to it, otherwise
363 # reuse the ipython traceback handler if we can get to it, otherwise
364 # make a new one
364 # make a new one
365 try:
365 try:
366 self._make_tb = __IPYTHON__.InteractiveTB.text
366 self._make_tb = __IPYTHON__.InteractiveTB.text
367 except:
367 except:
368 self._make_tb = AutoFormattedTB(mode = 'Context',
368 self._make_tb = AutoFormattedTB(mode = 'Context',
369 color_scheme='NoColor',
369 color_scheme='NoColor',
370 tb_offset = 1).text
370 tb_offset = 1).text
371 # Hold a formatted traceback if one is generated.
371 # Hold a formatted traceback if one is generated.
372 self._tb = None
372 self._tb = None
373
373
374 threading.Thread.__init__(self)
374 threading.Thread.__init__(self)
375
375
376 def __str__(self):
376 def __str__(self):
377 return self.strform
377 return self.strform
378
378
379 def __repr__(self):
379 def __repr__(self):
380 return '<BackgroundJob: %s>' % self.strform
380 return '<BackgroundJob: %s>' % self.strform
381
381
382 def traceback(self):
382 def traceback(self):
383 print self._tb
383 print self._tb
384
384
385 def run(self):
385 def run(self):
386 try:
386 try:
387 self.status = BackgroundJobBase.stat_running
387 self.status = BackgroundJobBase.stat_running
388 self.stat_code = BackgroundJobBase.stat_running_c
388 self.stat_code = BackgroundJobBase.stat_running_c
389 self.result = self.call()
389 self.result = self.call()
390 except:
390 except:
391 self.status = BackgroundJobBase.stat_dead
391 self.status = BackgroundJobBase.stat_dead
392 self.stat_code = BackgroundJobBase.stat_dead_c
392 self.stat_code = BackgroundJobBase.stat_dead_c
393 self.finished = None
393 self.finished = None
394 self.result = ('<BackgroundJob died, call job.traceback() for details>')
394 self.result = ('<BackgroundJob died, call jobs.traceback() for details>')
395 self._tb = self._make_tb()
395 self._tb = self._make_tb()
396 else:
396 else:
397 self.status = BackgroundJobBase.stat_completed
397 self.status = BackgroundJobBase.stat_completed
398 self.stat_code = BackgroundJobBase.stat_completed_c
398 self.stat_code = BackgroundJobBase.stat_completed_c
399 self.finished = True
399 self.finished = True
400
400
401 class BackgroundJobExpr(BackgroundJobBase):
401 class BackgroundJobExpr(BackgroundJobBase):
402 """Evaluate an expression as a background job (uses a separate thread)."""
402 """Evaluate an expression as a background job (uses a separate thread)."""
403
403
404 def __init__(self,expression,glob=None,loc=None):
404 def __init__(self,expression,glob=None,loc=None):
405 """Create a new job from a string which can be fed to eval().
405 """Create a new job from a string which can be fed to eval().
406
406
407 global/locals dicts can be provided, which will be passed to the eval
407 global/locals dicts can be provided, which will be passed to the eval
408 call."""
408 call."""
409
409
410 # fail immediately if the given expression can't be compiled
410 # fail immediately if the given expression can't be compiled
411 self.code = compile(expression,'<BackgroundJob compilation>','eval')
411 self.code = compile(expression,'<BackgroundJob compilation>','eval')
412
412
413 if glob is None:
413 if glob is None:
414 glob = {}
414 glob = {}
415 if loc is None:
415 if loc is None:
416 loc = {}
416 loc = {}
417
417
418 self.expression = self.strform = expression
418 self.expression = self.strform = expression
419 self.glob = glob
419 self.glob = glob
420 self.loc = loc
420 self.loc = loc
421 self._init()
421 self._init()
422
422
423 def call(self):
423 def call(self):
424 return eval(self.code,self.glob,self.loc)
424 return eval(self.code,self.glob,self.loc)
425
425
426 class BackgroundJobFunc(BackgroundJobBase):
426 class BackgroundJobFunc(BackgroundJobBase):
427 """Run a function call as a background job (uses a separate thread)."""
427 """Run a function call as a background job (uses a separate thread)."""
428
428
429 def __init__(self,func,*args,**kwargs):
429 def __init__(self,func,*args,**kwargs):
430 """Create a new job from a callable object.
430 """Create a new job from a callable object.
431
431
432 Any positional arguments and keyword args given to this constructor
432 Any positional arguments and keyword args given to this constructor
433 after the initial callable are passed directly to it."""
433 after the initial callable are passed directly to it."""
434
434
435 assert callable(func),'first argument must be callable'
435 assert callable(func),'first argument must be callable'
436
436
437 if args is None:
437 if args is None:
438 args = []
438 args = []
439 if kwargs is None:
439 if kwargs is None:
440 kwargs = {}
440 kwargs = {}
441
441
442 self.func = func
442 self.func = func
443 self.args = args
443 self.args = args
444 self.kwargs = kwargs
444 self.kwargs = kwargs
445 # The string form will only include the function passed, because
445 # The string form will only include the function passed, because
446 # generating string representations of the arguments is a potentially
446 # generating string representations of the arguments is a potentially
447 # _very_ expensive operation (e.g. with large arrays).
447 # _very_ expensive operation (e.g. with large arrays).
448 self.strform = str(func)
448 self.strform = str(func)
449 self._init()
449 self._init()
450
450
451 def call(self):
451 def call(self):
452 return self.func(*self.args,**self.kwargs)
452 return self.func(*self.args,**self.kwargs)
453
453
454
454
455 if __name__=='__main__':
455 if __name__=='__main__':
456
456
457 import time
457 import time
458
458
459 def sleepfunc(interval=2,*a,**kw):
459 def sleepfunc(interval=2,*a,**kw):
460 args = dict(interval=interval,
460 args = dict(interval=interval,
461 args=a,
461 args=a,
462 kwargs=kw)
462 kwargs=kw)
463 time.sleep(interval)
463 time.sleep(interval)
464 return args
464 return args
465
465
466 def diefunc(interval=2,*a,**kw):
466 def diefunc(interval=2,*a,**kw):
467 time.sleep(interval)
467 time.sleep(interval)
468 die
468 die
469
469
470 def printfunc(interval=1,reps=5):
470 def printfunc(interval=1,reps=5):
471 for n in range(reps):
471 for n in range(reps):
472 time.sleep(interval)
472 time.sleep(interval)
473 print 'In the background...'
473 print 'In the background...'
474
474
475 jobs = BackgroundJobManager()
475 jobs = BackgroundJobManager()
476 # first job will have # 0
476 # first job will have # 0
477 jobs.new(sleepfunc,4)
477 jobs.new(sleepfunc,4)
478 jobs.new(sleepfunc,kw={'reps':2})
478 jobs.new(sleepfunc,kw={'reps':2})
479 # This makes a job which will die
479 # This makes a job which will die
480 jobs.new(diefunc,1)
480 jobs.new(diefunc,1)
481 jobs.new('printfunc(1,3)')
481 jobs.new('printfunc(1,3)')
482
482
483 # after a while, you can get the traceback of a dead job. Run the line
483 # after a while, you can get the traceback of a dead job. Run the line
484 # below again interactively until it prints a traceback (check the status
484 # below again interactively until it prints a traceback (check the status
485 # of the job):
485 # of the job):
486 print jobs[1].status
486 print jobs[1].status
487 jobs[1].traceback()
487 jobs[1].traceback()
488
488
489 # Run this line again until the printed result changes
489 # Run this line again until the printed result changes
490 print "The result of job #0 is:",jobs[0].result
490 print "The result of job #0 is:",jobs[0].result
@@ -1,76 +1,77 b''
1 """
1 """
2 Base front end class for all async frontends.
2 Base front end class for all async frontends.
3 """
3 """
4 __docformat__ = "restructuredtext en"
4 __docformat__ = "restructuredtext en"
5
5
6 #-------------------------------------------------------------------------------
6 #-------------------------------------------------------------------------------
7 # Copyright (C) 2008 The IPython Development Team
7 # Copyright (C) 2008 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-------------------------------------------------------------------------------
11 #-------------------------------------------------------------------------------
12
12
13
13
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17 from IPython.external import guid
18
17
18 from IPython.external import guid
19
19
20 from zope.interface import Interface, Attribute, implements, classProvides
20 from zope.interface import Interface, Attribute, implements, classProvides
21 from twisted.python.failure import Failure
21 from twisted.python.failure import Failure
22 from IPython.frontend.frontendbase import FrontEndBase, IFrontEnd, IFrontEndFactory
22 from IPython.frontend.frontendbase import (
23 FrontEndBase, IFrontEnd, IFrontEndFactory)
23 from IPython.kernel.core.history import FrontEndHistory
24 from IPython.kernel.core.history import FrontEndHistory
24 from IPython.kernel.engineservice import IEngineCore
25 from IPython.kernel.engineservice import IEngineCore
25
26
26
27
27 class AsyncFrontEndBase(FrontEndBase):
28 class AsyncFrontEndBase(FrontEndBase):
28 """
29 """
29 Overrides FrontEndBase to wrap execute in a deferred result.
30 Overrides FrontEndBase to wrap execute in a deferred result.
30 All callbacks are made as callbacks on the deferred result.
31 All callbacks are made as callbacks on the deferred result.
31 """
32 """
32
33
33 implements(IFrontEnd)
34 implements(IFrontEnd)
34 classProvides(IFrontEndFactory)
35 classProvides(IFrontEndFactory)
35
36
36 def __init__(self, engine=None, history=None):
37 def __init__(self, engine=None, history=None):
37 assert(engine==None or IEngineCore.providedBy(engine))
38 assert(engine==None or IEngineCore.providedBy(engine))
38 self.engine = IEngineCore(engine)
39 self.engine = IEngineCore(engine)
39 if history is None:
40 if history is None:
40 self.history = FrontEndHistory(input_cache=[''])
41 self.history = FrontEndHistory(input_cache=[''])
41 else:
42 else:
42 self.history = history
43 self.history = history
43
44
44
45
45 def execute(self, block, blockID=None):
46 def execute(self, block, blockID=None):
46 """Execute the block and return the deferred result.
47 """Execute the block and return the deferred result.
47
48
48 Parameters:
49 Parameters:
49 block : {str, AST}
50 block : {str, AST}
50 blockID : any
51 blockID : any
51 Caller may provide an ID to identify this block.
52 Caller may provide an ID to identify this block.
52 result['blockID'] := blockID
53 result['blockID'] := blockID
53
54
54 Result:
55 Result:
55 Deferred result of self.interpreter.execute
56 Deferred result of self.interpreter.execute
56 """
57 """
57
58
58 if(not self.is_complete(block)):
59 if(not self.is_complete(block)):
59 return Failure(Exception("Block is not compilable"))
60 return Failure(Exception("Block is not compilable"))
60
61
61 if(blockID == None):
62 if(blockID == None):
62 blockID = guid.generate()
63 blockID = guid.generate()
63
64
64 d = self.engine.execute(block)
65 d = self.engine.execute(block)
65 d.addCallback(self._add_history, block=block)
66 d.addCallback(self._add_history, block=block)
66 d.addCallbacks(self._add_block_id_for_result,
67 d.addCallbacks(self._add_block_id_for_result,
67 errback=self._add_block_id_for_failure,
68 errback=self._add_block_id_for_failure,
68 callbackArgs=(blockID,),
69 callbackArgs=(blockID,),
69 errbackArgs=(blockID,))
70 errbackArgs=(blockID,))
70 d.addBoth(self.update_cell_prompt, blockID=blockID)
71 d.addBoth(self.update_cell_prompt, blockID=blockID)
71 d.addCallbacks(self.render_result,
72 d.addCallbacks(self.render_result,
72 errback=self.render_error)
73 errback=self.render_error)
73
74
74 return d
75 return d
75
76
76
77
@@ -1,94 +1,100 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """This file contains unittests for the
2 """This file contains unittests for the
3 IPython.frontend.cocoa.cocoa_frontend module.
3 IPython.frontend.cocoa.cocoa_frontend module.
4 """
4 """
5 __docformat__ = "restructuredtext en"
5 __docformat__ = "restructuredtext en"
6
6
7 #---------------------------------------------------------------------------
7 #---------------------------------------------------------------------------
8 # Copyright (C) 2005 The IPython Development Team
8 # Copyright (C) 2005 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #---------------------------------------------------------------------------
12 #---------------------------------------------------------------------------
13
13
14 #---------------------------------------------------------------------------
14 #---------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #---------------------------------------------------------------------------
16 #---------------------------------------------------------------------------
17
17
18 # Tell nose to skip this module
19 __test__ = {}
20
21 from twisted.trial import unittest
22 from twisted.internet.defer import succeed
23
24 from IPython.kernel.core.interpreter import Interpreter
25 import IPython.kernel.engineservice as es
26
18 try:
27 try:
19 from IPython.kernel.core.interpreter import Interpreter
28 from IPython.frontend.cocoa.cocoa_frontend import IPythonCocoaController
20 import IPython.kernel.engineservice as es
21 from IPython.testing.util import DeferredTestCase
22 from twisted.internet.defer import succeed
23 from IPython.frontend.cocoa.cocoa_frontend import IPythonCocoaController
24 from Foundation import NSMakeRect
29 from Foundation import NSMakeRect
25 from AppKit import NSTextView, NSScrollView
30 from AppKit import NSTextView, NSScrollView
26 except ImportError:
31 except ImportError:
27 import nose
32 # This tells twisted.trial to skip this module if PyObjC is not found
28 raise nose.SkipTest("This test requires zope.interface, Twisted, Foolscap and PyObjC")
33 skip = True
29
34
30 class TestIPythonCocoaControler(DeferredTestCase):
35 #---------------------------------------------------------------------------
36 # Tests
37 #---------------------------------------------------------------------------
38 class TestIPythonCocoaControler(unittest.TestCase):
31 """Tests for IPythonCocoaController"""
39 """Tests for IPythonCocoaController"""
32
40
33 def setUp(self):
41 def setUp(self):
34 self.controller = IPythonCocoaController.alloc().init()
42 self.controller = IPythonCocoaController.alloc().init()
35 self.engine = es.EngineService()
43 self.engine = es.EngineService()
36 self.engine.startService()
44 self.engine.startService()
37
45
38 def tearDown(self):
46 def tearDown(self):
39 self.controller = None
47 self.controller = None
40 self.engine.stopService()
48 self.engine.stopService()
41
49
42 def testControllerExecutesCode(self):
50 def testControllerExecutesCode(self):
43 code ="""5+5"""
51 code ="""5+5"""
44 expected = Interpreter().execute(code)
52 expected = Interpreter().execute(code)
45 del expected['number']
53 del expected['number']
46 def removeNumberAndID(result):
54 def removeNumberAndID(result):
47 del result['number']
55 del result['number']
48 del result['id']
56 del result['id']
49 return result
57 return result
50 self.assertDeferredEquals(
58 d = self.controller.execute(code)
51 self.controller.execute(code).addCallback(removeNumberAndID),
59 d.addCallback(removeNumberAndID)
52 expected)
60 d.addCallback(lambda r: self.assertEquals(r, expected))
53
61
54 def testControllerMirrorsUserNSWithValuesAsStrings(self):
62 def testControllerMirrorsUserNSWithValuesAsStrings(self):
55 code = """userns1=1;userns2=2"""
63 code = """userns1=1;userns2=2"""
56 def testControllerUserNS(result):
64 def testControllerUserNS(result):
57 self.assertEquals(self.controller.userNS['userns1'], 1)
65 self.assertEquals(self.controller.userNS['userns1'], 1)
58 self.assertEquals(self.controller.userNS['userns2'], 2)
66 self.assertEquals(self.controller.userNS['userns2'], 2)
59
60 self.controller.execute(code).addCallback(testControllerUserNS)
67 self.controller.execute(code).addCallback(testControllerUserNS)
61
68
62
63 def testControllerInstantiatesIEngine(self):
69 def testControllerInstantiatesIEngine(self):
64 self.assert_(es.IEngineBase.providedBy(self.controller.engine))
70 self.assert_(es.IEngineBase.providedBy(self.controller.engine))
65
71
66 def testControllerCompletesToken(self):
72 def testControllerCompletesToken(self):
67 code = """longNameVariable=10"""
73 code = """longNameVariable=10"""
68 def testCompletes(result):
74 def testCompletes(result):
69 self.assert_("longNameVariable" in result)
75 self.assert_("longNameVariable" in result)
70
76
71 def testCompleteToken(result):
77 def testCompleteToken(result):
72 self.controller.complete("longNa").addCallback(testCompletes)
78 self.controller.complete("longNa").addCallback(testCompletes)
73
79
74 self.controller.execute(code).addCallback(testCompletes)
80 self.controller.execute(code).addCallback(testCompletes)
75
81
76
82
77 def testCurrentIndent(self):
83 def testCurrentIndent(self):
78 """test that current_indent_string returns current indent or None.
84 """test that current_indent_string returns current indent or None.
79 Uses _indent_for_block for direct unit testing.
85 Uses _indent_for_block for direct unit testing.
80 """
86 """
81
87
82 self.controller.tabUsesSpaces = True
88 self.controller.tabUsesSpaces = True
83 self.assert_(self.controller._indent_for_block("""a=3""") == None)
89 self.assert_(self.controller._indent_for_block("""a=3""") == None)
84 self.assert_(self.controller._indent_for_block("") == None)
90 self.assert_(self.controller._indent_for_block("") == None)
85 block = """def test():\n a=3"""
91 block = """def test():\n a=3"""
86 self.assert_(self.controller._indent_for_block(block) == \
92 self.assert_(self.controller._indent_for_block(block) == \
87 ' ' * self.controller.tabSpaces)
93 ' ' * self.controller.tabSpaces)
88
94
89 block = """if(True):\n%sif(False):\n%spass""" % \
95 block = """if(True):\n%sif(False):\n%spass""" % \
90 (' '*self.controller.tabSpaces,
96 (' '*self.controller.tabSpaces,
91 2*' '*self.controller.tabSpaces)
97 2*' '*self.controller.tabSpaces)
92 self.assert_(self.controller._indent_for_block(block) == \
98 self.assert_(self.controller._indent_for_block(block) == \
93 2*(' '*self.controller.tabSpaces))
99 2*(' '*self.controller.tabSpaces))
94
100
@@ -1,333 +1,372 b''
1 """
1 """
2 Base front end class for all line-oriented frontends, rather than
2 Base front end class for all line-oriented frontends, rather than
3 block-oriented.
3 block-oriented.
4
4
5 Currently this focuses on synchronous frontends.
5 Currently this focuses on synchronous frontends.
6 """
6 """
7 __docformat__ = "restructuredtext en"
7 __docformat__ = "restructuredtext en"
8
8
9 #-------------------------------------------------------------------------------
9 #-------------------------------------------------------------------------------
10 # Copyright (C) 2008 The IPython Development Team
10 # Copyright (C) 2008 The IPython Development Team
11 #
11 #
12 # Distributed under the terms of the BSD License. The full license is in
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15
15
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17 # Imports
17 # Imports
18 #-------------------------------------------------------------------------------
18 #-------------------------------------------------------------------------------
19 import re
19 import re
20
20
21 import IPython
22 import sys
21 import sys
23 import codeop
22 import codeop
24 import traceback
25
23
26 from frontendbase import FrontEndBase
24 from frontendbase import FrontEndBase
27 from IPython.kernel.core.interpreter import Interpreter
25 from IPython.kernel.core.interpreter import Interpreter
28
26
29 def common_prefix(strings):
27 def common_prefix(strings):
30 """ Given a list of strings, return the common prefix between all
28 """ Given a list of strings, return the common prefix between all
31 these strings.
29 these strings.
32 """
30 """
33 ref = strings[0]
31 ref = strings[0]
34 prefix = ''
32 prefix = ''
35 for size in range(len(ref)):
33 for size in range(len(ref)):
36 test_prefix = ref[:size+1]
34 test_prefix = ref[:size+1]
37 for string in strings[1:]:
35 for string in strings[1:]:
38 if not string.startswith(test_prefix):
36 if not string.startswith(test_prefix):
39 return prefix
37 return prefix
40 prefix = test_prefix
38 prefix = test_prefix
41
39
42 return prefix
40 return prefix
43
41
44 #-------------------------------------------------------------------------------
42 #-------------------------------------------------------------------------------
45 # Base class for the line-oriented front ends
43 # Base class for the line-oriented front ends
46 #-------------------------------------------------------------------------------
44 #-------------------------------------------------------------------------------
47 class LineFrontEndBase(FrontEndBase):
45 class LineFrontEndBase(FrontEndBase):
48 """ Concrete implementation of the FrontEndBase class. This is meant
46 """ Concrete implementation of the FrontEndBase class. This is meant
49 to be the base class behind all the frontend that are line-oriented,
47 to be the base class behind all the frontend that are line-oriented,
50 rather than block-oriented.
48 rather than block-oriented.
51 """
49 """
52
50
53 # We need to keep the prompt number, to be able to increment
51 # We need to keep the prompt number, to be able to increment
54 # it when there is an exception.
52 # it when there is an exception.
55 prompt_number = 1
53 prompt_number = 1
56
54
57 # We keep a reference to the last result: it helps testing and
55 # We keep a reference to the last result: it helps testing and
58 # programatic control of the frontend.
56 # programatic control of the frontend.
59 last_result = dict(number=0)
57 last_result = dict(number=0)
60
58
59 # The last prompt displayed. Useful for continuation prompts.
60 last_prompt = ''
61
61 # The input buffer being edited
62 # The input buffer being edited
62 input_buffer = ''
63 input_buffer = ''
63
64
64 # Set to true for debug output
65 # Set to true for debug output
65 debug = False
66 debug = False
66
67
67 # A banner to print at startup
68 # A banner to print at startup
68 banner = None
69 banner = None
69
70
70 #--------------------------------------------------------------------------
71 #--------------------------------------------------------------------------
71 # FrontEndBase interface
72 # FrontEndBase interface
72 #--------------------------------------------------------------------------
73 #--------------------------------------------------------------------------
73
74
74 def __init__(self, shell=None, history=None, banner=None, *args, **kwargs):
75 def __init__(self, shell=None, history=None, banner=None, *args, **kwargs):
75 if shell is None:
76 if shell is None:
76 shell = Interpreter()
77 shell = Interpreter()
77 FrontEndBase.__init__(self, shell=shell, history=history)
78 FrontEndBase.__init__(self, shell=shell, history=history)
78
79
79 if banner is not None:
80 if banner is not None:
80 self.banner = banner
81 self.banner = banner
81
82
82 def start(self):
83 def start(self):
83 """ Put the frontend in a state where it is ready for user
84 """ Put the frontend in a state where it is ready for user
84 interaction.
85 interaction.
85 """
86 """
86 if self.banner is not None:
87 if self.banner is not None:
87 self.write(self.banner, refresh=False)
88 self.write(self.banner, refresh=False)
88
89
89 self.new_prompt(self.input_prompt_template.substitute(number=1))
90 self.new_prompt(self.input_prompt_template.substitute(number=1))
90
91
91
92
92 def complete(self, line):
93 def complete(self, line):
93 """Complete line in engine's user_ns
94 """Complete line in engine's user_ns
94
95
95 Parameters
96 Parameters
96 ----------
97 ----------
97 line : string
98 line : string
98
99
99 Result
100 Result
100 ------
101 ------
101 The replacement for the line and the list of possible completions.
102 The replacement for the line and the list of possible completions.
102 """
103 """
103 completions = self.shell.complete(line)
104 completions = self.shell.complete(line)
104 complete_sep = re.compile('[\s\{\}\[\]\(\)\=]')
105 complete_sep = re.compile('[\s\{\}\[\]\(\)\=]')
105 if completions:
106 if completions:
106 prefix = common_prefix(completions)
107 prefix = common_prefix(completions)
107 residual = complete_sep.split(line)[:-1]
108 residual = complete_sep.split(line)[:-1]
108 line = line[:-len(residual)] + prefix
109 line = line[:-len(residual)] + prefix
109 return line, completions
110 return line, completions
110
111
111
112
112 def render_result(self, result):
113 def render_result(self, result):
113 """ Frontend-specific rendering of the result of a calculation
114 """ Frontend-specific rendering of the result of a calculation
114 that has been sent to an engine.
115 that has been sent to an engine.
115 """
116 """
116 if 'stdout' in result and result['stdout']:
117 if 'stdout' in result and result['stdout']:
117 self.write('\n' + result['stdout'])
118 self.write('\n' + result['stdout'])
118 if 'display' in result and result['display']:
119 if 'display' in result and result['display']:
119 self.write("%s%s\n" % (
120 self.write("%s%s\n" % (
120 self.output_prompt_template.substitute(
121 self.output_prompt_template.substitute(
121 number=result['number']),
122 number=result['number']),
122 result['display']['pprint']
123 result['display']['pprint']
123 ) )
124 ) )
124
125
125
126
126 def render_error(self, failure):
127 def render_error(self, failure):
127 """ Frontend-specific rendering of error.
128 """ Frontend-specific rendering of error.
128 """
129 """
129 self.write('\n\n'+str(failure)+'\n\n')
130 self.write('\n\n'+str(failure)+'\n\n')
130 return failure
131 return failure
131
132
132
133
133 def is_complete(self, string):
134 def is_complete(self, string):
134 """ Check if a string forms a complete, executable set of
135 """ Check if a string forms a complete, executable set of
135 commands.
136 commands.
136
137
137 For the line-oriented frontend, multi-line code is not executed
138 For the line-oriented frontend, multi-line code is not executed
138 as soon as it is complete: the users has to enter two line
139 as soon as it is complete: the users has to enter two line
139 returns.
140 returns.
140 """
141 """
141 if string in ('', '\n'):
142 if string in ('', '\n'):
142 # Prefiltering, eg through ipython0, may return an empty
143 # Prefiltering, eg through ipython0, may return an empty
143 # string although some operations have been accomplished. We
144 # string although some operations have been accomplished. We
144 # thus want to consider an empty string as a complete
145 # thus want to consider an empty string as a complete
145 # statement.
146 # statement.
146 return True
147 return True
147 elif ( len(self.input_buffer.split('\n'))>2
148 elif ( len(self.input_buffer.split('\n'))>2
148 and not re.findall(r"\n[\t ]*\n[\t ]*$", string)):
149 and not re.findall(r"\n[\t ]*\n[\t ]*$", string)):
149 return False
150 return False
150 else:
151 else:
151 self.capture_output()
152 self.capture_output()
152 try:
153 try:
153 # Add line returns here, to make sure that the statement is
154 # Add line returns here, to make sure that the statement is
154 # complete.
155 # complete (except if '\' was used).
155 is_complete = codeop.compile_command(string.rstrip() + '\n\n',
156 # This should probably be done in a different place (like
157 # maybe 'prefilter_input' method? For now, this works.
158 clean_string = string.rstrip('\n')
159 if not clean_string.endswith('\\'): clean_string +='\n\n'
160 is_complete = codeop.compile_command(clean_string,
156 "<string>", "exec")
161 "<string>", "exec")
157 self.release_output()
162 self.release_output()
158 except Exception, e:
163 except Exception, e:
159 # XXX: Hack: return True so that the
164 # XXX: Hack: return True so that the
160 # code gets executed and the error captured.
165 # code gets executed and the error captured.
161 is_complete = True
166 is_complete = True
162 return is_complete
167 return is_complete
163
168
164
169
165 def write(self, string, refresh=True):
170 def write(self, string, refresh=True):
166 """ Write some characters to the display.
171 """ Write some characters to the display.
167
172
168 Subclass should overide this method.
173 Subclass should overide this method.
169
174
170 The refresh keyword argument is used in frontends with an
175 The refresh keyword argument is used in frontends with an
171 event loop, to choose whether the write should trigget an UI
176 event loop, to choose whether the write should trigget an UI
172 refresh, and thus be syncrhonous, or not.
177 refresh, and thus be syncrhonous, or not.
173 """
178 """
174 print >>sys.__stderr__, string
179 print >>sys.__stderr__, string
175
180
176
181
177 def execute(self, python_string, raw_string=None):
182 def execute(self, python_string, raw_string=None):
178 """ Stores the raw_string in the history, and sends the
183 """ Stores the raw_string in the history, and sends the
179 python string to the interpreter.
184 python string to the interpreter.
180 """
185 """
181 if raw_string is None:
186 if raw_string is None:
182 raw_string = python_string
187 raw_string = python_string
183 # Create a false result, in case there is an exception
188 # Create a false result, in case there is an exception
184 self.last_result = dict(number=self.prompt_number)
189 self.last_result = dict(number=self.prompt_number)
185
190
186 ## try:
187 ## self.history.input_cache[-1] = raw_string.rstrip()
188 ## result = self.shell.execute(python_string)
189 ## self.last_result = result
190 ## self.render_result(result)
191 ## except:
192 ## self.show_traceback()
193 ## finally:
194 ## self.after_execute()
195
196 try:
191 try:
197 try:
192 try:
198 self.history.input_cache[-1] = raw_string.rstrip()
193 self.history.input_cache[-1] = raw_string.rstrip()
199 result = self.shell.execute(python_string)
194 result = self.shell.execute(python_string)
200 self.last_result = result
195 self.last_result = result
201 self.render_result(result)
196 self.render_result(result)
202 except:
197 except:
203 self.show_traceback()
198 self.show_traceback()
204 finally:
199 finally:
205 self.after_execute()
200 self.after_execute()
206
201
207
202
208 #--------------------------------------------------------------------------
203 #--------------------------------------------------------------------------
209 # LineFrontEndBase interface
204 # LineFrontEndBase interface
210 #--------------------------------------------------------------------------
205 #--------------------------------------------------------------------------
211
206
212 def prefilter_input(self, string):
207 def prefilter_input(self, string):
213 """ Prefilter the input to turn it in valid python.
208 """ Prefilter the input to turn it in valid python.
214 """
209 """
215 string = string.replace('\r\n', '\n')
210 string = string.replace('\r\n', '\n')
216 string = string.replace('\t', 4*' ')
211 string = string.replace('\t', 4*' ')
217 # Clean the trailing whitespace
212 # Clean the trailing whitespace
218 string = '\n'.join(l.rstrip() for l in string.split('\n'))
213 string = '\n'.join(l.rstrip() for l in string.split('\n'))
219 return string
214 return string
220
215
221
216
222 def after_execute(self):
217 def after_execute(self):
223 """ All the operations required after an execution to put the
218 """ All the operations required after an execution to put the
224 terminal back in a shape where it is usable.
219 terminal back in a shape where it is usable.
225 """
220 """
226 self.prompt_number += 1
221 self.prompt_number += 1
227 self.new_prompt(self.input_prompt_template.substitute(
222 self.new_prompt(self.input_prompt_template.substitute(
228 number=(self.last_result['number'] + 1)))
223 number=(self.last_result['number'] + 1)))
229 # Start a new empty history entry
224 # Start a new empty history entry
230 self._add_history(None, '')
225 self._add_history(None, '')
231 self.history_cursor = len(self.history.input_cache) - 1
226 self.history_cursor = len(self.history.input_cache) - 1
232
227
233
228
234 def complete_current_input(self):
229 def complete_current_input(self):
235 """ Do code completion on current line.
230 """ Do code completion on current line.
236 """
231 """
237 if self.debug:
232 if self.debug:
238 print >>sys.__stdout__, "complete_current_input",
233 print >>sys.__stdout__, "complete_current_input",
239 line = self.input_buffer
234 line = self.input_buffer
240 new_line, completions = self.complete(line)
235 new_line, completions = self.complete(line)
241 if len(completions)>1:
236 if len(completions)>1:
242 self.write_completion(completions, new_line=new_line)
237 self.write_completion(completions, new_line=new_line)
243 elif not line == new_line:
238 elif not line == new_line:
244 self.input_buffer = new_line
239 self.input_buffer = new_line
245 if self.debug:
240 if self.debug:
246 print >>sys.__stdout__, 'line', line
241 print >>sys.__stdout__, 'line', line
247 print >>sys.__stdout__, 'new_line', new_line
242 print >>sys.__stdout__, 'new_line', new_line
248 print >>sys.__stdout__, completions
243 print >>sys.__stdout__, completions
249
244
250
245
251 def get_line_width(self):
246 def get_line_width(self):
252 """ Return the width of the line in characters.
247 """ Return the width of the line in characters.
253 """
248 """
254 return 80
249 return 80
255
250
256
251
257 def write_completion(self, possibilities, new_line=None):
252 def write_completion(self, possibilities, new_line=None):
258 """ Write the list of possible completions.
253 """ Write the list of possible completions.
259
254
260 new_line is the completed input line that should be displayed
255 new_line is the completed input line that should be displayed
261 after the completion are writen. If None, the input_buffer
256 after the completion are writen. If None, the input_buffer
262 before the completion is used.
257 before the completion is used.
263 """
258 """
264 if new_line is None:
259 if new_line is None:
265 new_line = self.input_buffer
260 new_line = self.input_buffer
266
261
267 self.write('\n')
262 self.write('\n')
268 max_len = len(max(possibilities, key=len)) + 1
263 max_len = len(max(possibilities, key=len)) + 1
269
264
270 # Now we check how much symbol we can put on a line...
265 # Now we check how much symbol we can put on a line...
271 chars_per_line = self.get_line_width()
266 chars_per_line = self.get_line_width()
272 symbols_per_line = max(1, chars_per_line/max_len)
267 symbols_per_line = max(1, chars_per_line/max_len)
273
268
274 pos = 1
269 pos = 1
275 buf = []
270 completion_string = []
276 for symbol in possibilities:
271 for symbol in possibilities:
277 if pos < symbols_per_line:
272 if pos < symbols_per_line:
278 buf.append(symbol.ljust(max_len))
273 completion_string.append(symbol.ljust(max_len))
279 pos += 1
274 pos += 1
280 else:
275 else:
281 buf.append(symbol.rstrip() + '\n')
276 completion_string.append(symbol.rstrip() + '\n')
282 pos = 1
277 pos = 1
283 self.write(''.join(buf))
278 self.write(''.join(completion_string))
284 self.new_prompt(self.input_prompt_template.substitute(
279 self.new_prompt(self.input_prompt_template.substitute(
285 number=self.last_result['number'] + 1))
280 number=self.last_result['number'] + 1))
286 self.input_buffer = new_line
281 self.input_buffer = new_line
287
282
288
283
289 def new_prompt(self, prompt):
284 def new_prompt(self, prompt):
290 """ Prints a prompt and starts a new editing buffer.
285 """ Prints a prompt and starts a new editing buffer.
291
286
292 Subclasses should use this method to make sure that the
287 Subclasses should use this method to make sure that the
293 terminal is put in a state favorable for a new line
288 terminal is put in a state favorable for a new line
294 input.
289 input.
295 """
290 """
296 self.input_buffer = ''
291 self.input_buffer = ''
297 self.write(prompt)
292 self.write(prompt)
298
293
299
294
295 def continuation_prompt(self):
296 """Returns the current continuation prompt.
297 """
298 return ("."*(len(self.last_prompt)-2) + ': ')
299
300
301 def execute_command(self, command, hidden=False):
302 """ Execute a command, not only in the model, but also in the
303 view, if any.
304 """
305 return self.shell.execute(command)
306
300 #--------------------------------------------------------------------------
307 #--------------------------------------------------------------------------
301 # Private API
308 # Private API
302 #--------------------------------------------------------------------------
309 #--------------------------------------------------------------------------
303
310
304 def _on_enter(self):
311 def _on_enter(self, new_line_pos=0):
305 """ Called when the return key is pressed in a line editing
312 """ Called when the return key is pressed in a line editing
306 buffer.
313 buffer.
314
315 Parameters
316 ----------
317 new_line_pos : integer, optional
318 Position of the new line to add, starting from the
319 end (0 adds a new line after the last line, -1 before
320 the last line...)
321
322 Returns
323 -------
324 True if execution is triggered
307 """
325 """
308 current_buffer = self.input_buffer
326 current_buffer = self.input_buffer
309 cleaned_buffer = self.prefilter_input(current_buffer)
327 # XXX: This string replace is ugly, but there should be no way it
328 # fails.
329 prompt_less_buffer = re.sub('^' + self.continuation_prompt(),
330 '', current_buffer).replace('\n' + self.continuation_prompt(),
331 '\n')
332 cleaned_buffer = self.prefilter_input(prompt_less_buffer)
310 if self.is_complete(cleaned_buffer):
333 if self.is_complete(cleaned_buffer):
311 self.execute(cleaned_buffer, raw_string=current_buffer)
334 self.execute(cleaned_buffer, raw_string=current_buffer)
335 return True
312 else:
336 else:
313 self.input_buffer += self._get_indent_string(
337 # Start a new line.
314 current_buffer[:-1])
338 new_line_pos = -new_line_pos
315 if len(current_buffer.split('\n')) == 2:
339 lines = current_buffer.split('\n')[:-1]
316 self.input_buffer += '\t\t'
340 prompt_less_lines = prompt_less_buffer.split('\n')
317 if current_buffer[:-1].split('\n')[-1].rstrip().endswith(':'):
341 # Create the new line, with the continuation prompt, and the
318 self.input_buffer += '\t'
342 # same amount of indent than the line above it.
319
343 new_line = self.continuation_prompt() + \
344 self._get_indent_string('\n'.join(
345 prompt_less_lines[:new_line_pos-1]))
346 if len(lines) == 1:
347 # We are starting a first continuation line. Indent it.
348 new_line += '\t'
349 elif current_buffer[:-1].split('\n')[-1].rstrip().endswith(':'):
350 # The last line ends with ":", autoindent the new line.
351 new_line += '\t'
352
353 if new_line_pos == 0:
354 lines.append(new_line)
355 else:
356 lines.insert(new_line_pos, new_line)
357 self.input_buffer = '\n'.join(lines)
358
320
359
321 def _get_indent_string(self, string):
360 def _get_indent_string(self, string):
322 """ Return the string of whitespace that prefixes a line. Used to
361 """ Return the string of whitespace that prefixes a line. Used to
323 add the right amount of indendation when creating a new line.
362 add the right amount of indendation when creating a new line.
324 """
363 """
325 string = string.replace('\t', ' '*4)
364 string = string.replace('\t', ' '*4)
326 string = string.split('\n')[-1]
365 string = string.split('\n')[-1]
327 indent_chars = len(string) - len(string.lstrip())
366 indent_chars = len(string) - len(string.lstrip())
328 indent_string = '\t'*(indent_chars // 4) + \
367 indent_string = '\t'*(indent_chars // 4) + \
329 ' '*(indent_chars % 4)
368 ' '*(indent_chars % 4)
330
369
331 return indent_string
370 return indent_string
332
371
333
372
@@ -1,246 +1,285 b''
1 """
1 """
2 Frontend class that uses IPython0 to prefilter the inputs.
2 Frontend class that uses IPython0 to prefilter the inputs.
3
3
4 Using the IPython0 mechanism gives us access to the magics.
4 Using the IPython0 mechanism gives us access to the magics.
5
5
6 This is a transitory class, used here to do the transition between
6 This is a transitory class, used here to do the transition between
7 ipython0 and ipython1. This class is meant to be short-lived as more
7 ipython0 and ipython1. This class is meant to be short-lived as more
8 functionnality is abstracted out of ipython0 in reusable functions and
8 functionnality is abstracted out of ipython0 in reusable functions and
9 is added on the interpreter. This class can be a used to guide this
9 is added on the interpreter. This class can be a used to guide this
10 refactoring.
10 refactoring.
11 """
11 """
12 __docformat__ = "restructuredtext en"
12 __docformat__ = "restructuredtext en"
13
13
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15 # Copyright (C) 2008 The IPython Development Team
15 # Copyright (C) 2008 The IPython Development Team
16 #
16 #
17 # Distributed under the terms of the BSD License. The full license is in
17 # Distributed under the terms of the BSD License. The full license is in
18 # the file COPYING, distributed as part of this software.
18 # the file COPYING, distributed as part of this software.
19 #-------------------------------------------------------------------------------
19 #-------------------------------------------------------------------------------
20
20
21 #-------------------------------------------------------------------------------
21 #-------------------------------------------------------------------------------
22 # Imports
22 # Imports
23 #-------------------------------------------------------------------------------
23 #-------------------------------------------------------------------------------
24 import sys
24 import sys
25
25 import pydoc
26 from linefrontendbase import LineFrontEndBase, common_prefix
26 import os
27 from frontendbase import FrontEndBase
27 import re
28 import __builtin__
28
29
29 from IPython.ipmaker import make_IPython
30 from IPython.ipmaker import make_IPython
30 from IPython.ipapi import IPApi
31 from IPython.ipapi import IPApi
31 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
32 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
32
33
33 from IPython.kernel.core.sync_traceback_trap import SyncTracebackTrap
34 from IPython.kernel.core.sync_traceback_trap import SyncTracebackTrap
34
35
35 from IPython.genutils import Term
36 from IPython.genutils import Term
36 import pydoc
37
37 import os
38 from linefrontendbase import LineFrontEndBase, common_prefix
38 import sys
39
39
40
40
41 def mk_system_call(system_call_function, command):
41 def mk_system_call(system_call_function, command):
42 """ given a os.system replacement, and a leading string command,
42 """ given a os.system replacement, and a leading string command,
43 returns a function that will execute the command with the given
43 returns a function that will execute the command with the given
44 argument string.
44 argument string.
45 """
45 """
46 def my_system_call(args):
46 def my_system_call(args):
47 system_call_function("%s %s" % (command, args))
47 system_call_function("%s %s" % (command, args))
48
49 my_system_call.__doc__ = "Calls %s" % command
48 return my_system_call
50 return my_system_call
49
51
50 #-------------------------------------------------------------------------------
52 #-------------------------------------------------------------------------------
51 # Frontend class using ipython0 to do the prefiltering.
53 # Frontend class using ipython0 to do the prefiltering.
52 #-------------------------------------------------------------------------------
54 #-------------------------------------------------------------------------------
53 class PrefilterFrontEnd(LineFrontEndBase):
55 class PrefilterFrontEnd(LineFrontEndBase):
54 """ Class that uses ipython0 to do prefilter the input, do the
56 """ Class that uses ipython0 to do prefilter the input, do the
55 completion and the magics.
57 completion and the magics.
56
58
57 The core trick is to use an ipython0 instance to prefilter the
59 The core trick is to use an ipython0 instance to prefilter the
58 input, and share the namespace between the interpreter instance used
60 input, and share the namespace between the interpreter instance used
59 to execute the statements and the ipython0 used for code
61 to execute the statements and the ipython0 used for code
60 completion...
62 completion...
61 """
63 """
62
64
63 debug = False
65 debug = False
64
66
65 def __init__(self, ipython0=None, *args, **kwargs):
67 def __init__(self, ipython0=None, argv=None, *args, **kwargs):
66 """ Parameters:
68 """ Parameters:
67 -----------
69 -----------
68
70
69 ipython0: an optional ipython0 instance to use for command
71 ipython0: an optional ipython0 instance to use for command
70 prefiltering and completion.
72 prefiltering and completion.
73
74 argv : list, optional
75 Used as the instance's argv value. If not given, [] is used.
71 """
76 """
77 if argv is None:
78 argv = []
79 # This is a hack to avoid the IPython exception hook to trigger
80 # on exceptions (https://bugs.launchpad.net/bugs/337105)
81 # XXX: This is horrible: module-leve monkey patching -> side
82 # effects.
83 from IPython import iplib
84 iplib.InteractiveShell.isthreaded = True
85
72 LineFrontEndBase.__init__(self, *args, **kwargs)
86 LineFrontEndBase.__init__(self, *args, **kwargs)
73 self.shell.output_trap = RedirectorOutputTrap(
87 self.shell.output_trap = RedirectorOutputTrap(
74 out_callback=self.write,
88 out_callback=self.write,
75 err_callback=self.write,
89 err_callback=self.write,
76 )
90 )
77 self.shell.traceback_trap = SyncTracebackTrap(
91 self.shell.traceback_trap = SyncTracebackTrap(
78 formatters=self.shell.traceback_trap.formatters,
92 formatters=self.shell.traceback_trap.formatters,
79 )
93 )
80
94
81 # Start the ipython0 instance:
95 # Start the ipython0 instance:
82 self.save_output_hooks()
96 self.save_output_hooks()
83 if ipython0 is None:
97 if ipython0 is None:
84 # Instanciate an IPython0 interpreter to be able to use the
98 # Instanciate an IPython0 interpreter to be able to use the
85 # prefiltering.
99 # prefiltering.
100 # Suppress all key input, to avoid waiting
101 def my_rawinput(x=None):
102 return '\n'
103 old_rawinput = __builtin__.raw_input
104 __builtin__.raw_input = my_rawinput
86 # XXX: argv=[] is a bit bold.
105 # XXX: argv=[] is a bit bold.
87 ipython0 = make_IPython(argv=[],
106 ipython0 = make_IPython(argv=argv,
88 user_ns=self.shell.user_ns,
107 user_ns=self.shell.user_ns,
89 user_global_ns=self.shell.user_global_ns)
108 user_global_ns=self.shell.user_global_ns)
109 __builtin__.raw_input = old_rawinput
90 self.ipython0 = ipython0
110 self.ipython0 = ipython0
91 # Set the pager:
111 # Set the pager:
92 self.ipython0.set_hook('show_in_pager',
112 self.ipython0.set_hook('show_in_pager',
93 lambda s, string: self.write("\n" + string))
113 lambda s, string: self.write("\n" + string))
94 self.ipython0.write = self.write
114 self.ipython0.write = self.write
95 self._ip = _ip = IPApi(self.ipython0)
115 self._ip = _ip = IPApi(self.ipython0)
96 # Make sure the raw system call doesn't get called, as we don't
116 # Make sure the raw system call doesn't get called, as we don't
97 # have a stdin accessible.
117 # have a stdin accessible.
98 self._ip.system = self.system_call
118 self._ip.system = self.system_call
99 # XXX: Muck around with magics so that they work better
119 # XXX: Muck around with magics so that they work better
100 # in our environment
120 # in our environment
101 self.ipython0.magic_ls = mk_system_call(self.system_call,
121 if not sys.platform.startswith('win'):
102 'ls -CF')
122 self.ipython0.magic_ls = mk_system_call(self.system_call,
123 'ls -CF')
103 # And now clean up the mess created by ipython0
124 # And now clean up the mess created by ipython0
104 self.release_output()
125 self.release_output()
105
126
106
127
107 if not 'banner' in kwargs and self.banner is None:
128 if not 'banner' in kwargs and self.banner is None:
108 self.banner = self.ipython0.BANNER + """
129 self.banner = self.ipython0.BANNER
109 This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code."""
110
130
131 # FIXME: __init__ and start should be two different steps
111 self.start()
132 self.start()
112
133
113 #--------------------------------------------------------------------------
134 #--------------------------------------------------------------------------
114 # FrontEndBase interface
135 # FrontEndBase interface
115 #--------------------------------------------------------------------------
136 #--------------------------------------------------------------------------
116
137
117 def show_traceback(self):
138 def show_traceback(self):
118 """ Use ipython0 to capture the last traceback and display it.
139 """ Use ipython0 to capture the last traceback and display it.
119 """
140 """
120 self.capture_output()
141 # Don't do the capture; the except_hook has already done some
142 # modifications to the IO streams, if we store them, we'll be
143 # storing the wrong ones.
144 #self.capture_output()
121 self.ipython0.showtraceback(tb_offset=-1)
145 self.ipython0.showtraceback(tb_offset=-1)
122 self.release_output()
146 self.release_output()
123
147
124
148
125 def execute(self, python_string, raw_string=None):
149 def execute(self, python_string, raw_string=None):
126 if self.debug:
150 if self.debug:
127 print 'Executing Python code:', repr(python_string)
151 print 'Executing Python code:', repr(python_string)
128 self.capture_output()
152 self.capture_output()
129 LineFrontEndBase.execute(self, python_string,
153 LineFrontEndBase.execute(self, python_string,
130 raw_string=raw_string)
154 raw_string=raw_string)
131 self.release_output()
155 self.release_output()
132
156
133
157
134 def save_output_hooks(self):
158 def save_output_hooks(self):
135 """ Store all the output hooks we can think of, to be able to
159 """ Store all the output hooks we can think of, to be able to
136 restore them.
160 restore them.
137
161
138 We need to do this early, as starting the ipython0 instance will
162 We need to do this early, as starting the ipython0 instance will
139 screw ouput hooks.
163 screw ouput hooks.
140 """
164 """
141 self.__old_cout_write = Term.cout.write
165 self.__old_cout_write = Term.cout.write
142 self.__old_cerr_write = Term.cerr.write
166 self.__old_cerr_write = Term.cerr.write
143 self.__old_stdout = sys.stdout
167 self.__old_stdout = sys.stdout
144 self.__old_stderr= sys.stderr
168 self.__old_stderr= sys.stderr
145 self.__old_help_output = pydoc.help.output
169 self.__old_help_output = pydoc.help.output
146 self.__old_display_hook = sys.displayhook
170 self.__old_display_hook = sys.displayhook
147
171
148
172
149 def capture_output(self):
173 def capture_output(self):
150 """ Capture all the output mechanisms we can think of.
174 """ Capture all the output mechanisms we can think of.
151 """
175 """
152 self.save_output_hooks()
176 self.save_output_hooks()
153 Term.cout.write = self.write
177 Term.cout.write = self.write
154 Term.cerr.write = self.write
178 Term.cerr.write = self.write
155 sys.stdout = Term.cout
179 sys.stdout = Term.cout
156 sys.stderr = Term.cerr
180 sys.stderr = Term.cerr
157 pydoc.help.output = self.shell.output_trap.out
181 pydoc.help.output = self.shell.output_trap.out
158
182
159
183
160 def release_output(self):
184 def release_output(self):
161 """ Release all the different captures we have made.
185 """ Release all the different captures we have made.
162 """
186 """
163 Term.cout.write = self.__old_cout_write
187 Term.cout.write = self.__old_cout_write
164 Term.cerr.write = self.__old_cerr_write
188 Term.cerr.write = self.__old_cerr_write
165 sys.stdout = self.__old_stdout
189 sys.stdout = self.__old_stdout
166 sys.stderr = self.__old_stderr
190 sys.stderr = self.__old_stderr
167 pydoc.help.output = self.__old_help_output
191 pydoc.help.output = self.__old_help_output
168 sys.displayhook = self.__old_display_hook
192 sys.displayhook = self.__old_display_hook
169
193
170
194
171 def complete(self, line):
195 def complete(self, line):
172 # FIXME: This should be factored out in the linefrontendbase
196 # FIXME: This should be factored out in the linefrontendbase
173 # method.
197 # method.
174 word = line.split('\n')[-1].split(' ')[-1]
198 word = self._get_completion_text(line)
175 completions = self.ipython0.complete(word)
199 completions = self.ipython0.complete(word)
176 # FIXME: The proper sort should be done in the complete method.
200 # FIXME: The proper sort should be done in the complete method.
177 key = lambda x: x.replace('_', '')
201 key = lambda x: x.replace('_', '')
178 completions.sort(key=key)
202 completions.sort(key=key)
179 if completions:
203 if completions:
180 prefix = common_prefix(completions)
204 prefix = common_prefix(completions)
181 line = line[:-len(word)] + prefix
205 line = line[:-len(word)] + prefix
182 return line, completions
206 return line, completions
183
207
184
208
185 #--------------------------------------------------------------------------
209 #--------------------------------------------------------------------------
186 # LineFrontEndBase interface
210 # LineFrontEndBase interface
187 #--------------------------------------------------------------------------
211 #--------------------------------------------------------------------------
188
212
189 def prefilter_input(self, input_string):
213 def prefilter_input(self, input_string):
190 """ Using IPython0 to prefilter the commands to turn them
214 """ Using IPython0 to prefilter the commands to turn them
191 in executable statements that are valid Python strings.
215 in executable statements that are valid Python strings.
192 """
216 """
193 input_string = LineFrontEndBase.prefilter_input(self, input_string)
217 input_string = LineFrontEndBase.prefilter_input(self, input_string)
194 filtered_lines = []
218 filtered_lines = []
195 # The IPython0 prefilters sometime produce output. We need to
219 # The IPython0 prefilters sometime produce output. We need to
196 # capture it.
220 # capture it.
197 self.capture_output()
221 self.capture_output()
198 self.last_result = dict(number=self.prompt_number)
222 self.last_result = dict(number=self.prompt_number)
199
223
200 ## try:
224 ## try:
201 ## for line in input_string.split('\n'):
225 ## for line in input_string.split('\n'):
202 ## filtered_lines.append(
226 ## filtered_lines.append(
203 ## self.ipython0.prefilter(line, False).rstrip())
227 ## self.ipython0.prefilter(line, False).rstrip())
204 ## except:
228 ## except:
205 ## # XXX: probably not the right thing to do.
229 ## # XXX: probably not the right thing to do.
206 ## self.ipython0.showsyntaxerror()
230 ## self.ipython0.showsyntaxerror()
207 ## self.after_execute()
231 ## self.after_execute()
208 ## finally:
232 ## finally:
209 ## self.release_output()
233 ## self.release_output()
210
234
211
235
212 try:
236 try:
213 try:
237 try:
214 for line in input_string.split('\n'):
238 for line in input_string.split('\n'):
215 filtered_lines.append(
239 filtered_lines.append(
216 self.ipython0.prefilter(line, False).rstrip())
240 self.ipython0.prefilter(line, False).rstrip())
217 except:
241 except:
218 # XXX: probably not the right thing to do.
242 # XXX: probably not the right thing to do.
219 self.ipython0.showsyntaxerror()
243 self.ipython0.showsyntaxerror()
220 self.after_execute()
244 self.after_execute()
221 finally:
245 finally:
222 self.release_output()
246 self.release_output()
223
247
224
248
225
249
226 # Clean up the trailing whitespace, to avoid indentation errors
250 # Clean up the trailing whitespace, to avoid indentation errors
227 filtered_string = '\n'.join(filtered_lines)
251 filtered_string = '\n'.join(filtered_lines)
228 return filtered_string
252 return filtered_string
229
253
230
254
231 #--------------------------------------------------------------------------
255 #--------------------------------------------------------------------------
232 # PrefilterFrontEnd interface
256 # PrefilterFrontEnd interface
233 #--------------------------------------------------------------------------
257 #--------------------------------------------------------------------------
234
258
235 def system_call(self, command_string):
259 def system_call(self, command_string):
236 """ Allows for frontend to define their own system call, to be
260 """ Allows for frontend to define their own system call, to be
237 able capture output and redirect input.
261 able capture output and redirect input.
238 """
262 """
239 return os.system(command_string)
263 return os.system(command_string)
240
264
241
265
242 def do_exit(self):
266 def do_exit(self):
243 """ Exit the shell, cleanup and save the history.
267 """ Exit the shell, cleanup and save the history.
244 """
268 """
245 self.ipython0.atexit_operations()
269 self.ipython0.atexit_operations()
246
270
271
272 def _get_completion_text(self, line):
273 """ Returns the text to be completed by breaking the line at specified
274 delimiters.
275 """
276 # Break at: spaces, '=', all parentheses (except if balanced).
277 # FIXME2: In the future, we need to make the implementation similar to
278 # that in the 'pyreadline' module (modes/basemode.py) where we break at
279 # each delimiter and try to complete the residual line, until we get a
280 # successful list of completions.
281 expression = '\s|=|,|:|\((?!.*\))|\[(?!.*\])|\{(?!.*\})'
282 complete_sep = re.compile(expression)
283 text = complete_sep.split(line)[-1]
284 return text
285
1 NO CONTENT: file renamed from IPython/frontend/_process/__init__.py to IPython/frontend/process/__init__.py
NO CONTENT: file renamed from IPython/frontend/_process/__init__.py to IPython/frontend/process/__init__.py
@@ -1,179 +1,184 b''
1 # Addapted from killableprocess.py.
1 # Addapted from killableprocess.py.
2 #______________________________________________________________________________
2 #______________________________________________________________________________
3 #
3 #
4 # killableprocess - subprocesses which can be reliably killed
4 # killableprocess - subprocesses which can be reliably killed
5 #
5 #
6 # Parts of this module are copied from the subprocess.py file contained
6 # Parts of this module are copied from the subprocess.py file contained
7 # in the Python distribution.
7 # in the Python distribution.
8 #
8 #
9 # Copyright (c) 2003-2004 by Peter Astrand <astrand@lysator.liu.se>
9 # Copyright (c) 2003-2004 by Peter Astrand <astrand@lysator.liu.se>
10 #
10 #
11 # Additions and modifications written by Benjamin Smedberg
11 # Additions and modifications written by Benjamin Smedberg
12 # <benjamin@smedbergs.us> are Copyright (c) 2006 by the Mozilla Foundation
12 # <benjamin@smedbergs.us> are Copyright (c) 2006 by the Mozilla Foundation
13 # <http://www.mozilla.org/>
13 # <http://www.mozilla.org/>
14 #
14 #
15 # By obtaining, using, and/or copying this software and/or its
15 # By obtaining, using, and/or copying this software and/or its
16 # associated documentation, you agree that you have read, understood,
16 # associated documentation, you agree that you have read, understood,
17 # and will comply with the following terms and conditions:
17 # and will comply with the following terms and conditions:
18 #
18 #
19 # Permission to use, copy, modify, and distribute this software and
19 # Permission to use, copy, modify, and distribute this software and
20 # its associated documentation for any purpose and without fee is
20 # its associated documentation for any purpose and without fee is
21 # hereby granted, provided that the above copyright notice appears in
21 # hereby granted, provided that the above copyright notice appears in
22 # all copies, and that both that copyright notice and this permission
22 # all copies, and that both that copyright notice and this permission
23 # notice appear in supporting documentation, and that the name of the
23 # notice appear in supporting documentation, and that the name of the
24 # author not be used in advertising or publicity pertaining to
24 # author not be used in advertising or publicity pertaining to
25 # distribution of the software without specific, written prior
25 # distribution of the software without specific, written prior
26 # permission.
26 # permission.
27 #
27 #
28 # THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
28 # THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
29 # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
29 # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
30 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
30 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
31 # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
31 # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
32 # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
32 # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
33 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
33 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
34 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
34 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
35
35
36 r"""killableprocess - Subprocesses which can be reliably killed
36 r"""killableprocess - Subprocesses which can be reliably killed
37
37
38 This module is a subclass of the builtin "subprocess" module. It allows
38 This module is a subclass of the builtin "subprocess" module. It allows
39 processes that launch subprocesses to be reliably killed on Windows (via the Popen.kill() method.
39 processes that launch subprocesses to be reliably killed on Windows (via the Popen.kill() method.
40
40
41 It also adds a timeout argument to Wait() for a limited period of time before
41 It also adds a timeout argument to Wait() for a limited period of time before
42 forcefully killing the process.
42 forcefully killing the process.
43
43
44 Note: On Windows, this module requires Windows 2000 or higher (no support for
44 Note: On Windows, this module requires Windows 2000 or higher (no support for
45 Windows 95, 98, or NT 4.0). It also requires ctypes, which is bundled with
45 Windows 95, 98, or NT 4.0). It also requires ctypes, which is bundled with
46 Python 2.5+ or available from http://python.net/crew/theller/ctypes/
46 Python 2.5+ or available from http://python.net/crew/theller/ctypes/
47 """
47 """
48
48
49 import subprocess
49 import subprocess
50 from subprocess import PIPE
50 from subprocess import PIPE
51 import sys
51 import sys
52 import os
52 import os
53 import types
53 import types
54
54
55 try:
55 try:
56 from subprocess import CalledProcessError
56 from subprocess import CalledProcessError
57 except ImportError:
57 except ImportError:
58 # Python 2.4 doesn't implement CalledProcessError
58 # Python 2.4 doesn't implement CalledProcessError
59 class CalledProcessError(Exception):
59 class CalledProcessError(Exception):
60 """This exception is raised when a process run by check_call() returns
60 """This exception is raised when a process run by check_call() returns
61 a non-zero exit status. The exit status will be stored in the
61 a non-zero exit status. The exit status will be stored in the
62 returncode attribute."""
62 returncode attribute."""
63 def __init__(self, returncode, cmd):
63 def __init__(self, returncode, cmd):
64 self.returncode = returncode
64 self.returncode = returncode
65 self.cmd = cmd
65 self.cmd = cmd
66 def __str__(self):
66 def __str__(self):
67 return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode)
67 return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode)
68
68
69 mswindows = (sys.platform == "win32")
69 mswindows = (sys.platform == "win32")
70
70
71 skip = False
71 skip = False
72
72
73 if mswindows:
73 if mswindows:
74 import platform
74 import platform
75 if platform.uname()[3] == '' or platform.uname()[3] > '6.0.6000':
75 if platform.uname()[3] == '' or platform.uname()[3] > '6.0.6000':
76 # Killable process does not work under vista when starting for
76 # Killable process does not work under vista when starting for
77 # something else than cmd.
77 # something else than cmd.
78 skip = True
78 skip = True
79 else:
79 else:
80 import winprocess
80 import winprocess
81 else:
81 else:
82 import signal
82 import signal
83
83
84 if not mswindows:
84 if not mswindows:
85 def DoNothing(*args):
85 def DoNothing(*args):
86 pass
86 pass
87
87
88
88
89 if skip:
89 if skip:
90 Popen = subprocess.Popen
90 Popen = subprocess.Popen
91 else:
91 else:
92 class Popen(subprocess.Popen):
92 class Popen(subprocess.Popen):
93 if not mswindows:
93 if not mswindows:
94 # Override __init__ to set a preexec_fn
94 # Override __init__ to set a preexec_fn
95 def __init__(self, *args, **kwargs):
95 def __init__(self, *args, **kwargs):
96 if len(args) >= 7:
96 if len(args) >= 7:
97 raise Exception("Arguments preexec_fn and after must be passed by keyword.")
97 raise Exception("Arguments preexec_fn and after must be passed by keyword.")
98
98
99 real_preexec_fn = kwargs.pop("preexec_fn", None)
99 real_preexec_fn = kwargs.pop("preexec_fn", None)
100 def setpgid_preexec_fn():
100 def setpgid_preexec_fn():
101 os.setpgid(0, 0)
101 os.setpgid(0, 0)
102 if real_preexec_fn:
102 if real_preexec_fn:
103 apply(real_preexec_fn)
103 apply(real_preexec_fn)
104
104
105 kwargs['preexec_fn'] = setpgid_preexec_fn
105 kwargs['preexec_fn'] = setpgid_preexec_fn
106
106
107 subprocess.Popen.__init__(self, *args, **kwargs)
107 subprocess.Popen.__init__(self, *args, **kwargs)
108
108
109 if mswindows:
109 if mswindows:
110 def _execute_child(self, args, executable, preexec_fn, close_fds,
110 def _execute_child(self, args, executable, preexec_fn, close_fds,
111 cwd, env, universal_newlines, startupinfo,
111 cwd, env, universal_newlines, startupinfo,
112 creationflags, shell,
112 creationflags, shell,
113 p2cread, p2cwrite,
113 p2cread, p2cwrite,
114 c2pread, c2pwrite,
114 c2pread, c2pwrite,
115 errread, errwrite):
115 errread, errwrite):
116 if not isinstance(args, types.StringTypes):
116 if not isinstance(args, types.StringTypes):
117 args = subprocess.list2cmdline(args)
117 args = subprocess.list2cmdline(args)
118
118
119 if startupinfo is None:
119 if startupinfo is None:
120 startupinfo = winprocess.STARTUPINFO()
120 startupinfo = winprocess.STARTUPINFO()
121
121
122 if None not in (p2cread, c2pwrite, errwrite):
122 if None not in (p2cread, c2pwrite, errwrite):
123 startupinfo.dwFlags |= winprocess.STARTF_USESTDHANDLES
123 startupinfo.dwFlags |= winprocess.STARTF_USESTDHANDLES
124
124
125 startupinfo.hStdInput = int(p2cread)
125 startupinfo.hStdInput = int(p2cread)
126 startupinfo.hStdOutput = int(c2pwrite)
126 startupinfo.hStdOutput = int(c2pwrite)
127 startupinfo.hStdError = int(errwrite)
127 startupinfo.hStdError = int(errwrite)
128 if shell:
128 if shell:
129 startupinfo.dwFlags |= winprocess.STARTF_USESHOWWINDOW
129 startupinfo.dwFlags |= winprocess.STARTF_USESHOWWINDOW
130 startupinfo.wShowWindow = winprocess.SW_HIDE
130 startupinfo.wShowWindow = winprocess.SW_HIDE
131 comspec = os.environ.get("COMSPEC", "cmd.exe")
131 comspec = os.environ.get("COMSPEC", "cmd.exe")
132 args = comspec + " /c " + args
132 args = comspec + " /c " + args
133
133
134 # We create a new job for this process, so that we can kill
134 # We create a new job for this process, so that we can kill
135 # the process and any sub-processes
135 # the process and any sub-processes
136 self._job = winprocess.CreateJobObject()
136 self._job = winprocess.CreateJobObject()
137
137
138 creationflags |= winprocess.CREATE_SUSPENDED
138 creationflags |= winprocess.CREATE_SUSPENDED
139 creationflags |= winprocess.CREATE_UNICODE_ENVIRONMENT
139 creationflags |= winprocess.CREATE_UNICODE_ENVIRONMENT
140
140
141 hp, ht, pid, tid = winprocess.CreateProcess(
141 hp, ht, pid, tid = winprocess.CreateProcess(
142 executable, args,
142 executable, args,
143 None, None, # No special security
143 None, None, # No special security
144 1, # Must inherit handles!
144 1, # Must inherit handles!
145 creationflags,
145 creationflags,
146 winprocess.EnvironmentBlock(env),
146 winprocess.EnvironmentBlock(env),
147 cwd, startupinfo)
147 cwd, startupinfo)
148
148
149 self._child_created = True
149 self._child_created = True
150 self._handle = hp
150 self._handle = hp
151 self._thread = ht
151 self._thread = ht
152 self.pid = pid
152 self.pid = pid
153
153
154 winprocess.AssignProcessToJobObject(self._job, hp)
154 # XXX: A try/except to fix UAC-related problems under
155 # Windows Vista, when reparenting jobs.
156 try:
157 winprocess.AssignProcessToJobObject(self._job, hp)
158 except WindowsError:
159 pass
155 winprocess.ResumeThread(ht)
160 winprocess.ResumeThread(ht)
156
161
157 if p2cread is not None:
162 if p2cread is not None:
158 p2cread.Close()
163 p2cread.Close()
159 if c2pwrite is not None:
164 if c2pwrite is not None:
160 c2pwrite.Close()
165 c2pwrite.Close()
161 if errwrite is not None:
166 if errwrite is not None:
162 errwrite.Close()
167 errwrite.Close()
163
168
164 def kill(self, group=True):
169 def kill(self, group=True):
165 """Kill the process. If group=True, all sub-processes will also be killed."""
170 """Kill the process. If group=True, all sub-processes will also be killed."""
166 if mswindows:
171 if mswindows:
167 if group:
172 if group:
168 winprocess.TerminateJobObject(self._job, 127)
173 winprocess.TerminateJobObject(self._job, 127)
169 else:
174 else:
170 winprocess.TerminateProcess(self._handle, 127)
175 winprocess.TerminateProcess(self._handle, 127)
171 self.returncode = 127
176 self.returncode = 127
172 else:
177 else:
173 if group:
178 if group:
174 os.killpg(self.pid, signal.SIGKILL)
179 os.killpg(self.pid, signal.SIGKILL)
175 else:
180 else:
176 os.kill(self.pid, signal.SIGKILL)
181 os.kill(self.pid, signal.SIGKILL)
177 self.returncode = -9
182 self.returncode = -9
178
183
179
184
1 NO CONTENT: file renamed from IPython/frontend/_process/pipedprocess.py to IPython/frontend/process/pipedprocess.py
NO CONTENT: file renamed from IPython/frontend/_process/pipedprocess.py to IPython/frontend/process/pipedprocess.py
1 NO CONTENT: file renamed from IPython/frontend/_process/winprocess.py to IPython/frontend/process/winprocess.py
NO CONTENT: file renamed from IPython/frontend/_process/winprocess.py to IPython/frontend/process/winprocess.py
@@ -1,155 +1,109 b''
1 # encoding: utf-8
1 # encoding: utf-8
2
2
3 """This file contains unittests for the frontendbase module."""
3 """This file contains unittests for the asyncfrontendbase module."""
4
4
5 __docformat__ = "restructuredtext en"
5 __docformat__ = "restructuredtext en"
6
6
7 #---------------------------------------------------------------------------
7 #---------------------------------------------------------------------------
8 # Copyright (C) 2008 The IPython Development Team
8 # Copyright (C) 2008 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #---------------------------------------------------------------------------
12 #---------------------------------------------------------------------------
13
13
14 #---------------------------------------------------------------------------
14 #---------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #---------------------------------------------------------------------------
16 #---------------------------------------------------------------------------
17
17
18 import unittest
18 # Tell nose to skip this module
19 __test__ = {}
19
20
20 try:
21 from twisted.trial import unittest
21 from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase
22 from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase
22 from IPython.frontend import frontendbase
23 from IPython.frontend import frontendbase
23 from IPython.kernel.engineservice import EngineService
24 from IPython.kernel.engineservice import EngineService
24 except ImportError:
25 from IPython.testing.parametric import Parametric, parametric
25 import nose
26 raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap")
27
26
28 from IPython.testing.decorators import skip
29
27
30 class FrontEndCallbackChecker(AsyncFrontEndBase):
28 class FrontEndCallbackChecker(AsyncFrontEndBase):
31 """FrontEndBase subclass for checking callbacks"""
29 """FrontEndBase subclass for checking callbacks"""
32 def __init__(self, engine=None, history=None):
30 def __init__(self, engine=None, history=None):
33 super(FrontEndCallbackChecker, self).__init__(engine=engine,
31 super(FrontEndCallbackChecker, self).__init__(engine=engine,
34 history=history)
32 history=history)
35 self.updateCalled = False
33 self.updateCalled = False
36 self.renderResultCalled = False
34 self.renderResultCalled = False
37 self.renderErrorCalled = False
35 self.renderErrorCalled = False
38
36
39 def update_cell_prompt(self, result, blockID=None):
37 def update_cell_prompt(self, result, blockID=None):
40 self.updateCalled = True
38 self.updateCalled = True
41 return result
39 return result
42
40
43 def render_result(self, result):
41 def render_result(self, result):
44 self.renderResultCalled = True
42 self.renderResultCalled = True
45 return result
43 return result
46
44
47
48 def render_error(self, failure):
45 def render_error(self, failure):
49 self.renderErrorCalled = True
46 self.renderErrorCalled = True
50 return failure
47 return failure
51
52
48
53
49
54
55 class TestAsyncFrontendBase(unittest.TestCase):
50 class TestAsyncFrontendBase(unittest.TestCase):
56 def setUp(self):
51 def setUp(self):
57 """Setup the EngineService and FrontEndBase"""
52 """Setup the EngineService and FrontEndBase"""
58
53
59 self.fb = FrontEndCallbackChecker(engine=EngineService())
54 self.fb = FrontEndCallbackChecker(engine=EngineService())
60
55
61 def test_implements_IFrontEnd(self):
56 def test_implements_IFrontEnd(self):
62 assert(frontendbase.IFrontEnd.implementedBy(
57 self.assert_(frontendbase.IFrontEnd.implementedBy(
63 AsyncFrontEndBase))
58 AsyncFrontEndBase))
64
59
65 def test_is_complete_returns_False_for_incomplete_block(self):
60 def test_is_complete_returns_False_for_incomplete_block(self):
66 """"""
67
68 block = """def test(a):"""
61 block = """def test(a):"""
69
62 self.assert_(self.fb.is_complete(block) == False)
70 assert(self.fb.is_complete(block) == False)
71
63
72 def test_is_complete_returns_True_for_complete_block(self):
64 def test_is_complete_returns_True_for_complete_block(self):
73 """"""
74
75 block = """def test(a): pass"""
65 block = """def test(a): pass"""
76
66 self.assert_(self.fb.is_complete(block))
77 assert(self.fb.is_complete(block))
78
79 block = """a=3"""
67 block = """a=3"""
80
68 self.assert_(self.fb.is_complete(block))
81 assert(self.fb.is_complete(block))
82
69
83 def test_blockID_added_to_result(self):
70 def test_blockID_added_to_result(self):
84 block = """3+3"""
71 block = """3+3"""
85
86 d = self.fb.execute(block, blockID='TEST_ID')
72 d = self.fb.execute(block, blockID='TEST_ID')
87
73 d.addCallback(lambda r: self.assert_(r['blockID']=='TEST_ID'))
88 d.addCallback(self.checkBlockID, expected='TEST_ID')
74 return d
89
75
90 def test_blockID_added_to_failure(self):
76 def test_blockID_added_to_failure(self):
91 block = "raise Exception()"
77 block = "raise Exception()"
92
93 d = self.fb.execute(block,blockID='TEST_ID')
78 d = self.fb.execute(block,blockID='TEST_ID')
94 d.addErrback(self.checkFailureID, expected='TEST_ID')
79 d.addErrback(lambda f: self.assert_(f.blockID=='TEST_ID'))
95
80 return d
96 def checkBlockID(self, result, expected=""):
97 assert(result['blockID'] == expected)
98
99
100 def checkFailureID(self, failure, expected=""):
101 assert(failure.blockID == expected)
102
103
81
104 def test_callbacks_added_to_execute(self):
82 def test_callbacks_added_to_execute(self):
105 """test that
106 update_cell_prompt
107 render_result
108
109 are added to execute request
110 """
111
112 d = self.fb.execute("10+10")
83 d = self.fb.execute("10+10")
113 d.addCallback(self.checkCallbacks)
84 d.addCallback(lambda r: self.assert_(self.fb.updateCalled and self.fb.renderResultCalled))
85 return d
114
86
115 def checkCallbacks(self, result):
116 assert(self.fb.updateCalled)
117 assert(self.fb.renderResultCalled)
118
119 @skip("This test fails and lead to an unhandled error in a Deferred.")
120 def test_error_callback_added_to_execute(self):
87 def test_error_callback_added_to_execute(self):
121 """test that render_error called on execution error"""
88 """Test that render_error called on execution error."""
122
89
123 d = self.fb.execute("raise Exception()")
90 d = self.fb.execute("raise Exception()")
124 d.addCallback(self.checkRenderError)
91 d.addErrback(lambda f: self.assert_(self.fb.renderErrorCalled))
125
92 return d
126 def checkRenderError(self, result):
127 assert(self.fb.renderErrorCalled)
128
93
129 def test_history_returns_expected_block(self):
94 def test_history_returns_expected_block(self):
130 """Make sure history browsing doesn't fail"""
95 """Make sure history browsing doesn't fail."""
131
96
132 blocks = ["a=1","a=2","a=3"]
97 blocks = ["a=1","a=2","a=3"]
133 for b in blocks:
98 d = self.fb.execute(blocks[0])
134 d = self.fb.execute(b)
99 d.addCallback(lambda _: self.fb.execute(blocks[1]))
135
100 d.addCallback(lambda _: self.fb.execute(blocks[2]))
136 # d is now the deferred for the last executed block
101 d.addCallback(lambda _: self.assert_(self.fb.get_history_previous("")==blocks[-2]))
137 d.addCallback(self.historyTests, blocks)
102 d.addCallback(lambda _: self.assert_(self.fb.get_history_previous("")==blocks[-3]))
138
103 d.addCallback(lambda _: self.assert_(self.fb.get_history_next()==blocks[-2]))
139
104 return d
140 def historyTests(self, result, blocks):
105
141 """historyTests"""
106 def test_history_returns_none_at_startup(self):
142
107 self.assert_(self.fb.get_history_previous("")==None)
143 assert(len(blocks) >= 3)
108 self.assert_(self.fb.get_history_next()==None)
144 assert(self.fb.get_history_previous("") == blocks[-2])
109
145 assert(self.fb.get_history_previous("") == blocks[-3])
146 assert(self.fb.get_history_next() == blocks[-2])
147
148
149 def test_history_returns_none_at_startup(self):
150 """test_history_returns_none_at_startup"""
151
152 assert(self.fb.get_history_previous("")==None)
153 assert(self.fb.get_history_next()==None)
154
155
@@ -1,180 +1,252 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Test process execution and IO redirection.
3 Test process execution and IO redirection.
4 """
4 """
5
5
6 __docformat__ = "restructuredtext en"
6 __docformat__ = "restructuredtext en"
7
7
8 #-------------------------------------------------------------------------------
8 #-------------------------------------------------------------------------------
9 # Copyright (C) 2008 The IPython Development Team
9 # Copyright (C) 2008 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is
11 # Distributed under the terms of the BSD License. The full license is
12 # in the file COPYING, distributed as part of this software.
12 # in the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
14
14
15 from copy import copy, deepcopy
15 from cStringIO import StringIO
16 from cStringIO import StringIO
16 import string
17 import string
17
18
18 from IPython.ipapi import get as get_ipython0
19 from nose.tools import assert_equal
20
19 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
21 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
20 from copy import deepcopy
22 from IPython.ipapi import get as get_ipython0
23 from IPython.testing.plugin.ipdoctest import default_argv
24
25
26 def safe_deepcopy(d):
27 """ Deep copy every key of the given dict, when possible. Elsewhere
28 do a copy.
29 """
30 copied_d = dict()
31 for key, value in d.iteritems():
32 try:
33 copied_d[key] = deepcopy(value)
34 except:
35 try:
36 copied_d[key] = copy(value)
37 except:
38 copied_d[key] = value
39 return copied_d
40
21
41
22 class TestPrefilterFrontEnd(PrefilterFrontEnd):
42 class TestPrefilterFrontEnd(PrefilterFrontEnd):
23
43
24 input_prompt_template = string.Template('')
44 input_prompt_template = string.Template('')
25 output_prompt_template = string.Template('')
45 output_prompt_template = string.Template('')
26 banner = ''
46 banner = ''
27
47
28 def __init__(self):
48 def __init__(self):
29 ipython0 = get_ipython0().IP
30 self.out = StringIO()
49 self.out = StringIO()
31 PrefilterFrontEnd.__init__(self, ipython0=ipython0)
50 PrefilterFrontEnd.__init__(self,argv=default_argv())
32 # Clean up the namespace for isolation between tests
33 user_ns = self.ipython0.user_ns
34 # We need to keep references to things so that they don't
35 # get garbage collected (this stinks).
36 self.shadow_ns = dict()
37 for i in self.ipython0.magic_who_ls():
38 self.shadow_ns[i] = user_ns.pop(i)
39 # Some more code for isolation (yeah, crazy)
51 # Some more code for isolation (yeah, crazy)
40 self._on_enter()
52 self._on_enter()
41 self.out.flush()
53 self.out.flush()
42 self.out.reset()
54 self.out.reset()
43 self.out.truncate()
55 self.out.truncate()
44
56
45 def write(self, string, *args, **kwargs):
57 def write(self, string, *args, **kwargs):
46 self.out.write(string)
58 self.out.write(string)
47
59
48 def _on_enter(self):
60 def _on_enter(self):
49 self.input_buffer += '\n'
61 self.input_buffer += '\n'
50 PrefilterFrontEnd._on_enter(self)
62 PrefilterFrontEnd._on_enter(self)
51
63
52
64
53 def isolate_ipython0(func):
65 def isolate_ipython0(func):
54 """ Decorator to isolate execution that involves an iptyhon0.
66 """ Decorator to isolate execution that involves an iptyhon0.
67
68 Notes
69 -----
70
71 Apply only to functions with no arguments. Nose skips functions
72 with arguments.
55 """
73 """
56 def my_func(*args, **kwargs):
74 def my_func():
57 ipython0 = get_ipython0().IP
75 iplib = get_ipython0()
58 user_ns = deepcopy(ipython0.user_ns)
76 if iplib is None:
59 global_ns = deepcopy(ipython0.global_ns)
77 return func()
78 ipython0 = iplib.IP
79 global_ns = safe_deepcopy(ipython0.user_global_ns)
80 user_ns = safe_deepcopy(ipython0.user_ns)
60 try:
81 try:
61 func(*args, **kwargs)
82 out = func()
62 finally:
83 finally:
63 ipython0.user_ns = user_ns
84 ipython0.user_ns = user_ns
64 ipython0.global_ns = global_ns
85 ipython0.user_global_ns = global_ns
86 # Undo the hack at creation of PrefilterFrontEnd
87 from IPython import iplib
88 iplib.InteractiveShell.isthreaded = False
89 return out
65
90
91 my_func.__name__ = func.__name__
66 return my_func
92 return my_func
67
93
68
94
69 @isolate_ipython0
95 @isolate_ipython0
70 def test_execution():
96 def test_execution():
71 """ Test execution of a command.
97 """ Test execution of a command.
72 """
98 """
73 f = TestPrefilterFrontEnd()
99 f = TestPrefilterFrontEnd()
74 f.input_buffer = 'print 1'
100 f.input_buffer = 'print 1'
75 f._on_enter()
101 f._on_enter()
76 out_value = f.out.getvalue()
102 out_value = f.out.getvalue()
77 assert out_value == '1\n'
103 assert_equal(out_value, '1\n')
78
104
79
105
80 @isolate_ipython0
106 @isolate_ipython0
81 def test_multiline():
107 def test_multiline():
82 """ Test execution of a multiline command.
108 """ Test execution of a multiline command.
83 """
109 """
84 f = TestPrefilterFrontEnd()
110 f = TestPrefilterFrontEnd()
85 f.input_buffer = 'if True:'
111 f.input_buffer = 'if True:'
86 f._on_enter()
112 f._on_enter()
87 f.input_buffer += 'print 1'
113 f.input_buffer += 'print 1'
88 f._on_enter()
114 f._on_enter()
89 out_value = f.out.getvalue()
115 out_value = f.out.getvalue()
90 assert out_value == ''
116 yield assert_equal, out_value, ''
91 f._on_enter()
117 f._on_enter()
92 out_value = f.out.getvalue()
118 out_value = f.out.getvalue()
93 assert out_value == '1\n'
119 yield assert_equal, out_value, '1\n'
94 f = TestPrefilterFrontEnd()
120 f = TestPrefilterFrontEnd()
95 f.input_buffer='(1 +'
121 f.input_buffer='(1 +'
96 f._on_enter()
122 f._on_enter()
97 f.input_buffer += '0)'
123 f.input_buffer += '0)'
98 f._on_enter()
124 f._on_enter()
99 out_value = f.out.getvalue()
125 out_value = f.out.getvalue()
100 assert out_value == ''
126 yield assert_equal, out_value, ''
101 f._on_enter()
127 f._on_enter()
102 out_value = f.out.getvalue()
128 out_value = f.out.getvalue()
103 assert out_value == '1\n'
129 yield assert_equal, out_value, '1\n'
104
130
105
131
106 @isolate_ipython0
132 @isolate_ipython0
107 def test_capture():
133 def test_capture():
108 """ Test the capture of output in different channels.
134 """ Test the capture of output in different channels.
109 """
135 """
110 # Test on the OS-level stdout, stderr.
136 # Test on the OS-level stdout, stderr.
111 f = TestPrefilterFrontEnd()
137 f = TestPrefilterFrontEnd()
112 f.input_buffer = \
138 f.input_buffer = \
113 'import os; out=os.fdopen(1, "w"); out.write("1") ; out.flush()'
139 'import os; out=os.fdopen(1, "w"); out.write("1") ; out.flush()'
114 f._on_enter()
140 f._on_enter()
115 out_value = f.out.getvalue()
141 out_value = f.out.getvalue()
116 assert out_value == '1'
142 yield assert_equal, out_value, '1'
117 f = TestPrefilterFrontEnd()
143 f = TestPrefilterFrontEnd()
118 f.input_buffer = \
144 f.input_buffer = \
119 'import os; out=os.fdopen(2, "w"); out.write("1") ; out.flush()'
145 'import os; out=os.fdopen(2, "w"); out.write("1") ; out.flush()'
120 f._on_enter()
146 f._on_enter()
121 out_value = f.out.getvalue()
147 out_value = f.out.getvalue()
122 assert out_value == '1'
148 yield assert_equal, out_value, '1'
123
149
124
150
125 @isolate_ipython0
151 @isolate_ipython0
126 def test_magic():
152 def test_magic():
127 """ Test the magic expansion and history.
153 """ Test the magic expansion and history.
128
154
129 This test is fairly fragile and will break when magics change.
155 This test is fairly fragile and will break when magics change.
130 """
156 """
131 f = TestPrefilterFrontEnd()
157 f = TestPrefilterFrontEnd()
158 # Before checking the interactive namespace, make sure it's clear (it can
159 # otherwise pick up things stored in the user's local db)
160 f.input_buffer += '%reset -f'
161 f._on_enter()
162 f.complete_current_input()
163 # Now, run the %who magic and check output
132 f.input_buffer += '%who'
164 f.input_buffer += '%who'
133 f._on_enter()
165 f._on_enter()
134 out_value = f.out.getvalue()
166 out_value = f.out.getvalue()
135 assert out_value == 'Interactive namespace is empty.\n'
167 assert_equal(out_value, 'Interactive namespace is empty.\n')
136
168
137
169
138 @isolate_ipython0
170 @isolate_ipython0
139 def test_help():
171 def test_help():
140 """ Test object inspection.
172 """ Test object inspection.
141 """
173 """
142 f = TestPrefilterFrontEnd()
174 f = TestPrefilterFrontEnd()
143 f.input_buffer += "def f():"
175 f.input_buffer += "def f():"
144 f._on_enter()
176 f._on_enter()
145 f.input_buffer += "'foobar'"
177 f.input_buffer += "'foobar'"
146 f._on_enter()
178 f._on_enter()
147 f.input_buffer += "pass"
179 f.input_buffer += "pass"
148 f._on_enter()
180 f._on_enter()
149 f._on_enter()
181 f._on_enter()
150 f.input_buffer += "f?"
182 f.input_buffer += "f?"
151 f._on_enter()
183 f._on_enter()
152 assert 'traceback' not in f.last_result
184 assert 'traceback' not in f.last_result
153 ## XXX: ipython doctest magic breaks this. I have no clue why
185 ## XXX: ipython doctest magic breaks this. I have no clue why
154 #out_value = f.out.getvalue()
186 #out_value = f.out.getvalue()
155 #assert out_value.split()[-1] == 'foobar'
187 #assert out_value.split()[-1] == 'foobar'
156
188
157
189
158 @isolate_ipython0
190 @isolate_ipython0
159 def test_completion():
191 def test_completion_simple():
160 """ Test command-line completion.
192 """ Test command-line completion on trivial examples.
161 """
193 """
162 f = TestPrefilterFrontEnd()
194 f = TestPrefilterFrontEnd()
163 f.input_buffer = 'zzza = 1'
195 f.input_buffer = 'zzza = 1'
164 f._on_enter()
196 f._on_enter()
165 f.input_buffer = 'zzzb = 2'
197 f.input_buffer = 'zzzb = 2'
166 f._on_enter()
198 f._on_enter()
167 f.input_buffer = 'zz'
199 f.input_buffer = 'zz'
168 f.complete_current_input()
200 f.complete_current_input()
169 out_value = f.out.getvalue()
201 out_value = f.out.getvalue()
170 assert out_value == '\nzzza zzzb '
202 yield assert_equal, out_value, '\nzzza zzzb '
171 assert f.input_buffer == 'zzz'
203 yield assert_equal, f.input_buffer, 'zzz'
204
205
206 @isolate_ipython0
207 def test_completion_parenthesis():
208 """ Test command-line completion when a parenthesis is open.
209 """
210 f = TestPrefilterFrontEnd()
211 f.input_buffer = 'zzza = 1'
212 f._on_enter()
213 f.input_buffer = 'zzzb = 2'
214 f._on_enter()
215 f.input_buffer = 'map(zz'
216 f.complete_current_input()
217 out_value = f.out.getvalue()
218 yield assert_equal, out_value, '\nzzza zzzb '
219 yield assert_equal, f.input_buffer, 'map(zzz'
220
221
222 @isolate_ipython0
223 def test_completion_indexing():
224 """ Test command-line completion when indexing on objects.
225 """
226 f = TestPrefilterFrontEnd()
227 f.input_buffer = 'a = [0]'
228 f._on_enter()
229 f.input_buffer = 'a[0].'
230 f.complete_current_input()
231 assert_equal(f.input_buffer, 'a[0].__')
232
233
234 @isolate_ipython0
235 def test_completion_equal():
236 """ Test command-line completion when the delimiter is "=", not " ".
237 """
238 f = TestPrefilterFrontEnd()
239 f.input_buffer = 'a=1.'
240 f.complete_current_input()
241 assert_equal(f.input_buffer, 'a=1.__')
242
172
243
173
244
174 if __name__ == '__main__':
245 if __name__ == '__main__':
175 test_magic()
246 test_magic()
176 test_help()
247 test_help()
177 test_execution()
248 test_execution()
178 test_multiline()
249 test_multiline()
179 test_capture()
250 test_capture()
180 test_completion()
251 test_completion_simple()
252 test_completion_complex()
@@ -1,67 +1,67 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Test process execution and IO redirection.
3 Test process execution and IO redirection.
4 """
4 """
5
5
6 __docformat__ = "restructuredtext en"
6 __docformat__ = "restructuredtext en"
7
7
8 #-------------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2008 The IPython Development Team
9 # Copyright (C) 2008-2009 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is
11 # Distributed under the terms of the BSD License. The full license is
12 # in the file COPYING, distributed as part of this software.
12 # in the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 from cStringIO import StringIO
15 from cStringIO import StringIO
16 from time import sleep
16 from time import sleep
17 import sys
17 import sys
18
18
19 from IPython.frontend._process import PipedProcess
19 from IPython.frontend.process import PipedProcess
20 from IPython.testing import decorators as testdec
20 from IPython.testing import decorators as testdec
21
21
22
22
23 def test_capture_out():
23 def test_capture_out():
24 """ A simple test to see if we can execute a process and get the output.
24 """ A simple test to see if we can execute a process and get the output.
25 """
25 """
26 s = StringIO()
26 s = StringIO()
27 p = PipedProcess('echo 1', out_callback=s.write, )
27 p = PipedProcess('echo 1', out_callback=s.write, )
28 p.start()
28 p.start()
29 p.join()
29 p.join()
30 result = s.getvalue().rstrip()
30 result = s.getvalue().rstrip()
31 assert result == '1'
31 assert result == '1'
32
32
33
33
34 def test_io():
34 def test_io():
35 """ Checks that we can send characters on stdin to the process.
35 """ Checks that we can send characters on stdin to the process.
36 """
36 """
37 s = StringIO()
37 s = StringIO()
38 p = PipedProcess(sys.executable + ' -c "a = raw_input(); print a"',
38 p = PipedProcess(sys.executable + ' -c "a = raw_input(); print a"',
39 out_callback=s.write, )
39 out_callback=s.write, )
40 p.start()
40 p.start()
41 test_string = '12345\n'
41 test_string = '12345\n'
42 while not hasattr(p, 'process'):
42 while not hasattr(p, 'process'):
43 sleep(0.1)
43 sleep(0.1)
44 p.process.stdin.write(test_string)
44 p.process.stdin.write(test_string)
45 p.join()
45 p.join()
46 result = s.getvalue()
46 result = s.getvalue()
47 assert result == test_string
47 assert result == test_string
48
48
49
49
50 def test_kill():
50 def test_kill():
51 """ Check that we can kill a process, and its subprocess.
51 """ Check that we can kill a process, and its subprocess.
52 """
52 """
53 s = StringIO()
53 s = StringIO()
54 p = PipedProcess(sys.executable + ' -c "a = raw_input();"',
54 p = PipedProcess(sys.executable + ' -c "a = raw_input();"',
55 out_callback=s.write, )
55 out_callback=s.write, )
56 p.start()
56 p.start()
57 while not hasattr(p, 'process'):
57 while not hasattr(p, 'process'):
58 sleep(0.1)
58 sleep(0.1)
59 p.process.kill()
59 p.process.kill()
60 assert p.process.poll() is not None
60 assert p.process.poll() is not None
61
61
62
62
63 if __name__ == '__main__':
63 if __name__ == '__main__':
64 test_capture_out()
64 test_capture_out()
65 test_io()
65 test_io()
66 test_kill()
66 test_kill()
67
67
@@ -1,436 +1,625 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 A Wx widget to act as a console and input commands.
3 A Wx widget to act as a console and input commands.
4
4
5 This widget deals with prompts and provides an edit buffer
5 This widget deals with prompts and provides an edit buffer
6 restricted to after the last prompt.
6 restricted to after the last prompt.
7 """
7 """
8
8
9 __docformat__ = "restructuredtext en"
9 __docformat__ = "restructuredtext en"
10
10
11 #-------------------------------------------------------------------------------
11 #-------------------------------------------------------------------------------
12 # Copyright (C) 2008 The IPython Development Team
12 # Copyright (C) 2008 The IPython Development Team
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is
14 # Distributed under the terms of the BSD License. The full license is
15 # in the file COPYING, distributed as part of this software.
15 # in the file COPYING, distributed as part of this software.
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17
17
18 #-------------------------------------------------------------------------------
18 #-------------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-------------------------------------------------------------------------------
20 #-------------------------------------------------------------------------------
21
21
22 import wx
22 import wx
23 import wx.stc as stc
23 import wx.stc as stc
24
24
25 from wx.py import editwindow
25 from wx.py import editwindow
26 import time
26 import time
27 import sys
27 import sys
28 import string
29
28 LINESEP = '\n'
30 LINESEP = '\n'
29 if sys.platform == 'win32':
31 if sys.platform == 'win32':
30 LINESEP = '\n\r'
32 LINESEP = '\n\r'
31
33
32 import re
34 import re
33
35
34 # FIXME: Need to provide an API for non user-generated display on the
36 # FIXME: Need to provide an API for non user-generated display on the
35 # screen: this should not be editable by the user.
37 # screen: this should not be editable by the user.
38 #-------------------------------------------------------------------------------
39 # Constants
40 #-------------------------------------------------------------------------------
41 _COMPLETE_BUFFER_MARKER = 31
42 _ERROR_MARKER = 30
43 _INPUT_MARKER = 29
36
44
37 _DEFAULT_SIZE = 10
45 _DEFAULT_SIZE = 10
38 if sys.platform == 'darwin':
46 if sys.platform == 'darwin':
39 _DEFAULT_SIZE = 12
47 _DEFAULT_SIZE = 12
40
48
41 _DEFAULT_STYLE = {
49 _DEFAULT_STYLE = {
42 'stdout' : 'fore:#0000FF',
50 #background definition
43 'stderr' : 'fore:#007f00',
44 'trace' : 'fore:#FF0000',
45
46 'default' : 'size:%d' % _DEFAULT_SIZE,
51 'default' : 'size:%d' % _DEFAULT_SIZE,
47 'bracegood' : 'fore:#00AA00,back:#000000,bold',
52 'bracegood' : 'fore:#00AA00,back:#000000,bold',
48 'bracebad' : 'fore:#FF0000,back:#000000,bold',
53 'bracebad' : 'fore:#FF0000,back:#000000,bold',
49
54
55 # Edge column: a number of None
56 'edge_column' : -1,
57
50 # properties for the various Python lexer styles
58 # properties for the various Python lexer styles
51 'comment' : 'fore:#007F00',
59 'comment' : 'fore:#007F00',
52 'number' : 'fore:#007F7F',
60 'number' : 'fore:#007F7F',
53 'string' : 'fore:#7F007F,italic',
61 'string' : 'fore:#7F007F,italic',
54 'char' : 'fore:#7F007F,italic',
62 'char' : 'fore:#7F007F,italic',
55 'keyword' : 'fore:#00007F,bold',
63 'keyword' : 'fore:#00007F,bold',
56 'triple' : 'fore:#7F0000',
64 'triple' : 'fore:#7F0000',
57 'tripledouble' : 'fore:#7F0000',
65 'tripledouble' : 'fore:#7F0000',
58 'class' : 'fore:#0000FF,bold,underline',
66 'class' : 'fore:#0000FF,bold,underline',
59 'def' : 'fore:#007F7F,bold',
67 'def' : 'fore:#007F7F,bold',
60 'operator' : 'bold'
68 'operator' : 'bold',
69
70 # Default colors
71 'trace' : '#FAFAF1', # Nice green
72 'stdout' : '#FDFFD3', # Nice yellow
73 'stderr' : '#FFF1F1', # Nice red
74
75 # Default scintilla settings
76 'antialiasing' : True,
77 'carret_color' : 'BLACK',
78 'background_color' :'WHITE',
79
80 #prompt definition
81 'prompt_in1' : \
82 '\n\x01\x1b[0;34m\x02In [\x01\x1b[1;34m\x02$number\x01\x1b[0;34m\x02]: \x01\x1b[0m\x02',
83
84 'prompt_out': \
85 '\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02$number\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02',
61 }
86 }
62
87
63 # new style numbers
88 # new style numbers
64 _STDOUT_STYLE = 15
89 _STDOUT_STYLE = 15
65 _STDERR_STYLE = 16
90 _STDERR_STYLE = 16
66 _TRACE_STYLE = 17
91 _TRACE_STYLE = 17
67
92
68
93
69 # system colors
94 # system colors
70 #SYS_COLOUR_BACKGROUND = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND)
95 #SYS_COLOUR_BACKGROUND = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND)
71
96
97 # Translation table from ANSI escape sequences to color.
98 ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'],
99 '0;32': [2, 'GREEN'], '0;33': [3, 'BROWN'],
100 '0;34': [4, 'BLUE'], '0;35': [5, 'PURPLE'],
101 '0;36': [6, 'CYAN'], '0;37': [7, 'LIGHT GREY'],
102 '1;30': [8, 'DARK GREY'], '1;31': [9, 'RED'],
103 '1;32': [10, 'SEA GREEN'], '1;33': [11, 'YELLOW'],
104 '1;34': [12, 'LIGHT BLUE'], '1;35':
105 [13, 'MEDIUM VIOLET RED'],
106 '1;36': [14, 'LIGHT STEEL BLUE'], '1;37': [15, 'YELLOW']}
107
108 # XXX: Maybe one day we should factor this code with ColorANSI. Right now
109 # ColorANSI is hard to reuse and makes our code more complex.
110
111 #we define platform specific fonts
112 if wx.Platform == '__WXMSW__':
113 FACES = { 'times': 'Times New Roman',
114 'mono' : 'Courier New',
115 'helv' : 'Arial',
116 'other': 'Comic Sans MS',
117 'size' : 10,
118 'size2': 8,
119 }
120 elif wx.Platform == '__WXMAC__':
121 FACES = { 'times': 'Times New Roman',
122 'mono' : 'Monaco',
123 'helv' : 'Arial',
124 'other': 'Comic Sans MS',
125 'size' : 10,
126 'size2': 8,
127 }
128 else:
129 FACES = { 'times': 'Times',
130 'mono' : 'Courier',
131 'helv' : 'Helvetica',
132 'other': 'new century schoolbook',
133 'size' : 10,
134 'size2': 8,
135 }
136
137
72 #-------------------------------------------------------------------------------
138 #-------------------------------------------------------------------------------
73 # The console widget class
139 # The console widget class
74 #-------------------------------------------------------------------------------
140 #-------------------------------------------------------------------------------
75 class ConsoleWidget(editwindow.EditWindow):
141 class ConsoleWidget(editwindow.EditWindow):
76 """ Specialized styled text control view for console-like workflow.
142 """ Specialized styled text control view for console-like workflow.
77
143
78 This widget is mainly interested in dealing with the prompt and
144 This widget is mainly interested in dealing with the prompt and
79 keeping the cursor inside the editing line.
145 keeping the cursor inside the editing line.
80 """
146 """
81
147
82 # This is where the title captured from the ANSI escape sequences are
148 # This is where the title captured from the ANSI escape sequences are
83 # stored.
149 # stored.
84 title = 'Console'
150 title = 'Console'
85
151
152 # Last prompt printed
153 last_prompt = ''
154
86 # The buffer being edited.
155 # The buffer being edited.
87 def _set_input_buffer(self, string):
156 def _set_input_buffer(self, string):
88 self.SetSelection(self.current_prompt_pos, self.GetLength())
157 self.SetSelection(self.current_prompt_pos, self.GetLength())
89 self.ReplaceSelection(string)
158 self.ReplaceSelection(string)
90 self.GotoPos(self.GetLength())
159 self.GotoPos(self.GetLength())
91
160
92 def _get_input_buffer(self):
161 def _get_input_buffer(self):
93 """ Returns the text in current edit buffer.
162 """ Returns the text in current edit buffer.
94 """
163 """
95 input_buffer = self.GetTextRange(self.current_prompt_pos,
164 input_buffer = self.GetTextRange(self.current_prompt_pos,
96 self.GetLength())
165 self.GetLength())
97 input_buffer = input_buffer.replace(LINESEP, '\n')
166 input_buffer = input_buffer.replace(LINESEP, '\n')
98 return input_buffer
167 return input_buffer
99
168
100 input_buffer = property(_get_input_buffer, _set_input_buffer)
169 input_buffer = property(_get_input_buffer, _set_input_buffer)
101
170
102 style = _DEFAULT_STYLE.copy()
171 style = _DEFAULT_STYLE.copy()
103
172
104 # Translation table from ANSI escape sequences to color. Override
173 # Translation table from ANSI escape sequences to color. Override
105 # this to specify your colors.
174 # this to specify your colors.
106 ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'],
175 ANSI_STYLES = ANSI_STYLES.copy()
107 '0;32': [2, 'GREEN'], '0;33': [3, 'BROWN'],
108 '0;34': [4, 'BLUE'], '0;35': [5, 'PURPLE'],
109 '0;36': [6, 'CYAN'], '0;37': [7, 'LIGHT GREY'],
110 '1;30': [8, 'DARK GREY'], '1;31': [9, 'RED'],
111 '1;32': [10, 'SEA GREEN'], '1;33': [11, 'YELLOW'],
112 '1;34': [12, 'LIGHT BLUE'], '1;35':
113 [13, 'MEDIUM VIOLET RED'],
114 '1;36': [14, 'LIGHT STEEL BLUE'], '1;37': [15, 'YELLOW']}
115
116 # The color of the carret (call _apply_style() after setting)
117 carret_color = 'BLACK'
118
176
177 # Font faces
178 faces = FACES.copy()
179
119 # Store the last time a refresh was done
180 # Store the last time a refresh was done
120 _last_refresh_time = 0
181 _last_refresh_time = 0
121
182
122 #--------------------------------------------------------------------------
183 #--------------------------------------------------------------------------
123 # Public API
184 # Public API
124 #--------------------------------------------------------------------------
185 #--------------------------------------------------------------------------
125
186
126 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
187 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
127 size=wx.DefaultSize, style=wx.WANTS_CHARS, ):
188 size=wx.DefaultSize, style=wx.WANTS_CHARS, ):
128 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
189 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
129 self._configure_scintilla()
190 self.configure_scintilla()
191 # Track if 'enter' key as ever been processed
192 # This variable will only be reallowed until key goes up
193 self.enter_catched = False
194 self.current_prompt_pos = 0
130
195
131 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
196 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
132 self.Bind(wx.EVT_KEY_UP, self._on_key_up)
197 self.Bind(wx.EVT_KEY_UP, self._on_key_up)
133
198
134
199
135 def write(self, text, refresh=True):
200 def write(self, text, refresh=True):
136 """ Write given text to buffer, while translating the ansi escape
201 """ Write given text to buffer, while translating the ansi escape
137 sequences.
202 sequences.
138 """
203 """
139 # XXX: do not put print statements to sys.stdout/sys.stderr in
204 # XXX: do not put print statements to sys.stdout/sys.stderr in
140 # this method, the print statements will call this method, as
205 # this method, the print statements will call this method, as
141 # you will end up with an infinit loop
206 # you will end up with an infinit loop
142 title = self.title_pat.split(text)
207 title = self.title_pat.split(text)
143 if len(title)>1:
208 if len(title)>1:
144 self.title = title[-2]
209 self.title = title[-2]
145
210
146 text = self.title_pat.sub('', text)
211 text = self.title_pat.sub('', text)
147 segments = self.color_pat.split(text)
212 segments = self.color_pat.split(text)
148 segment = segments.pop(0)
213 segment = segments.pop(0)
149 self.GotoPos(self.GetLength())
214 self.GotoPos(self.GetLength())
150 self.StartStyling(self.GetLength(), 0xFF)
215 self.StartStyling(self.GetLength(), 0xFF)
151 try:
216 try:
152 self.AppendText(segment)
217 self.AppendText(segment)
153 except UnicodeDecodeError:
218 except UnicodeDecodeError:
154 # XXX: Do I really want to skip the exception?
219 # XXX: Do I really want to skip the exception?
155 pass
220 pass
156
221
157 if segments:
222 if segments:
158 for ansi_tag, text in zip(segments[::2], segments[1::2]):
223 for ansi_tag, text in zip(segments[::2], segments[1::2]):
159 self.StartStyling(self.GetLength(), 0xFF)
224 self.StartStyling(self.GetLength(), 0xFF)
160 try:
225 try:
161 self.AppendText(text)
226 self.AppendText(text)
162 except UnicodeDecodeError:
227 except UnicodeDecodeError:
163 # XXX: Do I really want to skip the exception?
228 # XXX: Do I really want to skip the exception?
164 pass
229 pass
165
230
166 if ansi_tag not in self.ANSI_STYLES:
231 if ansi_tag not in self.ANSI_STYLES:
167 style = 0
232 style = 0
168 else:
233 else:
169 style = self.ANSI_STYLES[ansi_tag][0]
234 style = self.ANSI_STYLES[ansi_tag][0]
170
235
171 self.SetStyling(len(text), style)
236 self.SetStyling(len(text), style)
172
237
173 self.GotoPos(self.GetLength())
238 self.GotoPos(self.GetLength())
174 if refresh:
239 if refresh:
175 current_time = time.time()
240 current_time = time.time()
176 if current_time - self._last_refresh_time > 0.03:
241 if current_time - self._last_refresh_time > 0.03:
177 if sys.platform == 'win32':
242 if sys.platform == 'win32':
178 wx.SafeYield()
243 wx.SafeYield()
179 else:
244 else:
180 wx.Yield()
245 wx.Yield()
181 # self.ProcessEvent(wx.PaintEvent())
246 # self.ProcessEvent(wx.PaintEvent())
182 self._last_refresh_time = current_time
247 self._last_refresh_time = current_time
183
248
184
249
185 def new_prompt(self, prompt):
250 def new_prompt(self, prompt):
186 """ Prints a prompt at start of line, and move the start of the
251 """ Prints a prompt at start of line, and move the start of the
187 current block there.
252 current block there.
188
253
189 The prompt can be given with ascii escape sequences.
254 The prompt can be given with ascii escape sequences.
190 """
255 """
191 self.write(prompt, refresh=False)
256 self.write(prompt, refresh=False)
192 # now we update our cursor giving end of prompt
257 # now we update our cursor giving end of prompt
193 self.current_prompt_pos = self.GetLength()
258 self.current_prompt_pos = self.GetLength()
194 self.current_prompt_line = self.GetCurrentLine()
259 self.current_prompt_line = self.GetCurrentLine()
195 self.EnsureCaretVisible()
260 self.EnsureCaretVisible()
261 self.last_prompt = prompt
196
262
197
263
264 def continuation_prompt(self):
265 """ Returns the current continuation prompt.
266 We need to implement this method here to deal with the
267 ascii escape sequences cleaning up.
268 """
269 # ASCII-less prompt
270 ascii_less = ''.join(self.color_pat.split(self.last_prompt)[2::2])
271 return "."*(len(ascii_less)-2) + ': '
272
273
198 def scroll_to_bottom(self):
274 def scroll_to_bottom(self):
199 maxrange = self.GetScrollRange(wx.VERTICAL)
275 maxrange = self.GetScrollRange(wx.VERTICAL)
200 self.ScrollLines(maxrange)
276 self.ScrollLines(maxrange)
201
277
202
278
203 def pop_completion(self, possibilities, offset=0):
279 def pop_completion(self, possibilities, offset=0):
204 """ Pops up an autocompletion menu. Offset is the offset
280 """ Pops up an autocompletion menu. Offset is the offset
205 in characters of the position at which the menu should
281 in characters of the position at which the menu should
206 appear, relativ to the cursor.
282 appear, relativ to the cursor.
207 """
283 """
208 self.AutoCompSetIgnoreCase(False)
284 self.AutoCompSetIgnoreCase(False)
209 self.AutoCompSetAutoHide(False)
285 self.AutoCompSetAutoHide(False)
210 self.AutoCompSetMaxHeight(len(possibilities))
286 self.AutoCompSetMaxHeight(len(possibilities))
211 self.AutoCompShow(offset, " ".join(possibilities))
287 self.AutoCompShow(offset, " ".join(possibilities))
212
288
213
289
214 def get_line_width(self):
290 def get_line_width(self):
215 """ Return the width of the line in characters.
291 """ Return the width of the line in characters.
216 """
292 """
217 return self.GetSize()[0]/self.GetCharWidth()
293 return self.GetSize()[0]/self.GetCharWidth()
218
294
219 #--------------------------------------------------------------------------
220 # EditWindow API
221 #--------------------------------------------------------------------------
222
295
223 def OnUpdateUI(self, event):
296 def configure_scintilla(self):
224 """ Override the OnUpdateUI of the EditWindow class, to prevent
297 """ Set up all the styling option of the embedded scintilla
225 syntax highlighting both for faster redraw, and for more
298 widget.
226 consistent look and feel.
227 """
299 """
300 p = self.style.copy()
301
302 # Marker for complete buffer.
303 self.MarkerDefine(_COMPLETE_BUFFER_MARKER, stc.STC_MARK_BACKGROUND,
304 background=p['trace'])
228
305
229 #--------------------------------------------------------------------------
306 # Marker for current input buffer.
230 # Private API
307 self.MarkerDefine(_INPUT_MARKER, stc.STC_MARK_BACKGROUND,
231 #--------------------------------------------------------------------------
308 background=p['stdout'])
232
309 # Marker for tracebacks.
233 def _apply_style(self):
310 self.MarkerDefine(_ERROR_MARKER, stc.STC_MARK_BACKGROUND,
234 """ Applies the colors for the different text elements and the
311 background=p['stderr'])
235 carret.
236 """
237 self.SetCaretForeground(self.carret_color)
238
239 #self.StyleClearAll()
240 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,
241 "fore:#FF0000,back:#0000FF,bold")
242 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,
243 "fore:#000000,back:#FF0000,bold")
244
245 for style in self.ANSI_STYLES.values():
246 self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
247
312
248
249 def _configure_scintilla(self):
250 self.SetEOLMode(stc.STC_EOL_LF)
313 self.SetEOLMode(stc.STC_EOL_LF)
251
314
252 # Ctrl"+" or Ctrl "-" can be used to zoomin/zoomout the text inside
315 # Ctrl"+" or Ctrl "-" can be used to zoomin/zoomout the text inside
253 # the widget
316 # the widget
254 self.CmdKeyAssign(ord('+'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
317 self.CmdKeyAssign(ord('+'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
255 self.CmdKeyAssign(ord('-'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
318 self.CmdKeyAssign(ord('-'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
256 # Also allow Ctrl Shift "=" for poor non US keyboard users.
319 # Also allow Ctrl Shift "=" for poor non US keyboard users.
257 self.CmdKeyAssign(ord('='), stc.STC_SCMOD_CTRL|stc.STC_SCMOD_SHIFT,
320 self.CmdKeyAssign(ord('='), stc.STC_SCMOD_CTRL|stc.STC_SCMOD_SHIFT,
258 stc.STC_CMD_ZOOMIN)
321 stc.STC_CMD_ZOOMIN)
259
322
260 # Keys: we need to clear some of the keys the that don't play
323 # Keys: we need to clear some of the keys the that don't play
261 # well with a console.
324 # well with a console.
262 self.CmdKeyClear(ord('D'), stc.STC_SCMOD_CTRL)
325 self.CmdKeyClear(ord('D'), stc.STC_SCMOD_CTRL)
263 self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL)
326 self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL)
264 self.CmdKeyClear(ord('T'), stc.STC_SCMOD_CTRL)
327 self.CmdKeyClear(ord('T'), stc.STC_SCMOD_CTRL)
265 self.CmdKeyClear(ord('A'), stc.STC_SCMOD_CTRL)
328 self.CmdKeyClear(ord('A'), stc.STC_SCMOD_CTRL)
266
329
267 self.SetEOLMode(stc.STC_EOL_CRLF)
330 self.SetEOLMode(stc.STC_EOL_CRLF)
268 self.SetWrapMode(stc.STC_WRAP_CHAR)
331 self.SetWrapMode(stc.STC_WRAP_CHAR)
269 self.SetWrapMode(stc.STC_WRAP_WORD)
332 self.SetWrapMode(stc.STC_WRAP_WORD)
270 self.SetBufferedDraw(True)
333 self.SetBufferedDraw(True)
271 self.SetUseAntiAliasing(True)
334
335 self.SetUseAntiAliasing(p['antialiasing'])
336
272 self.SetLayoutCache(stc.STC_CACHE_PAGE)
337 self.SetLayoutCache(stc.STC_CACHE_PAGE)
273 self.SetUndoCollection(False)
338 self.SetUndoCollection(False)
274 self.SetUseTabs(True)
339 self.SetUseTabs(True)
275 self.SetIndent(4)
340 self.SetIndent(4)
276 self.SetTabWidth(4)
341 self.SetTabWidth(4)
277
342
278 # we don't want scintilla's autocompletion to choose
343 # we don't want scintilla's autocompletion to choose
279 # automaticaly out of a single choice list, as we pop it up
344 # automaticaly out of a single choice list, as we pop it up
280 # automaticaly
345 # automaticaly
281 self.AutoCompSetChooseSingle(False)
346 self.AutoCompSetChooseSingle(False)
282 self.AutoCompSetMaxHeight(10)
347 self.AutoCompSetMaxHeight(10)
283 # XXX: this doesn't seem to have an effect.
348 # XXX: this doesn't seem to have an effect.
284 self.AutoCompSetFillUps('\n')
349 self.AutoCompSetFillUps('\n')
285
350
286 self.SetMargins(3, 3) #text is moved away from border with 3px
351 self.SetMargins(3, 3) #text is moved away from border with 3px
287 # Suppressing Scintilla margins
352 # Suppressing Scintilla margins
288 self.SetMarginWidth(0, 0)
353 self.SetMarginWidth(0, 0)
289 self.SetMarginWidth(1, 0)
354 self.SetMarginWidth(1, 0)
290 self.SetMarginWidth(2, 0)
355 self.SetMarginWidth(2, 0)
291
356
292 self._apply_style()
293
294 # Xterm escape sequences
357 # Xterm escape sequences
295 self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
358 self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
296 self.title_pat = re.compile('\x1b]0;(.*?)\x07')
359 self.title_pat = re.compile('\x1b]0;(.*?)\x07')
297
360
298 #self.SetEdgeMode(stc.STC_EDGE_LINE)
299 #self.SetEdgeColumn(80)
300
301 # styles
361 # styles
302 p = self.style
362
303 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default'])
363 self.SetCaretForeground(p['carret_color'])
364
365 background_color = p['background_color']
366
367 if 'default' in p:
368 if 'back' not in p['default']:
369 p['default'] += ',back:%s' % background_color
370 if 'size' not in p['default']:
371 p['default'] += ',size:%s' % self.faces['size']
372 if 'face' not in p['default']:
373 p['default'] += ',face:%s' % self.faces['mono']
374
375 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default'])
376 else:
377 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
378 "fore:%s,back:%s,size:%d,face:%s"
379 % (self.ANSI_STYLES['0;30'][1],
380 background_color,
381 self.faces['size'], self.faces['mono']))
382
304 self.StyleClearAll()
383 self.StyleClearAll()
384
385 # XXX: two lines below are usefull if not using the lexer
386 #for style in self.ANSI_STYLES.values():
387 # self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
388
389 # prompt definition
390 self.prompt_in1 = p['prompt_in1']
391 self.prompt_out = p['prompt_out']
392
393 self.output_prompt_template = string.Template(self.prompt_out)
394 self.input_prompt_template = string.Template(self.prompt_in1)
395
305 self.StyleSetSpec(_STDOUT_STYLE, p['stdout'])
396 self.StyleSetSpec(_STDOUT_STYLE, p['stdout'])
306 self.StyleSetSpec(_STDERR_STYLE, p['stderr'])
397 self.StyleSetSpec(_STDERR_STYLE, p['stderr'])
307 self.StyleSetSpec(_TRACE_STYLE, p['trace'])
398 self.StyleSetSpec(_TRACE_STYLE, p['trace'])
308
309 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, p['bracegood'])
399 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, p['bracegood'])
310 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, p['bracebad'])
400 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, p['bracebad'])
311 self.StyleSetSpec(stc.STC_P_COMMENTLINE, p['comment'])
401 self.StyleSetSpec(stc.STC_P_COMMENTLINE, p['comment'])
312 self.StyleSetSpec(stc.STC_P_NUMBER, p['number'])
402 self.StyleSetSpec(stc.STC_P_NUMBER, p['number'])
313 self.StyleSetSpec(stc.STC_P_STRING, p['string'])
403 self.StyleSetSpec(stc.STC_P_STRING, p['string'])
314 self.StyleSetSpec(stc.STC_P_CHARACTER, p['char'])
404 self.StyleSetSpec(stc.STC_P_CHARACTER, p['char'])
315 self.StyleSetSpec(stc.STC_P_WORD, p['keyword'])
405 self.StyleSetSpec(stc.STC_P_WORD, p['keyword'])
316 self.StyleSetSpec(stc.STC_P_WORD2, p['keyword'])
406 self.StyleSetSpec(stc.STC_P_WORD2, p['keyword'])
317 self.StyleSetSpec(stc.STC_P_TRIPLE, p['triple'])
407 self.StyleSetSpec(stc.STC_P_TRIPLE, p['triple'])
318 self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, p['tripledouble'])
408 self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, p['tripledouble'])
319 self.StyleSetSpec(stc.STC_P_CLASSNAME, p['class'])
409 self.StyleSetSpec(stc.STC_P_CLASSNAME, p['class'])
320 self.StyleSetSpec(stc.STC_P_DEFNAME, p['def'])
410 self.StyleSetSpec(stc.STC_P_DEFNAME, p['def'])
321 self.StyleSetSpec(stc.STC_P_OPERATOR, p['operator'])
411 self.StyleSetSpec(stc.STC_P_OPERATOR, p['operator'])
322 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment'])
412 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment'])
323
413
414 edge_column = p['edge_column']
415 if edge_column is not None and edge_column > 0:
416 #we add a vertical line to console widget
417 self.SetEdgeMode(stc.STC_EDGE_LINE)
418 self.SetEdgeColumn(edge_column)
419
420
421 #--------------------------------------------------------------------------
422 # EditWindow API
423 #--------------------------------------------------------------------------
424
425 def OnUpdateUI(self, event):
426 """ Override the OnUpdateUI of the EditWindow class, to prevent
427 syntax highlighting both for faster redraw, and for more
428 consistent look and feel.
429 """
430
431
432 #--------------------------------------------------------------------------
433 # Private API
434 #--------------------------------------------------------------------------
435
324 def _on_key_down(self, event, skip=True):
436 def _on_key_down(self, event, skip=True):
325 """ Key press callback used for correcting behavior for
437 """ Key press callback used for correcting behavior for
326 console-like interfaces: the cursor is constraint to be after
438 console-like interfaces: the cursor is constraint to be after
327 the last prompt.
439 the last prompt.
328
440
329 Return True if event as been catched.
441 Return True if event as been catched.
330 """
442 """
331 catched = True
443 catched = True
444 # XXX: Would the right way to do this be to have a
445 # dictionary at the instance level associating keys with
446 # callbacks? How would we deal with inheritance? And Do the
447 # different callbacks share local variables?
448
332 # Intercept some specific keys.
449 # Intercept some specific keys.
333 if event.KeyCode == ord('L') and event.ControlDown() :
450 if event.KeyCode == ord('L') and event.ControlDown() :
334 self.scroll_to_bottom()
451 self.scroll_to_bottom()
335 elif event.KeyCode == ord('K') and event.ControlDown() :
452 elif event.KeyCode == ord('K') and event.ControlDown() :
336 self.input_buffer = ''
453 self.input_buffer = ''
337 elif event.KeyCode == ord('A') and event.ControlDown() :
454 elif event.KeyCode == ord('A') and event.ControlDown() :
338 self.GotoPos(self.GetLength())
455 self.GotoPos(self.GetLength())
339 self.SetSelectionStart(self.current_prompt_pos)
456 self.SetSelectionStart(self.current_prompt_pos)
340 self.SetSelectionEnd(self.GetCurrentPos())
457 self.SetSelectionEnd(self.GetCurrentPos())
341 catched = True
458 catched = True
342 elif event.KeyCode == ord('E') and event.ControlDown() :
459 elif event.KeyCode == ord('E') and event.ControlDown() :
343 self.GotoPos(self.GetLength())
460 self.GotoPos(self.GetLength())
344 catched = True
461 catched = True
345 elif event.KeyCode == wx.WXK_PAGEUP:
462 elif event.KeyCode == wx.WXK_PAGEUP:
346 self.ScrollPages(-1)
463 self.ScrollPages(-1)
347 elif event.KeyCode == wx.WXK_PAGEDOWN:
464 elif event.KeyCode == wx.WXK_PAGEDOWN:
348 self.ScrollPages(1)
465 self.ScrollPages(1)
466 elif event.KeyCode == wx.WXK_HOME:
467 self.GotoPos(self.GetLength())
468 elif event.KeyCode == wx.WXK_END:
469 self.GotoPos(self.GetLength())
349 elif event.KeyCode == wx.WXK_UP and event.ShiftDown():
470 elif event.KeyCode == wx.WXK_UP and event.ShiftDown():
350 self.ScrollLines(-1)
471 self.ScrollLines(-1)
351 elif event.KeyCode == wx.WXK_DOWN and event.ShiftDown():
472 elif event.KeyCode == wx.WXK_DOWN and event.ShiftDown():
352 self.ScrollLines(1)
473 self.ScrollLines(1)
353 else:
474 else:
354 catched = False
475 catched = False
355
476
356 if self.AutoCompActive():
477 if self.AutoCompActive():
357 event.Skip()
478 event.Skip()
358 else:
479 else:
359 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
480 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
360 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
481 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN,
482 wx.MOD_SHIFT):
361 catched = True
483 catched = True
362 self.CallTipCancel()
484 if not self.enter_catched:
363 self.write('\n', refresh=False)
485 self.CallTipCancel()
364 # Under windows scintilla seems to be doing funny stuff to the
486 if event.Modifiers == wx.MOD_SHIFT:
365 # line returns here, but the getter for input_buffer filters
487 # Try to force execution
366 # this out.
488 self.GotoPos(self.GetLength())
367 if sys.platform == 'win32':
489 self.write('\n' + self.continuation_prompt(),
368 self.input_buffer = self.input_buffer
490 refresh=False)
369 self._on_enter()
491 self._on_enter()
492 else:
493 self._on_enter()
494 self.enter_catched = True
370
495
371 elif event.KeyCode == wx.WXK_HOME:
496 elif event.KeyCode == wx.WXK_HOME:
372 if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
497 if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
373 self.GotoPos(self.current_prompt_pos)
498 self.GotoPos(self.current_prompt_pos)
374 catched = True
499 catched = True
375
500
376 elif event.Modifiers == wx.MOD_SHIFT:
501 elif event.Modifiers == wx.MOD_SHIFT:
377 # FIXME: This behavior is not ideal: if the selection
502 # FIXME: This behavior is not ideal: if the selection
378 # is already started, it will jump.
503 # is already started, it will jump.
379 self.SetSelectionStart(self.current_prompt_pos)
504 self.SetSelectionStart(self.current_prompt_pos)
380 self.SetSelectionEnd(self.GetCurrentPos())
505 self.SetSelectionEnd(self.GetCurrentPos())
381 catched = True
506 catched = True
382
507
383 elif event.KeyCode == wx.WXK_UP:
508 elif event.KeyCode == wx.WXK_UP:
384 if self.GetCurrentLine() > self.current_prompt_line:
509 if self.GetCurrentLine() > self.current_prompt_line:
385 if self.GetCurrentLine() == self.current_prompt_line + 1 \
510 if self.GetCurrentLine() == self.current_prompt_line + 1 \
386 and self.GetColumn(self.GetCurrentPos()) < \
511 and self.GetColumn(self.GetCurrentPos()) < \
387 self.GetColumn(self.current_prompt_pos):
512 self.GetColumn(self.current_prompt_pos):
388 self.GotoPos(self.current_prompt_pos)
513 self.GotoPos(self.current_prompt_pos)
389 else:
514 else:
390 event.Skip()
515 event.Skip()
391 catched = True
516 catched = True
392
517
393 elif event.KeyCode in (wx.WXK_LEFT, wx.WXK_BACK):
518 elif event.KeyCode in (wx.WXK_LEFT, wx.WXK_BACK):
394 if self.GetCurrentPos() > self.current_prompt_pos:
519 if not self._keep_cursor_in_buffer(self.GetCurrentPos() - 1):
520 event.Skip()
521 catched = True
522
523 elif event.KeyCode == wx.WXK_RIGHT:
524 if not self._keep_cursor_in_buffer(self.GetCurrentPos() + 1):
525 event.Skip()
526 catched = True
527
528
529 elif event.KeyCode == wx.WXK_DELETE:
530 if not self._keep_cursor_in_buffer(self.GetCurrentPos() - 1):
395 event.Skip()
531 event.Skip()
396 catched = True
532 catched = True
397
533
398 if skip and not catched:
534 if skip and not catched:
399 # Put the cursor back in the edit region
535 # Put the cursor back in the edit region
400 if self.GetCurrentPos() < self.current_prompt_pos:
536 if not self._keep_cursor_in_buffer():
401 self.GotoPos(self.current_prompt_pos)
537 if not (self.GetCurrentPos() == self.GetLength()
402 else:
538 and event.KeyCode == wx.WXK_DELETE):
403 event.Skip()
539 event.Skip()
540 catched = True
404
541
405 return catched
542 return catched
406
543
407
544
408 def _on_key_up(self, event, skip=True):
545 def _on_key_up(self, event, skip=True):
409 """ If cursor is outside the editing region, put it back.
546 """ If cursor is outside the editing region, put it back.
410 """
547 """
411 event.Skip()
548 if skip:
412 if self.GetCurrentPos() < self.current_prompt_pos:
549 event.Skip()
413 self.GotoPos(self.current_prompt_pos)
550 self._keep_cursor_in_buffer()
551
552
553 # XXX: I need to avoid the problem of having an empty glass;
554 def _keep_cursor_in_buffer(self, pos=None):
555 """ Checks if the cursor is where it is allowed to be. If not,
556 put it back.
414
557
558 Returns
559 -------
560 cursor_moved: Boolean
561 whether or not the cursor was moved by this routine.
562
563 Notes
564 ------
565 WARNING: This does proper checks only for horizontal
566 movements.
567 """
568 if pos is None:
569 current_pos = self.GetCurrentPos()
570 else:
571 current_pos = pos
572 if current_pos < self.current_prompt_pos:
573 self.GotoPos(self.current_prompt_pos)
574 return True
575 line_num = self.LineFromPosition(current_pos)
576 if not current_pos > self.GetLength():
577 line_pos = self.GetColumn(current_pos)
578 else:
579 line_pos = self.GetColumn(self.GetLength())
580 line = self.GetLine(line_num)
581 # Jump the continuation prompt
582 continuation_prompt = self.continuation_prompt()
583 if ( line.startswith(continuation_prompt)
584 and line_pos < len(continuation_prompt)):
585 if line_pos < 2:
586 # We are at the beginning of the line, trying to move
587 # forward: jump forward.
588 self.GotoPos(current_pos + 1 +
589 len(continuation_prompt) - line_pos)
590 else:
591 # Jump back up
592 self.GotoPos(self.GetLineEndPosition(line_num-1))
593 return True
594 elif ( current_pos > self.GetLineEndPosition(line_num)
595 and not current_pos == self.GetLength()):
596 # Jump to next line
597 self.GotoPos(current_pos + 1 +
598 len(continuation_prompt))
599 return True
600
601 # We re-allow enter event processing
602 self.enter_catched = False
603 return False
415
604
416
605
417 if __name__ == '__main__':
606 if __name__ == '__main__':
418 # Some simple code to test the console widget.
607 # Some simple code to test the console widget.
419 class MainWindow(wx.Frame):
608 class MainWindow(wx.Frame):
420 def __init__(self, parent, id, title):
609 def __init__(self, parent, id, title):
421 wx.Frame.__init__(self, parent, id, title, size=(300,250))
610 wx.Frame.__init__(self, parent, id, title, size=(300, 250))
422 self._sizer = wx.BoxSizer(wx.VERTICAL)
611 self._sizer = wx.BoxSizer(wx.VERTICAL)
423 self.console_widget = ConsoleWidget(self)
612 self.console_widget = ConsoleWidget(self)
424 self._sizer.Add(self.console_widget, 1, wx.EXPAND)
613 self._sizer.Add(self.console_widget, 1, wx.EXPAND)
425 self.SetSizer(self._sizer)
614 self.SetSizer(self._sizer)
426 self.SetAutoLayout(1)
615 self.SetAutoLayout(1)
427 self.Show(True)
616 self.Show(True)
428
617
429 app = wx.PySimpleApp()
618 app = wx.PySimpleApp()
430 w = MainWindow(None, wx.ID_ANY, 'ConsoleWidget')
619 w = MainWindow(None, wx.ID_ANY, 'ConsoleWidget')
431 w.SetSize((780, 460))
620 w.SetSize((780, 460))
432 w.Show()
621 w.Show()
433
622
434 app.MainLoop()
623 app.MainLoop()
435
624
436
625
@@ -1,110 +1,119 b''
1 """
1 """
2 Entry point for a simple application giving a graphical frontend to
2 Entry point for a simple application giving a graphical frontend to
3 ipython.
3 ipython.
4 """
4 """
5
5
6 try:
6 try:
7 import wx
7 import wx
8 except ImportError, e:
8 except ImportError, e:
9 e.message = """%s
9 e.message = """%s
10 ________________________________________________________________________________
10 ________________________________________________________________________________
11 You need wxPython to run this application.
11 You need wxPython to run this application.
12 """ % e.message
12 """ % e.message
13 e.args = (e.message, ) + e.args[1:]
13 e.args = (e.message, ) + e.args[1:]
14 raise e
14 raise e
15
15
16 from wx_frontend import WxController
16 from wx_frontend import WxController
17 import __builtin__
17 import __builtin__
18
18
19
19
20 class IPythonXController(WxController):
20 class IPythonXController(WxController):
21 """ Sub class of WxController that adds some application-specific
21 """ Sub class of WxController that adds some application-specific
22 bindings.
22 bindings.
23 """
23 """
24
24
25 debug = False
25 debug = False
26
26
27 def __init__(self, *args, **kwargs):
27 def __init__(self, *args, **kwargs):
28 WxController.__init__(self, *args, **kwargs)
28 WxController.__init__(self, *args, **kwargs)
29 self.ipython0.ask_exit = self.do_exit
29 self.ipython0.ask_exit = self.do_exit
30 # Scroll to top
30 # Scroll to top
31 maxrange = self.GetScrollRange(wx.VERTICAL)
31 maxrange = self.GetScrollRange(wx.VERTICAL)
32 self.ScrollLines(-maxrange)
32 self.ScrollLines(-maxrange)
33
33
34
34
35 def _on_key_down(self, event, skip=True):
35 def _on_key_down(self, event, skip=True):
36 # Intercept Ctrl-D to quit
36 # Intercept Ctrl-D to quit
37 if event.KeyCode == ord('D') and event.ControlDown() and \
37 if event.KeyCode == ord('D') and event.ControlDown() and \
38 self.input_buffer == '' and \
38 self.input_buffer == '' and \
39 self._input_state == 'readline':
39 self._input_state == 'readline':
40 wx.CallAfter(self.ask_exit)
40 wx.CallAfter(self.ask_exit)
41 else:
41 else:
42 WxController._on_key_down(self, event, skip=skip)
42 WxController._on_key_down(self, event, skip=skip)
43
43
44
44
45 def ask_exit(self):
45 def ask_exit(self):
46 """ Ask the user whether to exit.
46 """ Ask the user whether to exit.
47 """
47 """
48 self._input_state = 'subprocess'
48 self._input_state = 'subprocess'
49 self.write('\n', refresh=False)
49 self.write('\n', refresh=False)
50 self.capture_output()
50 self.capture_output()
51 self.ipython0.shell.exit()
51 self.ipython0.shell.exit()
52 self.release_output()
52 self.release_output()
53 if not self.ipython0.exit_now:
53 if not self.ipython0.exit_now:
54 wx.CallAfter(self.new_prompt,
54 wx.CallAfter(self.new_prompt,
55 self.input_prompt_template.substitute(
55 self.input_prompt_template.substitute(
56 number=self.last_result['number'] + 1))
56 number=self.last_result['number'] + 1))
57 else:
57 else:
58 wx.CallAfter(wx.GetApp().Exit)
58 wx.CallAfter(wx.GetApp().Exit)
59 self.write('Exiting ...', refresh=False)
59 self.write('Exiting ...', refresh=False)
60
60
61
61
62 def do_exit(self):
62 def do_exit(self):
63 """ Exits the interpreter, kills the windows.
63 """ Exits the interpreter, kills the windows.
64 """
64 """
65 WxController.do_exit(self)
65 WxController.do_exit(self)
66 self.release_output()
66 self.release_output()
67 wx.CallAfter(wx.Exit)
67 wx.CallAfter(wx.Exit)
68
68
69
69
70
70
71 class IPythonX(wx.Frame):
71 class IPythonX(wx.Frame):
72 """ Main frame of the IPythonX app.
72 """ Main frame of the IPythonX app.
73 """
73 """
74
74
75 def __init__(self, parent, id, title, debug=False):
75 def __init__(self, parent, id, title, debug=False):
76 wx.Frame.__init__(self, parent, id, title, size=(300,250))
76 wx.Frame.__init__(self, parent, id, title, size=(300,250))
77 self._sizer = wx.BoxSizer(wx.VERTICAL)
77 self._sizer = wx.BoxSizer(wx.VERTICAL)
78 self.shell = IPythonXController(self, debug=debug)
78 self.shell = IPythonXController(self, debug=debug)
79 self._sizer.Add(self.shell, 1, wx.EXPAND)
79 self._sizer.Add(self.shell, 1, wx.EXPAND)
80 self.SetSizer(self._sizer)
80 self.SetSizer(self._sizer)
81 self.SetAutoLayout(1)
81 self.SetAutoLayout(1)
82 self.Show(True)
82 self.Show(True)
83 wx.EVT_CLOSE(self, self.on_close)
84
85
86 def on_close(self, event):
87 """ Called on closing the windows.
88
89 Stops the event loop, to close all the child windows.
90 """
91 wx.CallAfter(wx.Exit)
83
92
84
93
85 def main():
94 def main():
86 from optparse import OptionParser
95 from optparse import OptionParser
87 usage = """usage: %prog [options]
96 usage = """usage: %prog [options]
88
97
89 Simple graphical frontend to IPython, using WxWidgets."""
98 Simple graphical frontend to IPython, using WxWidgets."""
90 parser = OptionParser(usage=usage)
99 parser = OptionParser(usage=usage)
91 parser.add_option("-d", "--debug",
100 parser.add_option("-d", "--debug",
92 action="store_true", dest="debug", default=False,
101 action="store_true", dest="debug", default=False,
93 help="Enable debug message for the wx frontend.")
102 help="Enable debug message for the wx frontend.")
94
103
95 options, args = parser.parse_args()
104 options, args = parser.parse_args()
96
105
97 # Clear the options, to avoid having the ipython0 instance complain
106 # Clear the options, to avoid having the ipython0 instance complain
98 import sys
107 import sys
99 sys.argv = sys.argv[:1]
108 sys.argv = sys.argv[:1]
100
109
101 app = wx.PySimpleApp()
110 app = wx.PySimpleApp()
102 frame = IPythonX(None, wx.ID_ANY, 'IPythonX', debug=options.debug)
111 frame = IPythonX(None, wx.ID_ANY, 'IPythonX', debug=options.debug)
103 frame.shell.SetFocus()
112 frame.shell.SetFocus()
104 frame.shell.app = app
113 frame.shell.app = app
105 frame.SetSize((680, 460))
114 frame.SetSize((680, 460))
106
115
107 app.MainLoop()
116 app.MainLoop()
108
117
109 if __name__ == '__main__':
118 if __name__ == '__main__':
110 main()
119 main()
@@ -1,526 +1,601 b''
1 # encoding: utf-8 -*- test-case-name:
1 # encoding: utf-8 -*- test-case-name:
2 # FIXME: Need to add tests.
2 # FIXME: Need to add tests.
3 # ipython1.frontend.wx.tests.test_wx_frontend -*-
3 # ipython1.frontend.wx.tests.test_wx_frontend -*-
4
4
5 """Classes to provide a Wx frontend to the
5 """Classes to provide a Wx frontend to the
6 IPython.kernel.core.interpreter.
6 IPython.kernel.core.interpreter.
7
7
8 This class inherits from ConsoleWidget, that provides a console-like
8 This class inherits from ConsoleWidget, that provides a console-like
9 widget to provide a text-rendering widget suitable for a terminal.
9 widget to provide a text-rendering widget suitable for a terminal.
10 """
10 """
11
11
12 __docformat__ = "restructuredtext en"
12 __docformat__ = "restructuredtext en"
13
13
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15 # Copyright (C) 2008 The IPython Development Team
15 # Copyright (C) 2008 The IPython Development Team
16 #
16 #
17 # Distributed under the terms of the BSD License. The full license is in
17 # Distributed under the terms of the BSD License. The full license is in
18 # the file COPYING, distributed as part of this software.
18 # the file COPYING, distributed as part of this software.
19 #-------------------------------------------------------------------------------
19 #-------------------------------------------------------------------------------
20
20
21 #-------------------------------------------------------------------------------
21 #-------------------------------------------------------------------------------
22 # Imports
22 # Imports
23 #-------------------------------------------------------------------------------
23 #-------------------------------------------------------------------------------
24
24
25 # Major library imports
25 # Major library imports
26 import re
26 import re
27 import __builtin__
27 import __builtin__
28 from time import sleep
29 import sys
28 import sys
30 from threading import Lock
29 from threading import Lock
31 import string
32
30
33 import wx
31 import wx
34 from wx import stc
32 from wx import stc
35
33
36 # Ipython-specific imports.
34 # Ipython-specific imports.
37 from IPython.frontend._process import PipedProcess
35 from IPython.frontend.process import PipedProcess
38 from console_widget import ConsoleWidget
36 from console_widget import ConsoleWidget, _COMPLETE_BUFFER_MARKER, \
37 _ERROR_MARKER, _INPUT_MARKER
39 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
38 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
40
39
41 #-------------------------------------------------------------------------------
40 #-------------------------------------------------------------------------------
42 # Constants
43 #-------------------------------------------------------------------------------
44
45 _COMPLETE_BUFFER_BG = '#FAFAF1' # Nice green
46 _INPUT_BUFFER_BG = '#FDFFD3' # Nice yellow
47 _ERROR_BG = '#FFF1F1' # Nice red
48
49 _COMPLETE_BUFFER_MARKER = 31
50 _ERROR_MARKER = 30
51 _INPUT_MARKER = 29
52
53 prompt_in1 = \
54 '\n\x01\x1b[0;34m\x02In [\x01\x1b[1;34m\x02$number\x01\x1b[0;34m\x02]: \x01\x1b[0m\x02'
55
56 prompt_out = \
57 '\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02$number\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02'
58
59 #-------------------------------------------------------------------------------
60 # Classes to implement the Wx frontend
41 # Classes to implement the Wx frontend
61 #-------------------------------------------------------------------------------
42 #-------------------------------------------------------------------------------
62 class WxController(ConsoleWidget, PrefilterFrontEnd):
43 class WxController(ConsoleWidget, PrefilterFrontEnd):
63 """Classes to provide a Wx frontend to the
44 """Classes to provide a Wx frontend to the
64 IPython.kernel.core.interpreter.
45 IPython.kernel.core.interpreter.
65
46
66 This class inherits from ConsoleWidget, that provides a console-like
47 This class inherits from ConsoleWidget, that provides a console-like
67 widget to provide a text-rendering widget suitable for a terminal.
48 widget to provide a text-rendering widget suitable for a terminal.
68 """
49 """
69
50
70 output_prompt_template = string.Template(prompt_out)
71
72 input_prompt_template = string.Template(prompt_in1)
73
74 # Print debug info on what is happening to the console.
51 # Print debug info on what is happening to the console.
75 debug = False
52 debug = False
76
53
77 # The title of the terminal, as captured through the ANSI escape
54 # The title of the terminal, as captured through the ANSI escape
78 # sequences.
55 # sequences.
79 def _set_title(self, title):
56 def _set_title(self, title):
80 return self.Parent.SetTitle(title)
57 return self.Parent.SetTitle(title)
81
58
82 def _get_title(self):
59 def _get_title(self):
83 return self.Parent.GetTitle()
60 return self.Parent.GetTitle()
84
61
85 title = property(_get_title, _set_title)
62 title = property(_get_title, _set_title)
86
63
87
64
88 # The buffer being edited.
65 # The buffer being edited.
89 # We are duplicating the definition here because of multiple
66 # We are duplicating the definition here because of multiple
90 # inheritence
67 # inheritence
91 def _set_input_buffer(self, string):
68 def _set_input_buffer(self, string):
92 ConsoleWidget._set_input_buffer(self, string)
69 ConsoleWidget._set_input_buffer(self, string)
93 self._colorize_input_buffer()
70 self._colorize_input_buffer()
94
71
95 def _get_input_buffer(self):
72 def _get_input_buffer(self):
96 """ Returns the text in current edit buffer.
73 """ Returns the text in current edit buffer.
97 """
74 """
98 return ConsoleWidget._get_input_buffer(self)
75 return ConsoleWidget._get_input_buffer(self)
99
76
100 input_buffer = property(_get_input_buffer, _set_input_buffer)
77 input_buffer = property(_get_input_buffer, _set_input_buffer)
101
78
102
79
103 #--------------------------------------------------------------------------
80 #--------------------------------------------------------------------------
104 # Private Attributes
81 # Private Attributes
105 #--------------------------------------------------------------------------
82 #--------------------------------------------------------------------------
106
83
107 # A flag governing the behavior of the input. Can be:
84 # A flag governing the behavior of the input. Can be:
108 #
85 #
109 # 'readline' for readline-like behavior with a prompt
86 # 'readline' for readline-like behavior with a prompt
110 # and an edit buffer.
87 # and an edit buffer.
111 # 'raw_input' similar to readline, but triggered by a raw-input
88 # 'raw_input' similar to readline, but triggered by a raw-input
112 # call. Can be used by subclasses to act differently.
89 # call. Can be used by subclasses to act differently.
113 # 'subprocess' for sending the raw input directly to a
90 # 'subprocess' for sending the raw input directly to a
114 # subprocess.
91 # subprocess.
115 # 'buffering' for buffering of the input, that will be used
92 # 'buffering' for buffering of the input, that will be used
116 # when the input state switches back to another state.
93 # when the input state switches back to another state.
117 _input_state = 'readline'
94 _input_state = 'readline'
118
95
119 # Attribute to store reference to the pipes of a subprocess, if we
96 # Attribute to store reference to the pipes of a subprocess, if we
120 # are running any.
97 # are running any.
121 _running_process = False
98 _running_process = False
122
99
123 # A queue for writing fast streams to the screen without flooding the
100 # A queue for writing fast streams to the screen without flooding the
124 # event loop
101 # event loop
125 _out_buffer = []
102 _out_buffer = []
126
103
127 # A lock to lock the _out_buffer to make sure we don't empty it
104 # A lock to lock the _out_buffer to make sure we don't empty it
128 # while it is being swapped
105 # while it is being swapped
129 _out_buffer_lock = Lock()
106 _out_buffer_lock = Lock()
130
107
131 # The different line markers used to higlight the prompts.
108 # The different line markers used to higlight the prompts.
132 _markers = dict()
109 _markers = dict()
133
110
134 #--------------------------------------------------------------------------
111 #--------------------------------------------------------------------------
135 # Public API
112 # Public API
136 #--------------------------------------------------------------------------
113 #--------------------------------------------------------------------------
137
114
138 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
115 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
139 size=wx.DefaultSize,
116 size=wx.DefaultSize,
140 style=wx.CLIP_CHILDREN|wx.WANTS_CHARS,
117 style=wx.CLIP_CHILDREN|wx.WANTS_CHARS,
118 styledef=None,
141 *args, **kwds):
119 *args, **kwds):
142 """ Create Shell instance.
120 """ Create Shell instance.
121
122 Parameters
123 -----------
124 styledef : dict, optional
125 styledef is the dictionary of options used to define the
126 style.
143 """
127 """
128 if styledef is not None:
129 self.style = styledef
144 ConsoleWidget.__init__(self, parent, id, pos, size, style)
130 ConsoleWidget.__init__(self, parent, id, pos, size, style)
145 PrefilterFrontEnd.__init__(self, **kwds)
131 PrefilterFrontEnd.__init__(self, **kwds)
146
132
147 # Stick in our own raw_input:
133 # Stick in our own raw_input:
148 self.ipython0.raw_input = self.raw_input
134 self.ipython0.raw_input = self.raw_input
149
135
150 # Marker for complete buffer.
151 self.MarkerDefine(_COMPLETE_BUFFER_MARKER, stc.STC_MARK_BACKGROUND,
152 background=_COMPLETE_BUFFER_BG)
153 # Marker for current input buffer.
154 self.MarkerDefine(_INPUT_MARKER, stc.STC_MARK_BACKGROUND,
155 background=_INPUT_BUFFER_BG)
156 # Marker for tracebacks.
157 self.MarkerDefine(_ERROR_MARKER, stc.STC_MARK_BACKGROUND,
158 background=_ERROR_BG)
159
160 # A time for flushing the write buffer
136 # A time for flushing the write buffer
161 BUFFER_FLUSH_TIMER_ID = 100
137 BUFFER_FLUSH_TIMER_ID = 100
162 self._buffer_flush_timer = wx.Timer(self, BUFFER_FLUSH_TIMER_ID)
138 self._buffer_flush_timer = wx.Timer(self, BUFFER_FLUSH_TIMER_ID)
163 wx.EVT_TIMER(self, BUFFER_FLUSH_TIMER_ID, self._buffer_flush)
139 wx.EVT_TIMER(self, BUFFER_FLUSH_TIMER_ID, self._buffer_flush)
164
140
165 if 'debug' in kwds:
141 if 'debug' in kwds:
166 self.debug = kwds['debug']
142 self.debug = kwds['debug']
167 kwds.pop('debug')
143 kwds.pop('debug')
168
144
169 # Inject self in namespace, for debug
145 # Inject self in namespace, for debug
170 if self.debug:
146 if self.debug:
171 self.shell.user_ns['self'] = self
147 self.shell.user_ns['self'] = self
172 # Inject our own raw_input in namespace
148 # Inject our own raw_input in namespace
173 self.shell.user_ns['raw_input'] = self.raw_input
149 self.shell.user_ns['raw_input'] = self.raw_input
174
150
175
176 def raw_input(self, prompt=''):
151 def raw_input(self, prompt=''):
177 """ A replacement from python's raw_input.
152 """ A replacement from python's raw_input.
178 """
153 """
179 self.new_prompt(prompt)
154 self.new_prompt(prompt)
180 self._input_state = 'raw_input'
155 self._input_state = 'raw_input'
181 if hasattr(self, '_cursor'):
156 if hasattr(self, '_cursor'):
182 del self._cursor
157 del self._cursor
183 self.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))
158 self.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))
184 self.__old_on_enter = self._on_enter
159 self.__old_on_enter = self._on_enter
185 event_loop = wx.EventLoop()
160 event_loop = wx.EventLoop()
186 def my_on_enter():
161 def my_on_enter():
187 event_loop.Exit()
162 event_loop.Exit()
188 self._on_enter = my_on_enter
163 self._on_enter = my_on_enter
189 # XXX: Running a separate event_loop. Ugly.
164 # XXX: Running a separate event_loop. Ugly.
190 event_loop.Run()
165 event_loop.Run()
191 self._on_enter = self.__old_on_enter
166 self._on_enter = self.__old_on_enter
192 self._input_state = 'buffering'
167 self._input_state = 'buffering'
193 self._cursor = wx.BusyCursor()
168 self._cursor = wx.BusyCursor()
194 return self.input_buffer.rstrip('\n')
169 return self.input_buffer.rstrip('\n')
195
170
196
171
197 def system_call(self, command_string):
172 def system_call(self, command_string):
198 self._input_state = 'subprocess'
173 self._input_state = 'subprocess'
199 event_loop = wx.EventLoop()
174 event_loop = wx.EventLoop()
200 def _end_system_call():
175 def _end_system_call():
201 self._input_state = 'buffering'
176 self._input_state = 'buffering'
202 self._running_process = False
177 self._running_process = False
203 event_loop.Exit()
178 event_loop.Exit()
204
179
205 self._running_process = PipedProcess(command_string,
180 self._running_process = PipedProcess(command_string,
206 out_callback=self.buffered_write,
181 out_callback=self.buffered_write,
207 end_callback = _end_system_call)
182 end_callback = _end_system_call)
208 self._running_process.start()
183 self._running_process.start()
209 # XXX: Running a separate event_loop. Ugly.
184 # XXX: Running a separate event_loop. Ugly.
210 event_loop.Run()
185 event_loop.Run()
211 # Be sure to flush the buffer.
186 # Be sure to flush the buffer.
212 self._buffer_flush(event=None)
187 self._buffer_flush(event=None)
213
188
214
189
215 def do_calltip(self):
190 def do_calltip(self):
216 """ Analyse current and displays useful calltip for it.
191 """ Analyse current and displays useful calltip for it.
217 """
192 """
218 if self.debug:
193 if self.debug:
219 print >>sys.__stdout__, "do_calltip"
194 print >>sys.__stdout__, "do_calltip"
220 separators = re.compile('[\s\{\}\[\]\(\)\= ,:]')
195 separators = re.compile('[\s\{\}\[\]\(\)\= ,:]')
221 symbol = self.input_buffer
196 symbol = self.input_buffer
222 symbol_string = separators.split(symbol)[-1]
197 symbol_string = separators.split(symbol)[-1]
223 base_symbol_string = symbol_string.split('.')[0]
198 base_symbol_string = symbol_string.split('.')[0]
224 if base_symbol_string in self.shell.user_ns:
199 if base_symbol_string in self.shell.user_ns:
225 symbol = self.shell.user_ns[base_symbol_string]
200 symbol = self.shell.user_ns[base_symbol_string]
226 elif base_symbol_string in self.shell.user_global_ns:
201 elif base_symbol_string in self.shell.user_global_ns:
227 symbol = self.shell.user_global_ns[base_symbol_string]
202 symbol = self.shell.user_global_ns[base_symbol_string]
228 elif base_symbol_string in __builtin__.__dict__:
203 elif base_symbol_string in __builtin__.__dict__:
229 symbol = __builtin__.__dict__[base_symbol_string]
204 symbol = __builtin__.__dict__[base_symbol_string]
230 else:
205 else:
231 return False
206 return False
232 try:
207 try:
233 for name in symbol_string.split('.')[1:] + ['__doc__']:
208 for name in symbol_string.split('.')[1:] + ['__doc__']:
234 symbol = getattr(symbol, name)
209 symbol = getattr(symbol, name)
235 self.AutoCompCancel()
210 self.AutoCompCancel()
236 # Check that the symbol can indeed be converted to a string:
211 # Check that the symbol can indeed be converted to a string:
237 symbol += ''
212 symbol += ''
238 wx.CallAfter(self.CallTipShow, self.GetCurrentPos(), symbol)
213 wx.CallAfter(self.CallTipShow, self.GetCurrentPos(), symbol)
239 except:
214 except:
240 # The retrieve symbol couldn't be converted to a string
215 # The retrieve symbol couldn't be converted to a string
241 pass
216 pass
242
217
243
218
244 def _popup_completion(self, create=False):
219 def _popup_completion(self, create=False):
245 """ Updates the popup completion menu if it exists. If create is
220 """ Updates the popup completion menu if it exists. If create is
246 true, open the menu.
221 true, open the menu.
247 """
222 """
248 if self.debug:
223 if self.debug:
249 print >>sys.__stdout__, "_popup_completion"
224 print >>sys.__stdout__, "_popup_completion"
250 line = self.input_buffer
225 line = self.input_buffer
251 if (self.AutoCompActive() and line and not line[-1] == '.') \
226 if (self.AutoCompActive() and line and not line[-1] == '.') \
252 or create==True:
227 or create==True:
253 suggestion, completions = self.complete(line)
228 suggestion, completions = self.complete(line)
254 offset=0
255 if completions:
229 if completions:
256 complete_sep = re.compile('[\s\{\}\[\]\(\)\= ,:]')
230 offset = len(self._get_completion_text(line))
257 residual = complete_sep.split(line)[-1]
258 offset = len(residual)
259 self.pop_completion(completions, offset=offset)
231 self.pop_completion(completions, offset=offset)
260 if self.debug:
232 if self.debug:
261 print >>sys.__stdout__, completions
233 print >>sys.__stdout__, completions
262
234
263
235
264 def buffered_write(self, text):
236 def buffered_write(self, text):
265 """ A write method for streams, that caches the stream in order
237 """ A write method for streams, that caches the stream in order
266 to avoid flooding the event loop.
238 to avoid flooding the event loop.
267
239
268 This can be called outside of the main loop, in separate
240 This can be called outside of the main loop, in separate
269 threads.
241 threads.
270 """
242 """
271 self._out_buffer_lock.acquire()
243 self._out_buffer_lock.acquire()
272 self._out_buffer.append(text)
244 self._out_buffer.append(text)
273 self._out_buffer_lock.release()
245 self._out_buffer_lock.release()
274 if not self._buffer_flush_timer.IsRunning():
246 if not self._buffer_flush_timer.IsRunning():
275 wx.CallAfter(self._buffer_flush_timer.Start,
247 wx.CallAfter(self._buffer_flush_timer.Start,
276 milliseconds=100, oneShot=True)
248 milliseconds=100, oneShot=True)
277
249
278
250
251 def clear_screen(self):
252 """ Empty completely the widget.
253 """
254 self.ClearAll()
255 self.new_prompt(self.input_prompt_template.substitute(
256 number=(self.last_result['number'] + 1)))
257
258
279 #--------------------------------------------------------------------------
259 #--------------------------------------------------------------------------
280 # LineFrontEnd interface
260 # LineFrontEnd interface
281 #--------------------------------------------------------------------------
261 #--------------------------------------------------------------------------
282
262
283 def execute(self, python_string, raw_string=None):
263 def execute(self, python_string, raw_string=None):
284 self._input_state = 'buffering'
264 self._input_state = 'buffering'
285 self.CallTipCancel()
265 self.CallTipCancel()
286 self._cursor = wx.BusyCursor()
266 self._cursor = wx.BusyCursor()
287 if raw_string is None:
267 if raw_string is None:
288 raw_string = python_string
268 raw_string = python_string
289 end_line = self.current_prompt_line \
269 end_line = self.current_prompt_line \
290 + max(1, len(raw_string.split('\n'))-1)
270 + max(1, len(raw_string.split('\n'))-1)
291 for i in range(self.current_prompt_line, end_line):
271 for i in range(self.current_prompt_line, end_line):
292 if i in self._markers:
272 if i in self._markers:
293 self.MarkerDeleteHandle(self._markers[i])
273 self.MarkerDeleteHandle(self._markers[i])
294 self._markers[i] = self.MarkerAdd(i, _COMPLETE_BUFFER_MARKER)
274 self._markers[i] = self.MarkerAdd(i, _COMPLETE_BUFFER_MARKER)
295 # Use a callafter to update the display robustly under windows
275 # Use a callafter to update the display robustly under windows
296 def callback():
276 def callback():
297 self.GotoPos(self.GetLength())
277 self.GotoPos(self.GetLength())
298 PrefilterFrontEnd.execute(self, python_string,
278 PrefilterFrontEnd.execute(self, python_string,
299 raw_string=raw_string)
279 raw_string=raw_string)
300 wx.CallAfter(callback)
280 wx.CallAfter(callback)
301
281
282
283 def execute_command(self, command, hidden=False):
284 """ Execute a command, not only in the model, but also in the
285 view.
286 """
287 # XXX: This method needs to be integrated in the base fronted
288 # interface
289 if hidden:
290 return self.shell.execute(command)
291 else:
292 # XXX: we are not storing the input buffer previous to the
293 # execution, as this forces us to run the execution
294 # input_buffer a yield, which is not good.
295 ##current_buffer = self.shell.control.input_buffer
296 command = command.rstrip()
297 if len(command.split('\n')) > 1:
298 # The input command is several lines long, we need to
299 # force the execution to happen
300 command += '\n'
301 cleaned_command = self.prefilter_input(command)
302 self.input_buffer = command
303 # Do not use wx.Yield() (aka GUI.process_events()) to avoid
304 # recursive yields.
305 self.ProcessEvent(wx.PaintEvent())
306 self.write('\n')
307 if not self.is_complete(cleaned_command + '\n'):
308 self._colorize_input_buffer()
309 self.render_error('Incomplete or invalid input')
310 self.new_prompt(self.input_prompt_template.substitute(
311 number=(self.last_result['number'] + 1)))
312 return False
313 self._on_enter()
314 return True
315
316
302 def save_output_hooks(self):
317 def save_output_hooks(self):
303 self.__old_raw_input = __builtin__.raw_input
318 self.__old_raw_input = __builtin__.raw_input
304 PrefilterFrontEnd.save_output_hooks(self)
319 PrefilterFrontEnd.save_output_hooks(self)
305
320
306 def capture_output(self):
321 def capture_output(self):
307 self.SetLexer(stc.STC_LEX_NULL)
322 self.SetLexer(stc.STC_LEX_NULL)
308 PrefilterFrontEnd.capture_output(self)
323 PrefilterFrontEnd.capture_output(self)
309 __builtin__.raw_input = self.raw_input
324 __builtin__.raw_input = self.raw_input
310
325
311
326
312 def release_output(self):
327 def release_output(self):
313 __builtin__.raw_input = self.__old_raw_input
328 __builtin__.raw_input = self.__old_raw_input
314 PrefilterFrontEnd.release_output(self)
329 PrefilterFrontEnd.release_output(self)
315 self.SetLexer(stc.STC_LEX_PYTHON)
330 self.SetLexer(stc.STC_LEX_PYTHON)
316
331
317
332
318 def after_execute(self):
333 def after_execute(self):
319 PrefilterFrontEnd.after_execute(self)
334 PrefilterFrontEnd.after_execute(self)
320 # Clear the wait cursor
335 # Clear the wait cursor
321 if hasattr(self, '_cursor'):
336 if hasattr(self, '_cursor'):
322 del self._cursor
337 del self._cursor
323 self.SetCursor(wx.StockCursor(wx.CURSOR_CHAR))
338 self.SetCursor(wx.StockCursor(wx.CURSOR_CHAR))
324
339
325
340
326 def show_traceback(self):
341 def show_traceback(self):
327 start_line = self.GetCurrentLine()
342 start_line = self.GetCurrentLine()
328 PrefilterFrontEnd.show_traceback(self)
343 PrefilterFrontEnd.show_traceback(self)
329 self.ProcessEvent(wx.PaintEvent())
344 self.ProcessEvent(wx.PaintEvent())
330 #wx.Yield()
345 #wx.Yield()
331 for i in range(start_line, self.GetCurrentLine()):
346 for i in range(start_line, self.GetCurrentLine()):
332 self._markers[i] = self.MarkerAdd(i, _ERROR_MARKER)
347 self._markers[i] = self.MarkerAdd(i, _ERROR_MARKER)
333
348
334
349
335 #--------------------------------------------------------------------------
350 #--------------------------------------------------------------------------
336 # FrontEndBase interface
351 # FrontEndBase interface
337 #--------------------------------------------------------------------------
352 #--------------------------------------------------------------------------
338
353
339 def render_error(self, e):
354 def render_error(self, e):
340 start_line = self.GetCurrentLine()
355 start_line = self.GetCurrentLine()
341 self.write('\n' + e + '\n')
356 self.write('\n' + e + '\n')
342 for i in range(start_line, self.GetCurrentLine()):
357 for i in range(start_line, self.GetCurrentLine()):
343 self._markers[i] = self.MarkerAdd(i, _ERROR_MARKER)
358 self._markers[i] = self.MarkerAdd(i, _ERROR_MARKER)
344
359
345
360
346 #--------------------------------------------------------------------------
361 #--------------------------------------------------------------------------
347 # ConsoleWidget interface
362 # ConsoleWidget interface
348 #--------------------------------------------------------------------------
363 #--------------------------------------------------------------------------
349
364
350 def new_prompt(self, prompt):
365 def new_prompt(self, prompt):
351 """ Display a new prompt, and start a new input buffer.
366 """ Display a new prompt, and start a new input buffer.
352 """
367 """
353 self._input_state = 'readline'
368 self._input_state = 'readline'
354 ConsoleWidget.new_prompt(self, prompt)
369 ConsoleWidget.new_prompt(self, prompt)
355 i = self.current_prompt_line
370 i = self.current_prompt_line
356 self._markers[i] = self.MarkerAdd(i, _INPUT_MARKER)
371 self._markers[i] = self.MarkerAdd(i, _INPUT_MARKER)
357
372
358
373
374 def continuation_prompt(self, *args, **kwargs):
375 # Avoid multiple inheritence, be explicit about which
376 # parent method class gets called
377 return ConsoleWidget.continuation_prompt(self, *args, **kwargs)
378
379
359 def write(self, *args, **kwargs):
380 def write(self, *args, **kwargs):
360 # Avoid multiple inheritence, be explicit about which
381 # Avoid multiple inheritence, be explicit about which
361 # parent method class gets called
382 # parent method class gets called
362 ConsoleWidget.write(self, *args, **kwargs)
383 return ConsoleWidget.write(self, *args, **kwargs)
363
384
364
385
365 def _on_key_down(self, event, skip=True):
386 def _on_key_down(self, event, skip=True):
366 """ Capture the character events, let the parent
387 """ Capture the character events, let the parent
367 widget handle them, and put our logic afterward.
388 widget handle them, and put our logic afterward.
368 """
389 """
369 # FIXME: This method needs to be broken down in smaller ones.
390 # FIXME: This method needs to be broken down in smaller ones.
370 current_line_number = self.GetCurrentLine()
391 current_line_num = self.GetCurrentLine()
371 if event.KeyCode in (ord('c'), ord('C')) and event.ControlDown():
392 if event.KeyCode in (ord('c'), ord('C')) and event.ControlDown():
372 # Capture Control-C
393 # Capture Control-C
373 if self._input_state == 'subprocess':
394 if self._input_state == 'subprocess':
374 if self.debug:
395 if self.debug:
375 print >>sys.__stderr__, 'Killing running process'
396 print >>sys.__stderr__, 'Killing running process'
376 if hasattr(self._running_process, 'process'):
397 if hasattr(self._running_process, 'process'):
377 self._running_process.process.kill()
398 self._running_process.process.kill()
378 elif self._input_state == 'buffering':
399 elif self._input_state == 'buffering':
379 if self.debug:
400 if self.debug:
380 print >>sys.__stderr__, 'Raising KeyboardInterrupt'
401 print >>sys.__stderr__, 'Raising KeyboardInterrupt'
381 raise KeyboardInterrupt
402 raise KeyboardInterrupt
382 # XXX: We need to make really sure we
403 # XXX: We need to make really sure we
383 # get back to a prompt.
404 # get back to a prompt.
384 elif self._input_state == 'subprocess' and (
405 elif self._input_state == 'subprocess' and (
385 ( event.KeyCode<256 and
406 ( event.KeyCode<256 and
386 not event.ControlDown() )
407 not event.ControlDown() )
387 or
408 or
388 ( event.KeyCode in (ord('d'), ord('D')) and
409 ( event.KeyCode in (ord('d'), ord('D')) and
389 event.ControlDown())):
410 event.ControlDown())):
390 # We are running a process, we redirect keys.
411 # We are running a process, we redirect keys.
391 ConsoleWidget._on_key_down(self, event, skip=skip)
412 ConsoleWidget._on_key_down(self, event, skip=skip)
392 char = chr(event.KeyCode)
413 char = chr(event.KeyCode)
393 # Deal with some inconsistency in wx keycodes:
414 # Deal with some inconsistency in wx keycodes:
394 if char == '\r':
415 if char == '\r':
395 char = '\n'
416 char = '\n'
396 elif not event.ShiftDown():
417 elif not event.ShiftDown():
397 char = char.lower()
418 char = char.lower()
398 if event.ControlDown() and event.KeyCode in (ord('d'), ord('D')):
419 if event.ControlDown() and event.KeyCode in (ord('d'), ord('D')):
399 char = '\04'
420 char = '\04'
400 self._running_process.process.stdin.write(char)
421 self._running_process.process.stdin.write(char)
401 self._running_process.process.stdin.flush()
422 self._running_process.process.stdin.flush()
402 elif event.KeyCode in (ord('('), 57, 53):
423 elif event.KeyCode in (ord('('), 57, 53):
403 # Calltips
424 # Calltips
404 event.Skip()
425 event.Skip()
405 self.do_calltip()
426 self.do_calltip()
406 elif self.AutoCompActive() and not event.KeyCode == ord('\t'):
427 elif self.AutoCompActive() and not event.KeyCode == ord('\t'):
407 event.Skip()
428 event.Skip()
408 if event.KeyCode in (wx.WXK_BACK, wx.WXK_DELETE):
429 if event.KeyCode in (wx.WXK_BACK, wx.WXK_DELETE):
409 wx.CallAfter(self._popup_completion, create=True)
430 wx.CallAfter(self._popup_completion, create=True)
410 elif not event.KeyCode in (wx.WXK_UP, wx.WXK_DOWN, wx.WXK_LEFT,
431 elif not event.KeyCode in (wx.WXK_UP, wx.WXK_DOWN, wx.WXK_LEFT,
411 wx.WXK_RIGHT, wx.WXK_ESCAPE):
432 wx.WXK_RIGHT, wx.WXK_ESCAPE):
412 wx.CallAfter(self._popup_completion)
433 wx.CallAfter(self._popup_completion)
413 else:
434 else:
414 # Up history
435 # Up history
415 if event.KeyCode == wx.WXK_UP and (
436 if event.KeyCode == wx.WXK_UP and (
416 ( current_line_number == self.current_prompt_line and
437 ( current_line_num == self.current_prompt_line and
417 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
438 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
418 or event.ControlDown() ):
439 or event.ControlDown() ):
419 new_buffer = self.get_history_previous(
440 new_buffer = self.get_history_previous(
420 self.input_buffer)
441 self.input_buffer)
421 if new_buffer is not None:
442 if new_buffer is not None:
422 self.input_buffer = new_buffer
443 self.input_buffer = new_buffer
423 if self.GetCurrentLine() > self.current_prompt_line:
444 if self.GetCurrentLine() > self.current_prompt_line:
424 # Go to first line, for seemless history up.
445 # Go to first line, for seemless history up.
425 self.GotoPos(self.current_prompt_pos)
446 self.GotoPos(self.current_prompt_pos)
426 # Down history
447 # Down history
427 elif event.KeyCode == wx.WXK_DOWN and (
448 elif event.KeyCode == wx.WXK_DOWN and (
428 ( current_line_number == self.LineCount -1 and
449 ( current_line_num == self.LineCount -1 and
429 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
450 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
430 or event.ControlDown() ):
451 or event.ControlDown() ):
431 new_buffer = self.get_history_next()
452 new_buffer = self.get_history_next()
432 if new_buffer is not None:
453 if new_buffer is not None:
433 self.input_buffer = new_buffer
454 self.input_buffer = new_buffer
434 # Tab-completion
455 # Tab-completion
435 elif event.KeyCode == ord('\t'):
456 elif event.KeyCode == ord('\t'):
436 current_line, current_line_number = self.CurLine
457 current_line, current_line_num = self.CurLine
437 if not re.match(r'^\s*$', current_line):
458 if not re.match(r'^\s*$', current_line):
438 self.complete_current_input()
459 self.complete_current_input()
439 if self.AutoCompActive():
460 if self.AutoCompActive():
440 wx.CallAfter(self._popup_completion, create=True)
461 wx.CallAfter(self._popup_completion, create=True)
441 else:
462 else:
442 event.Skip()
463 event.Skip()
464 elif event.KeyCode == wx.WXK_BACK:
465 # If characters where erased, check if we have to
466 # remove a line.
467 # XXX: What about DEL?
468 # FIXME: This logics should be in ConsoleWidget, as it is
469 # independant of IPython
470 current_line, _ = self.CurLine
471 current_pos = self.GetCurrentPos()
472 current_line_num = self.LineFromPosition(current_pos)
473 current_col = self.GetColumn(current_pos)
474 len_prompt = len(self.continuation_prompt())
475 if ( current_line.startswith(self.continuation_prompt())
476 and current_col == len_prompt):
477 new_lines = []
478 for line_num, line in enumerate(
479 self.input_buffer.split('\n')):
480 if (line_num + self.current_prompt_line ==
481 current_line_num):
482 new_lines.append(line[len_prompt:])
483 else:
484 new_lines.append('\n'+line)
485 # The first character is '\n', due to the above
486 # code:
487 self.input_buffer = ''.join(new_lines)[1:]
488 self.GotoPos(current_pos - 1 - len_prompt)
489 else:
490 ConsoleWidget._on_key_down(self, event, skip=skip)
443 else:
491 else:
444 ConsoleWidget._on_key_down(self, event, skip=skip)
492 ConsoleWidget._on_key_down(self, event, skip=skip)
493
445
494
446
495
447 def _on_key_up(self, event, skip=True):
496 def _on_key_up(self, event, skip=True):
448 """ Called when any key is released.
497 """ Called when any key is released.
449 """
498 """
450 if event.KeyCode in (59, ord('.')):
499 if event.KeyCode in (59, ord('.')):
451 # Intercepting '.'
500 # Intercepting '.'
452 event.Skip()
501 event.Skip()
453 wx.CallAfter(self._popup_completion, create=True)
502 wx.CallAfter(self._popup_completion, create=True)
454 else:
503 else:
455 ConsoleWidget._on_key_up(self, event, skip=skip)
504 ConsoleWidget._on_key_up(self, event, skip=skip)
505 # Make sure the continuation_prompts are always followed by a
506 # whitespace
507 new_lines = []
508 if self._input_state == 'readline':
509 position = self.GetCurrentPos()
510 continuation_prompt = self.continuation_prompt()[:-1]
511 for line in self.input_buffer.split('\n'):
512 if not line == continuation_prompt:
513 new_lines.append(line)
514 self.input_buffer = '\n'.join(new_lines)
515 self.GotoPos(position)
456
516
457
517
458 def _on_enter(self):
518 def _on_enter(self):
459 """ Called on return key down, in readline input_state.
519 """ Called on return key down, in readline input_state.
460 """
520 """
521 last_line_num = self.LineFromPosition(self.GetLength())
522 current_line_num = self.LineFromPosition(self.GetCurrentPos())
523 new_line_pos = (last_line_num - current_line_num)
461 if self.debug:
524 if self.debug:
462 print >>sys.__stdout__, repr(self.input_buffer)
525 print >>sys.__stdout__, repr(self.input_buffer)
463 PrefilterFrontEnd._on_enter(self)
526 self.write('\n', refresh=False)
527 # Under windows scintilla seems to be doing funny
528 # stuff to the line returns here, but the getter for
529 # input_buffer filters this out.
530 if sys.platform == 'win32':
531 self.input_buffer = self.input_buffer
532 old_prompt_num = self.current_prompt_pos
533 has_executed = PrefilterFrontEnd._on_enter(self,
534 new_line_pos=new_line_pos)
535 if old_prompt_num == self.current_prompt_pos:
536 # No execution has happened
537 self.GotoPos(self.GetLineEndPosition(current_line_num + 1))
538 return has_executed
464
539
465
540
466 #--------------------------------------------------------------------------
541 #--------------------------------------------------------------------------
467 # EditWindow API
542 # EditWindow API
468 #--------------------------------------------------------------------------
543 #--------------------------------------------------------------------------
469
544
470 def OnUpdateUI(self, event):
545 def OnUpdateUI(self, event):
471 """ Override the OnUpdateUI of the EditWindow class, to prevent
546 """ Override the OnUpdateUI of the EditWindow class, to prevent
472 syntax highlighting both for faster redraw, and for more
547 syntax highlighting both for faster redraw, and for more
473 consistent look and feel.
548 consistent look and feel.
474 """
549 """
475 if not self._input_state == 'readline':
550 if not self._input_state == 'readline':
476 ConsoleWidget.OnUpdateUI(self, event)
551 ConsoleWidget.OnUpdateUI(self, event)
477
552
478 #--------------------------------------------------------------------------
553 #--------------------------------------------------------------------------
479 # Private API
554 # Private API
480 #--------------------------------------------------------------------------
555 #--------------------------------------------------------------------------
481
556
482 def _buffer_flush(self, event):
557 def _buffer_flush(self, event):
483 """ Called by the timer to flush the write buffer.
558 """ Called by the timer to flush the write buffer.
484
559
485 This is always called in the mainloop, by the wx timer.
560 This is always called in the mainloop, by the wx timer.
486 """
561 """
487 self._out_buffer_lock.acquire()
562 self._out_buffer_lock.acquire()
488 _out_buffer = self._out_buffer
563 _out_buffer = self._out_buffer
489 self._out_buffer = []
564 self._out_buffer = []
490 self._out_buffer_lock.release()
565 self._out_buffer_lock.release()
491 self.write(''.join(_out_buffer), refresh=False)
566 self.write(''.join(_out_buffer), refresh=False)
492
567
493
568
494 def _colorize_input_buffer(self):
569 def _colorize_input_buffer(self):
495 """ Keep the input buffer lines at a bright color.
570 """ Keep the input buffer lines at a bright color.
496 """
571 """
497 if not self._input_state in ('readline', 'raw_input'):
572 if not self._input_state in ('readline', 'raw_input'):
498 return
573 return
499 end_line = self.GetCurrentLine()
574 end_line = self.GetCurrentLine()
500 if not sys.platform == 'win32':
575 if not sys.platform == 'win32':
501 end_line += 1
576 end_line += 1
502 for i in range(self.current_prompt_line, end_line):
577 for i in range(self.current_prompt_line, end_line):
503 if i in self._markers:
578 if i in self._markers:
504 self.MarkerDeleteHandle(self._markers[i])
579 self.MarkerDeleteHandle(self._markers[i])
505 self._markers[i] = self.MarkerAdd(i, _INPUT_MARKER)
580 self._markers[i] = self.MarkerAdd(i, _INPUT_MARKER)
506
581
507
582
508 if __name__ == '__main__':
583 if __name__ == '__main__':
509 class MainWindow(wx.Frame):
584 class MainWindow(wx.Frame):
510 def __init__(self, parent, id, title):
585 def __init__(self, parent, id, title):
511 wx.Frame.__init__(self, parent, id, title, size=(300,250))
586 wx.Frame.__init__(self, parent, id, title, size=(300,250))
512 self._sizer = wx.BoxSizer(wx.VERTICAL)
587 self._sizer = wx.BoxSizer(wx.VERTICAL)
513 self.shell = WxController(self)
588 self.shell = WxController(self)
514 self._sizer.Add(self.shell, 1, wx.EXPAND)
589 self._sizer.Add(self.shell, 1, wx.EXPAND)
515 self.SetSizer(self._sizer)
590 self.SetSizer(self._sizer)
516 self.SetAutoLayout(1)
591 self.SetAutoLayout(1)
517 self.Show(True)
592 self.Show(True)
518
593
519 app = wx.PySimpleApp()
594 app = wx.PySimpleApp()
520 frame = MainWindow(None, wx.ID_ANY, 'Ipython')
595 frame = MainWindow(None, wx.ID_ANY, 'Ipython')
521 frame.shell.SetFocus()
596 frame.shell.SetFocus()
522 frame.SetSize((680, 460))
597 frame.SetSize((680, 460))
523 self = frame.shell
598 self = frame.shell
524
599
525 app.MainLoop()
600 app.MainLoop()
526
601
@@ -1,2161 +1,2171 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """General purpose utilities.
2 """General purpose utilities.
3
3
4 This is a grab-bag of stuff I find useful in most programs I write. Some of
4 This is a grab-bag of stuff I find useful in most programs I write. Some of
5 these things are also convenient when working at the command line.
5 these things are also convenient when working at the command line.
6 """
6 """
7
7
8 #*****************************************************************************
8 #*****************************************************************************
9 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
9 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #*****************************************************************************
13 #*****************************************************************************
14
14
15 #****************************************************************************
15 #****************************************************************************
16 # required modules from the Python standard library
16 # required modules from the Python standard library
17 import __main__
17 import __main__
18 import commands
18 import commands
19 try:
19 try:
20 import doctest
20 import doctest
21 except ImportError:
21 except ImportError:
22 pass
22 pass
23 import os
23 import os
24 import platform
24 import platform
25 import re
25 import re
26 import shlex
26 import shlex
27 import shutil
27 import shutil
28 import subprocess
28 import subprocess
29 import sys
29 import sys
30 import tempfile
30 import tempfile
31 import time
31 import time
32 import types
32 import types
33 import warnings
33 import warnings
34
34
35 # Curses and termios are Unix-only modules
35 # Curses and termios are Unix-only modules
36 try:
36 try:
37 import curses
37 import curses
38 # We need termios as well, so if its import happens to raise, we bail on
38 # We need termios as well, so if its import happens to raise, we bail on
39 # using curses altogether.
39 # using curses altogether.
40 import termios
40 import termios
41 except ImportError:
41 except ImportError:
42 USE_CURSES = False
42 USE_CURSES = False
43 else:
43 else:
44 # Curses on Solaris may not be complete, so we can't use it there
44 # Curses on Solaris may not be complete, so we can't use it there
45 USE_CURSES = hasattr(curses,'initscr')
45 USE_CURSES = hasattr(curses,'initscr')
46
46
47 # Other IPython utilities
47 # Other IPython utilities
48 import IPython
48 import IPython
49 from IPython.Itpl import Itpl,itpl,printpl
49 from IPython.Itpl import Itpl,itpl,printpl
50 from IPython import DPyGetOpt, platutils
50 from IPython import DPyGetOpt, platutils
51 from IPython.generics import result_display
51 from IPython.generics import result_display
52 import IPython.ipapi
52 import IPython.ipapi
53 from IPython.external.path import path
53 from IPython.external.path import path
54 if os.name == "nt":
54 if os.name == "nt":
55 from IPython.winconsole import get_console_size
55 from IPython.winconsole import get_console_size
56
56
57 try:
57 try:
58 set
58 set
59 except:
59 except:
60 from sets import Set as set
60 from sets import Set as set
61
61
62
62
63 #****************************************************************************
63 #****************************************************************************
64 # Exceptions
64 # Exceptions
65 class Error(Exception):
65 class Error(Exception):
66 """Base class for exceptions in this module."""
66 """Base class for exceptions in this module."""
67 pass
67 pass
68
68
69 #----------------------------------------------------------------------------
69 #----------------------------------------------------------------------------
70 class IOStream:
70 class IOStream:
71 def __init__(self,stream,fallback):
71 def __init__(self,stream,fallback):
72 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
72 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
73 stream = fallback
73 stream = fallback
74 self.stream = stream
74 self.stream = stream
75 self._swrite = stream.write
75 self._swrite = stream.write
76 self.flush = stream.flush
76 self.flush = stream.flush
77
77
78 def write(self,data):
78 def write(self,data):
79 try:
79 try:
80 self._swrite(data)
80 self._swrite(data)
81 except:
81 except:
82 try:
82 try:
83 # print handles some unicode issues which may trip a plain
83 # print handles some unicode issues which may trip a plain
84 # write() call. Attempt to emulate write() by using a
84 # write() call. Attempt to emulate write() by using a
85 # trailing comma
85 # trailing comma
86 print >> self.stream, data,
86 print >> self.stream, data,
87 except:
87 except:
88 # if we get here, something is seriously broken.
88 # if we get here, something is seriously broken.
89 print >> sys.stderr, \
89 print >> sys.stderr, \
90 'ERROR - failed to write data to stream:', self.stream
90 'ERROR - failed to write data to stream:', self.stream
91
91
92 def close(self):
92 def close(self):
93 pass
93 pass
94
94
95
95
96 class IOTerm:
96 class IOTerm:
97 """ Term holds the file or file-like objects for handling I/O operations.
97 """ Term holds the file or file-like objects for handling I/O operations.
98
98
99 These are normally just sys.stdin, sys.stdout and sys.stderr but for
99 These are normally just sys.stdin, sys.stdout and sys.stderr but for
100 Windows they can can replaced to allow editing the strings before they are
100 Windows they can can replaced to allow editing the strings before they are
101 displayed."""
101 displayed."""
102
102
103 # In the future, having IPython channel all its I/O operations through
103 # In the future, having IPython channel all its I/O operations through
104 # this class will make it easier to embed it into other environments which
104 # this class will make it easier to embed it into other environments which
105 # are not a normal terminal (such as a GUI-based shell)
105 # are not a normal terminal (such as a GUI-based shell)
106 def __init__(self,cin=None,cout=None,cerr=None):
106 def __init__(self,cin=None,cout=None,cerr=None):
107 self.cin = IOStream(cin,sys.stdin)
107 self.cin = IOStream(cin,sys.stdin)
108 self.cout = IOStream(cout,sys.stdout)
108 self.cout = IOStream(cout,sys.stdout)
109 self.cerr = IOStream(cerr,sys.stderr)
109 self.cerr = IOStream(cerr,sys.stderr)
110
110
111 # Global variable to be used for all I/O
111 # Global variable to be used for all I/O
112 Term = IOTerm()
112 Term = IOTerm()
113
113
114 import IPython.rlineimpl as readline
114 import IPython.rlineimpl as readline
115 # Remake Term to use the readline i/o facilities
115 # Remake Term to use the readline i/o facilities
116 if sys.platform == 'win32' and readline.have_readline:
116 if sys.platform == 'win32' and readline.have_readline:
117
117
118 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
118 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
119
119
120
120
121 #****************************************************************************
121 #****************************************************************************
122 # Generic warning/error printer, used by everything else
122 # Generic warning/error printer, used by everything else
123 def warn(msg,level=2,exit_val=1):
123 def warn(msg,level=2,exit_val=1):
124 """Standard warning printer. Gives formatting consistency.
124 """Standard warning printer. Gives formatting consistency.
125
125
126 Output is sent to Term.cerr (sys.stderr by default).
126 Output is sent to Term.cerr (sys.stderr by default).
127
127
128 Options:
128 Options:
129
129
130 -level(2): allows finer control:
130 -level(2): allows finer control:
131 0 -> Do nothing, dummy function.
131 0 -> Do nothing, dummy function.
132 1 -> Print message.
132 1 -> Print message.
133 2 -> Print 'WARNING:' + message. (Default level).
133 2 -> Print 'WARNING:' + message. (Default level).
134 3 -> Print 'ERROR:' + message.
134 3 -> Print 'ERROR:' + message.
135 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
135 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
136
136
137 -exit_val (1): exit value returned by sys.exit() for a level 4
137 -exit_val (1): exit value returned by sys.exit() for a level 4
138 warning. Ignored for all other levels."""
138 warning. Ignored for all other levels."""
139
139
140 if level>0:
140 if level>0:
141 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
141 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
142 print >> Term.cerr, '%s%s' % (header[level],msg)
142 print >> Term.cerr, '%s%s' % (header[level],msg)
143 if level == 4:
143 if level == 4:
144 print >> Term.cerr,'Exiting.\n'
144 print >> Term.cerr,'Exiting.\n'
145 sys.exit(exit_val)
145 sys.exit(exit_val)
146
146
147 def info(msg):
147 def info(msg):
148 """Equivalent to warn(msg,level=1)."""
148 """Equivalent to warn(msg,level=1)."""
149
149
150 warn(msg,level=1)
150 warn(msg,level=1)
151
151
152 def error(msg):
152 def error(msg):
153 """Equivalent to warn(msg,level=3)."""
153 """Equivalent to warn(msg,level=3)."""
154
154
155 warn(msg,level=3)
155 warn(msg,level=3)
156
156
157 def fatal(msg,exit_val=1):
157 def fatal(msg,exit_val=1):
158 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
158 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
159
159
160 warn(msg,exit_val=exit_val,level=4)
160 warn(msg,exit_val=exit_val,level=4)
161
161
162 #---------------------------------------------------------------------------
162 #---------------------------------------------------------------------------
163 # Debugging routines
163 # Debugging routines
164 #
164 #
165 def debugx(expr,pre_msg=''):
165 def debugx(expr,pre_msg=''):
166 """Print the value of an expression from the caller's frame.
166 """Print the value of an expression from the caller's frame.
167
167
168 Takes an expression, evaluates it in the caller's frame and prints both
168 Takes an expression, evaluates it in the caller's frame and prints both
169 the given expression and the resulting value (as well as a debug mark
169 the given expression and the resulting value (as well as a debug mark
170 indicating the name of the calling function. The input must be of a form
170 indicating the name of the calling function. The input must be of a form
171 suitable for eval().
171 suitable for eval().
172
172
173 An optional message can be passed, which will be prepended to the printed
173 An optional message can be passed, which will be prepended to the printed
174 expr->value pair."""
174 expr->value pair."""
175
175
176 cf = sys._getframe(1)
176 cf = sys._getframe(1)
177 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
177 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
178 eval(expr,cf.f_globals,cf.f_locals))
178 eval(expr,cf.f_globals,cf.f_locals))
179
179
180 # deactivate it by uncommenting the following line, which makes it a no-op
180 # deactivate it by uncommenting the following line, which makes it a no-op
181 #def debugx(expr,pre_msg=''): pass
181 #def debugx(expr,pre_msg=''): pass
182
182
183 #----------------------------------------------------------------------------
183 #----------------------------------------------------------------------------
184 StringTypes = types.StringTypes
184 StringTypes = types.StringTypes
185
185
186 # Basic timing functionality
186 # Basic timing functionality
187
187
188 # If possible (Unix), use the resource module instead of time.clock()
188 # If possible (Unix), use the resource module instead of time.clock()
189 try:
189 try:
190 import resource
190 import resource
191 def clocku():
191 def clocku():
192 """clocku() -> floating point number
192 """clocku() -> floating point number
193
193
194 Return the *USER* CPU time in seconds since the start of the process.
194 Return the *USER* CPU time in seconds since the start of the process.
195 This is done via a call to resource.getrusage, so it avoids the
195 This is done via a call to resource.getrusage, so it avoids the
196 wraparound problems in time.clock()."""
196 wraparound problems in time.clock()."""
197
197
198 return resource.getrusage(resource.RUSAGE_SELF)[0]
198 return resource.getrusage(resource.RUSAGE_SELF)[0]
199
199
200 def clocks():
200 def clocks():
201 """clocks() -> floating point number
201 """clocks() -> floating point number
202
202
203 Return the *SYSTEM* CPU time in seconds since the start of the process.
203 Return the *SYSTEM* CPU time in seconds since the start of the process.
204 This is done via a call to resource.getrusage, so it avoids the
204 This is done via a call to resource.getrusage, so it avoids the
205 wraparound problems in time.clock()."""
205 wraparound problems in time.clock()."""
206
206
207 return resource.getrusage(resource.RUSAGE_SELF)[1]
207 return resource.getrusage(resource.RUSAGE_SELF)[1]
208
208
209 def clock():
209 def clock():
210 """clock() -> floating point number
210 """clock() -> floating point number
211
211
212 Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
212 Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
213 the process. This is done via a call to resource.getrusage, so it
213 the process. This is done via a call to resource.getrusage, so it
214 avoids the wraparound problems in time.clock()."""
214 avoids the wraparound problems in time.clock()."""
215
215
216 u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
216 u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
217 return u+s
217 return u+s
218
218
219 def clock2():
219 def clock2():
220 """clock2() -> (t_user,t_system)
220 """clock2() -> (t_user,t_system)
221
221
222 Similar to clock(), but return a tuple of user/system times."""
222 Similar to clock(), but return a tuple of user/system times."""
223 return resource.getrusage(resource.RUSAGE_SELF)[:2]
223 return resource.getrusage(resource.RUSAGE_SELF)[:2]
224
224
225 except ImportError:
225 except ImportError:
226 # There is no distinction of user/system time under windows, so we just use
226 # There is no distinction of user/system time under windows, so we just use
227 # time.clock() for everything...
227 # time.clock() for everything...
228 clocku = clocks = clock = time.clock
228 clocku = clocks = clock = time.clock
229 def clock2():
229 def clock2():
230 """Under windows, system CPU time can't be measured.
230 """Under windows, system CPU time can't be measured.
231
231
232 This just returns clock() and zero."""
232 This just returns clock() and zero."""
233 return time.clock(),0.0
233 return time.clock(),0.0
234
234
235 def timings_out(reps,func,*args,**kw):
235 def timings_out(reps,func,*args,**kw):
236 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
236 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
237
237
238 Execute a function reps times, return a tuple with the elapsed total
238 Execute a function reps times, return a tuple with the elapsed total
239 CPU time in seconds, the time per call and the function's output.
239 CPU time in seconds, the time per call and the function's output.
240
240
241 Under Unix, the return value is the sum of user+system time consumed by
241 Under Unix, the return value is the sum of user+system time consumed by
242 the process, computed via the resource module. This prevents problems
242 the process, computed via the resource module. This prevents problems
243 related to the wraparound effect which the time.clock() function has.
243 related to the wraparound effect which the time.clock() function has.
244
244
245 Under Windows the return value is in wall clock seconds. See the
245 Under Windows the return value is in wall clock seconds. See the
246 documentation for the time module for more details."""
246 documentation for the time module for more details."""
247
247
248 reps = int(reps)
248 reps = int(reps)
249 assert reps >=1, 'reps must be >= 1'
249 assert reps >=1, 'reps must be >= 1'
250 if reps==1:
250 if reps==1:
251 start = clock()
251 start = clock()
252 out = func(*args,**kw)
252 out = func(*args,**kw)
253 tot_time = clock()-start
253 tot_time = clock()-start
254 else:
254 else:
255 rng = xrange(reps-1) # the last time is executed separately to store output
255 rng = xrange(reps-1) # the last time is executed separately to store output
256 start = clock()
256 start = clock()
257 for dummy in rng: func(*args,**kw)
257 for dummy in rng: func(*args,**kw)
258 out = func(*args,**kw) # one last time
258 out = func(*args,**kw) # one last time
259 tot_time = clock()-start
259 tot_time = clock()-start
260 av_time = tot_time / reps
260 av_time = tot_time / reps
261 return tot_time,av_time,out
261 return tot_time,av_time,out
262
262
263 def timings(reps,func,*args,**kw):
263 def timings(reps,func,*args,**kw):
264 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
264 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
265
265
266 Execute a function reps times, return a tuple with the elapsed total CPU
266 Execute a function reps times, return a tuple with the elapsed total CPU
267 time in seconds and the time per call. These are just the first two values
267 time in seconds and the time per call. These are just the first two values
268 in timings_out()."""
268 in timings_out()."""
269
269
270 return timings_out(reps,func,*args,**kw)[0:2]
270 return timings_out(reps,func,*args,**kw)[0:2]
271
271
272 def timing(func,*args,**kw):
272 def timing(func,*args,**kw):
273 """timing(func,*args,**kw) -> t_total
273 """timing(func,*args,**kw) -> t_total
274
274
275 Execute a function once, return the elapsed total CPU time in
275 Execute a function once, return the elapsed total CPU time in
276 seconds. This is just the first value in timings_out()."""
276 seconds. This is just the first value in timings_out()."""
277
277
278 return timings_out(1,func,*args,**kw)[0]
278 return timings_out(1,func,*args,**kw)[0]
279
279
280 #****************************************************************************
280 #****************************************************************************
281 # file and system
281 # file and system
282
282
283 def arg_split(s,posix=False):
283 def arg_split(s,posix=False):
284 """Split a command line's arguments in a shell-like manner.
284 """Split a command line's arguments in a shell-like manner.
285
285
286 This is a modified version of the standard library's shlex.split()
286 This is a modified version of the standard library's shlex.split()
287 function, but with a default of posix=False for splitting, so that quotes
287 function, but with a default of posix=False for splitting, so that quotes
288 in inputs are respected."""
288 in inputs are respected."""
289
289
290 # XXX - there may be unicode-related problems here!!! I'm not sure that
290 # XXX - there may be unicode-related problems here!!! I'm not sure that
291 # shlex is truly unicode-safe, so it might be necessary to do
291 # shlex is truly unicode-safe, so it might be necessary to do
292 #
292 #
293 # s = s.encode(sys.stdin.encoding)
293 # s = s.encode(sys.stdin.encoding)
294 #
294 #
295 # first, to ensure that shlex gets a normal string. Input from anyone who
295 # first, to ensure that shlex gets a normal string. Input from anyone who
296 # knows more about unicode and shlex than I would be good to have here...
296 # knows more about unicode and shlex than I would be good to have here...
297 lex = shlex.shlex(s, posix=posix)
297 lex = shlex.shlex(s, posix=posix)
298 lex.whitespace_split = True
298 lex.whitespace_split = True
299 return list(lex)
299 return list(lex)
300
300
301 def system(cmd,verbose=0,debug=0,header=''):
301 def system(cmd,verbose=0,debug=0,header=''):
302 """Execute a system command, return its exit status.
302 """Execute a system command, return its exit status.
303
303
304 Options:
304 Options:
305
305
306 - verbose (0): print the command to be executed.
306 - verbose (0): print the command to be executed.
307
307
308 - debug (0): only print, do not actually execute.
308 - debug (0): only print, do not actually execute.
309
309
310 - header (''): Header to print on screen prior to the executed command (it
310 - header (''): Header to print on screen prior to the executed command (it
311 is only prepended to the command, no newlines are added).
311 is only prepended to the command, no newlines are added).
312
312
313 Note: a stateful version of this function is available through the
313 Note: a stateful version of this function is available through the
314 SystemExec class."""
314 SystemExec class."""
315
315
316 stat = 0
316 stat = 0
317 if verbose or debug: print header+cmd
317 if verbose or debug: print header+cmd
318 sys.stdout.flush()
318 sys.stdout.flush()
319 if not debug: stat = os.system(cmd)
319 if not debug: stat = os.system(cmd)
320 return stat
320 return stat
321
321
322 def abbrev_cwd():
322 def abbrev_cwd():
323 """ Return abbreviated version of cwd, e.g. d:mydir """
323 """ Return abbreviated version of cwd, e.g. d:mydir """
324 cwd = os.getcwd().replace('\\','/')
324 cwd = os.getcwd().replace('\\','/')
325 drivepart = ''
325 drivepart = ''
326 tail = cwd
326 tail = cwd
327 if sys.platform == 'win32':
327 if sys.platform == 'win32':
328 if len(cwd) < 4:
328 if len(cwd) < 4:
329 return cwd
329 return cwd
330 drivepart,tail = os.path.splitdrive(cwd)
330 drivepart,tail = os.path.splitdrive(cwd)
331
331
332
332
333 parts = tail.split('/')
333 parts = tail.split('/')
334 if len(parts) > 2:
334 if len(parts) > 2:
335 tail = '/'.join(parts[-2:])
335 tail = '/'.join(parts[-2:])
336
336
337 return (drivepart + (
337 return (drivepart + (
338 cwd == '/' and '/' or tail))
338 cwd == '/' and '/' or tail))
339
339
340
340
341 # This function is used by ipython in a lot of places to make system calls.
341 # This function is used by ipython in a lot of places to make system calls.
342 # We need it to be slightly different under win32, due to the vagaries of
342 # We need it to be slightly different under win32, due to the vagaries of
343 # 'network shares'. A win32 override is below.
343 # 'network shares'. A win32 override is below.
344
344
345 def shell(cmd,verbose=0,debug=0,header=''):
345 def shell(cmd,verbose=0,debug=0,header=''):
346 """Execute a command in the system shell, always return None.
346 """Execute a command in the system shell, always return None.
347
347
348 Options:
348 Options:
349
349
350 - verbose (0): print the command to be executed.
350 - verbose (0): print the command to be executed.
351
351
352 - debug (0): only print, do not actually execute.
352 - debug (0): only print, do not actually execute.
353
353
354 - header (''): Header to print on screen prior to the executed command (it
354 - header (''): Header to print on screen prior to the executed command (it
355 is only prepended to the command, no newlines are added).
355 is only prepended to the command, no newlines are added).
356
356
357 Note: this is similar to genutils.system(), but it returns None so it can
357 Note: this is similar to genutils.system(), but it returns None so it can
358 be conveniently used in interactive loops without getting the return value
358 be conveniently used in interactive loops without getting the return value
359 (typically 0) printed many times."""
359 (typically 0) printed many times."""
360
360
361 stat = 0
361 stat = 0
362 if verbose or debug: print header+cmd
362 if verbose or debug: print header+cmd
363 # flush stdout so we don't mangle python's buffering
363 # flush stdout so we don't mangle python's buffering
364 sys.stdout.flush()
364 sys.stdout.flush()
365
365
366 if not debug:
366 if not debug:
367 platutils.set_term_title("IPy " + cmd)
367 platutils.set_term_title("IPy " + cmd)
368 os.system(cmd)
368 os.system(cmd)
369 platutils.set_term_title("IPy " + abbrev_cwd())
369 platutils.set_term_title("IPy " + abbrev_cwd())
370
370
371 # override shell() for win32 to deal with network shares
371 # override shell() for win32 to deal with network shares
372 if os.name in ('nt','dos'):
372 if os.name in ('nt','dos'):
373
373
374 shell_ori = shell
374 shell_ori = shell
375
375
376 def shell(cmd,verbose=0,debug=0,header=''):
376 def shell(cmd,verbose=0,debug=0,header=''):
377 if os.getcwd().startswith(r"\\"):
377 if os.getcwd().startswith(r"\\"):
378 path = os.getcwd()
378 path = os.getcwd()
379 # change to c drive (cannot be on UNC-share when issuing os.system,
379 # change to c drive (cannot be on UNC-share when issuing os.system,
380 # as cmd.exe cannot handle UNC addresses)
380 # as cmd.exe cannot handle UNC addresses)
381 os.chdir("c:")
381 os.chdir("c:")
382 # issue pushd to the UNC-share and then run the command
382 # issue pushd to the UNC-share and then run the command
383 try:
383 try:
384 shell_ori('"pushd %s&&"'%path+cmd,verbose,debug,header)
384 shell_ori('"pushd %s&&"'%path+cmd,verbose,debug,header)
385 finally:
385 finally:
386 os.chdir(path)
386 os.chdir(path)
387 else:
387 else:
388 shell_ori(cmd,verbose,debug,header)
388 shell_ori(cmd,verbose,debug,header)
389
389
390 shell.__doc__ = shell_ori.__doc__
390 shell.__doc__ = shell_ori.__doc__
391
391
392 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
392 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
393 """Dummy substitute for perl's backquotes.
393 """Dummy substitute for perl's backquotes.
394
394
395 Executes a command and returns the output.
395 Executes a command and returns the output.
396
396
397 Accepts the same arguments as system(), plus:
397 Accepts the same arguments as system(), plus:
398
398
399 - split(0): if true, the output is returned as a list split on newlines.
399 - split(0): if true, the output is returned as a list split on newlines.
400
400
401 Note: a stateful version of this function is available through the
401 Note: a stateful version of this function is available through the
402 SystemExec class.
402 SystemExec class.
403
403
404 This is pretty much deprecated and rarely used,
404 This is pretty much deprecated and rarely used,
405 genutils.getoutputerror may be what you need.
405 genutils.getoutputerror may be what you need.
406
406
407 """
407 """
408
408
409 if verbose or debug: print header+cmd
409 if verbose or debug: print header+cmd
410 if not debug:
410 if not debug:
411 output = os.popen(cmd).read()
411 output = os.popen(cmd).read()
412 # stipping last \n is here for backwards compat.
412 # stipping last \n is here for backwards compat.
413 if output.endswith('\n'):
413 if output.endswith('\n'):
414 output = output[:-1]
414 output = output[:-1]
415 if split:
415 if split:
416 return output.split('\n')
416 return output.split('\n')
417 else:
417 else:
418 return output
418 return output
419
419
420 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
420 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
421 """Return (standard output,standard error) of executing cmd in a shell.
421 """Return (standard output,standard error) of executing cmd in a shell.
422
422
423 Accepts the same arguments as system(), plus:
423 Accepts the same arguments as system(), plus:
424
424
425 - split(0): if true, each of stdout/err is returned as a list split on
425 - split(0): if true, each of stdout/err is returned as a list split on
426 newlines.
426 newlines.
427
427
428 Note: a stateful version of this function is available through the
428 Note: a stateful version of this function is available through the
429 SystemExec class."""
429 SystemExec class."""
430
430
431 if verbose or debug: print header+cmd
431 if verbose or debug: print header+cmd
432 if not cmd:
432 if not cmd:
433 if split:
433 if split:
434 return [],[]
434 return [],[]
435 else:
435 else:
436 return '',''
436 return '',''
437 if not debug:
437 if not debug:
438 pin,pout,perr = os.popen3(cmd)
438 pin,pout,perr = os.popen3(cmd)
439 tout = pout.read().rstrip()
439 tout = pout.read().rstrip()
440 terr = perr.read().rstrip()
440 terr = perr.read().rstrip()
441 pin.close()
441 pin.close()
442 pout.close()
442 pout.close()
443 perr.close()
443 perr.close()
444 if split:
444 if split:
445 return tout.split('\n'),terr.split('\n')
445 return tout.split('\n'),terr.split('\n')
446 else:
446 else:
447 return tout,terr
447 return tout,terr
448
448
449 # for compatibility with older naming conventions
449 # for compatibility with older naming conventions
450 xsys = system
450 xsys = system
451 bq = getoutput
451 bq = getoutput
452
452
453 class SystemExec:
453 class SystemExec:
454 """Access the system and getoutput functions through a stateful interface.
454 """Access the system and getoutput functions through a stateful interface.
455
455
456 Note: here we refer to the system and getoutput functions from this
456 Note: here we refer to the system and getoutput functions from this
457 library, not the ones from the standard python library.
457 library, not the ones from the standard python library.
458
458
459 This class offers the system and getoutput functions as methods, but the
459 This class offers the system and getoutput functions as methods, but the
460 verbose, debug and header parameters can be set for the instance (at
460 verbose, debug and header parameters can be set for the instance (at
461 creation time or later) so that they don't need to be specified on each
461 creation time or later) so that they don't need to be specified on each
462 call.
462 call.
463
463
464 For efficiency reasons, there's no way to override the parameters on a
464 For efficiency reasons, there's no way to override the parameters on a
465 per-call basis other than by setting instance attributes. If you need
465 per-call basis other than by setting instance attributes. If you need
466 local overrides, it's best to directly call system() or getoutput().
466 local overrides, it's best to directly call system() or getoutput().
467
467
468 The following names are provided as alternate options:
468 The following names are provided as alternate options:
469 - xsys: alias to system
469 - xsys: alias to system
470 - bq: alias to getoutput
470 - bq: alias to getoutput
471
471
472 An instance can then be created as:
472 An instance can then be created as:
473 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
473 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
474 """
474 """
475
475
476 def __init__(self,verbose=0,debug=0,header='',split=0):
476 def __init__(self,verbose=0,debug=0,header='',split=0):
477 """Specify the instance's values for verbose, debug and header."""
477 """Specify the instance's values for verbose, debug and header."""
478 setattr_list(self,'verbose debug header split')
478 setattr_list(self,'verbose debug header split')
479
479
480 def system(self,cmd):
480 def system(self,cmd):
481 """Stateful interface to system(), with the same keyword parameters."""
481 """Stateful interface to system(), with the same keyword parameters."""
482
482
483 system(cmd,self.verbose,self.debug,self.header)
483 system(cmd,self.verbose,self.debug,self.header)
484
484
485 def shell(self,cmd):
485 def shell(self,cmd):
486 """Stateful interface to shell(), with the same keyword parameters."""
486 """Stateful interface to shell(), with the same keyword parameters."""
487
487
488 shell(cmd,self.verbose,self.debug,self.header)
488 shell(cmd,self.verbose,self.debug,self.header)
489
489
490 xsys = system # alias
490 xsys = system # alias
491
491
492 def getoutput(self,cmd):
492 def getoutput(self,cmd):
493 """Stateful interface to getoutput()."""
493 """Stateful interface to getoutput()."""
494
494
495 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
495 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
496
496
497 def getoutputerror(self,cmd):
497 def getoutputerror(self,cmd):
498 """Stateful interface to getoutputerror()."""
498 """Stateful interface to getoutputerror()."""
499
499
500 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
500 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
501
501
502 bq = getoutput # alias
502 bq = getoutput # alias
503
503
504 #-----------------------------------------------------------------------------
504 #-----------------------------------------------------------------------------
505 def mutex_opts(dict,ex_op):
505 def mutex_opts(dict,ex_op):
506 """Check for presence of mutually exclusive keys in a dict.
506 """Check for presence of mutually exclusive keys in a dict.
507
507
508 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
508 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
509 for op1,op2 in ex_op:
509 for op1,op2 in ex_op:
510 if op1 in dict and op2 in dict:
510 if op1 in dict and op2 in dict:
511 raise ValueError,'\n*** ERROR in Arguments *** '\
511 raise ValueError,'\n*** ERROR in Arguments *** '\
512 'Options '+op1+' and '+op2+' are mutually exclusive.'
512 'Options '+op1+' and '+op2+' are mutually exclusive.'
513
513
514 #-----------------------------------------------------------------------------
514 #-----------------------------------------------------------------------------
515 def get_py_filename(name):
515 def get_py_filename(name):
516 """Return a valid python filename in the current directory.
516 """Return a valid python filename in the current directory.
517
517
518 If the given name is not a file, it adds '.py' and searches again.
518 If the given name is not a file, it adds '.py' and searches again.
519 Raises IOError with an informative message if the file isn't found."""
519 Raises IOError with an informative message if the file isn't found."""
520
520
521 name = os.path.expanduser(name)
521 name = os.path.expanduser(name)
522 if not os.path.isfile(name) and not name.endswith('.py'):
522 if not os.path.isfile(name) and not name.endswith('.py'):
523 name += '.py'
523 name += '.py'
524 if os.path.isfile(name):
524 if os.path.isfile(name):
525 return name
525 return name
526 else:
526 else:
527 raise IOError,'File `%s` not found.' % name
527 raise IOError,'File `%s` not found.' % name
528
528
529 #-----------------------------------------------------------------------------
529 #-----------------------------------------------------------------------------
530 def filefind(fname,alt_dirs = None):
530 def filefind(fname,alt_dirs = None):
531 """Return the given filename either in the current directory, if it
531 """Return the given filename either in the current directory, if it
532 exists, or in a specified list of directories.
532 exists, or in a specified list of directories.
533
533
534 ~ expansion is done on all file and directory names.
534 ~ expansion is done on all file and directory names.
535
535
536 Upon an unsuccessful search, raise an IOError exception."""
536 Upon an unsuccessful search, raise an IOError exception."""
537
537
538 if alt_dirs is None:
538 if alt_dirs is None:
539 try:
539 try:
540 alt_dirs = get_home_dir()
540 alt_dirs = get_home_dir()
541 except HomeDirError:
541 except HomeDirError:
542 alt_dirs = os.getcwd()
542 alt_dirs = os.getcwd()
543 search = [fname] + list_strings(alt_dirs)
543 search = [fname] + list_strings(alt_dirs)
544 search = map(os.path.expanduser,search)
544 search = map(os.path.expanduser,search)
545 #print 'search list for',fname,'list:',search # dbg
545 #print 'search list for',fname,'list:',search # dbg
546 fname = search[0]
546 fname = search[0]
547 if os.path.isfile(fname):
547 if os.path.isfile(fname):
548 return fname
548 return fname
549 for direc in search[1:]:
549 for direc in search[1:]:
550 testname = os.path.join(direc,fname)
550 testname = os.path.join(direc,fname)
551 #print 'testname',testname # dbg
551 #print 'testname',testname # dbg
552 if os.path.isfile(testname):
552 if os.path.isfile(testname):
553 return testname
553 return testname
554 raise IOError,'File' + `fname` + \
554 raise IOError,'File' + `fname` + \
555 ' not found in current or supplied directories:' + `alt_dirs`
555 ' not found in current or supplied directories:' + `alt_dirs`
556
556
557 #----------------------------------------------------------------------------
557 #----------------------------------------------------------------------------
558 def file_read(filename):
558 def file_read(filename):
559 """Read a file and close it. Returns the file source."""
559 """Read a file and close it. Returns the file source."""
560 fobj = open(filename,'r');
560 fobj = open(filename,'r');
561 source = fobj.read();
561 source = fobj.read();
562 fobj.close()
562 fobj.close()
563 return source
563 return source
564
564
565 def file_readlines(filename):
565 def file_readlines(filename):
566 """Read a file and close it. Returns the file source using readlines()."""
566 """Read a file and close it. Returns the file source using readlines()."""
567 fobj = open(filename,'r');
567 fobj = open(filename,'r');
568 lines = fobj.readlines();
568 lines = fobj.readlines();
569 fobj.close()
569 fobj.close()
570 return lines
570 return lines
571
571
572 #----------------------------------------------------------------------------
572 #----------------------------------------------------------------------------
573 def target_outdated(target,deps):
573 def target_outdated(target,deps):
574 """Determine whether a target is out of date.
574 """Determine whether a target is out of date.
575
575
576 target_outdated(target,deps) -> 1/0
576 target_outdated(target,deps) -> 1/0
577
577
578 deps: list of filenames which MUST exist.
578 deps: list of filenames which MUST exist.
579 target: single filename which may or may not exist.
579 target: single filename which may or may not exist.
580
580
581 If target doesn't exist or is older than any file listed in deps, return
581 If target doesn't exist or is older than any file listed in deps, return
582 true, otherwise return false.
582 true, otherwise return false.
583 """
583 """
584 try:
584 try:
585 target_time = os.path.getmtime(target)
585 target_time = os.path.getmtime(target)
586 except os.error:
586 except os.error:
587 return 1
587 return 1
588 for dep in deps:
588 for dep in deps:
589 dep_time = os.path.getmtime(dep)
589 dep_time = os.path.getmtime(dep)
590 if dep_time > target_time:
590 if dep_time > target_time:
591 #print "For target",target,"Dep failed:",dep # dbg
591 #print "For target",target,"Dep failed:",dep # dbg
592 #print "times (dep,tar):",dep_time,target_time # dbg
592 #print "times (dep,tar):",dep_time,target_time # dbg
593 return 1
593 return 1
594 return 0
594 return 0
595
595
596 #-----------------------------------------------------------------------------
596 #-----------------------------------------------------------------------------
597 def target_update(target,deps,cmd):
597 def target_update(target,deps,cmd):
598 """Update a target with a given command given a list of dependencies.
598 """Update a target with a given command given a list of dependencies.
599
599
600 target_update(target,deps,cmd) -> runs cmd if target is outdated.
600 target_update(target,deps,cmd) -> runs cmd if target is outdated.
601
601
602 This is just a wrapper around target_outdated() which calls the given
602 This is just a wrapper around target_outdated() which calls the given
603 command if target is outdated."""
603 command if target is outdated."""
604
604
605 if target_outdated(target,deps):
605 if target_outdated(target,deps):
606 xsys(cmd)
606 xsys(cmd)
607
607
608 #----------------------------------------------------------------------------
608 #----------------------------------------------------------------------------
609 def unquote_ends(istr):
609 def unquote_ends(istr):
610 """Remove a single pair of quotes from the endpoints of a string."""
610 """Remove a single pair of quotes from the endpoints of a string."""
611
611
612 if not istr:
612 if not istr:
613 return istr
613 return istr
614 if (istr[0]=="'" and istr[-1]=="'") or \
614 if (istr[0]=="'" and istr[-1]=="'") or \
615 (istr[0]=='"' and istr[-1]=='"'):
615 (istr[0]=='"' and istr[-1]=='"'):
616 return istr[1:-1]
616 return istr[1:-1]
617 else:
617 else:
618 return istr
618 return istr
619
619
620 #----------------------------------------------------------------------------
620 #----------------------------------------------------------------------------
621 def process_cmdline(argv,names=[],defaults={},usage=''):
621 def process_cmdline(argv,names=[],defaults={},usage=''):
622 """ Process command-line options and arguments.
622 """ Process command-line options and arguments.
623
623
624 Arguments:
624 Arguments:
625
625
626 - argv: list of arguments, typically sys.argv.
626 - argv: list of arguments, typically sys.argv.
627
627
628 - names: list of option names. See DPyGetOpt docs for details on options
628 - names: list of option names. See DPyGetOpt docs for details on options
629 syntax.
629 syntax.
630
630
631 - defaults: dict of default values.
631 - defaults: dict of default values.
632
632
633 - usage: optional usage notice to print if a wrong argument is passed.
633 - usage: optional usage notice to print if a wrong argument is passed.
634
634
635 Return a dict of options and a list of free arguments."""
635 Return a dict of options and a list of free arguments."""
636
636
637 getopt = DPyGetOpt.DPyGetOpt()
637 getopt = DPyGetOpt.DPyGetOpt()
638 getopt.setIgnoreCase(0)
638 getopt.setIgnoreCase(0)
639 getopt.parseConfiguration(names)
639 getopt.parseConfiguration(names)
640
640
641 try:
641 try:
642 getopt.processArguments(argv)
642 getopt.processArguments(argv)
643 except DPyGetOpt.ArgumentError, exc:
643 except DPyGetOpt.ArgumentError, exc:
644 print usage
644 print usage
645 warn('"%s"' % exc,level=4)
645 warn('"%s"' % exc,level=4)
646
646
647 defaults.update(getopt.optionValues)
647 defaults.update(getopt.optionValues)
648 args = getopt.freeValues
648 args = getopt.freeValues
649
649
650 return defaults,args
650 return defaults,args
651
651
652 #----------------------------------------------------------------------------
652 #----------------------------------------------------------------------------
653 def optstr2types(ostr):
653 def optstr2types(ostr):
654 """Convert a string of option names to a dict of type mappings.
654 """Convert a string of option names to a dict of type mappings.
655
655
656 optstr2types(str) -> {None:'string_opts',int:'int_opts',float:'float_opts'}
656 optstr2types(str) -> {None:'string_opts',int:'int_opts',float:'float_opts'}
657
657
658 This is used to get the types of all the options in a string formatted
658 This is used to get the types of all the options in a string formatted
659 with the conventions of DPyGetOpt. The 'type' None is used for options
659 with the conventions of DPyGetOpt. The 'type' None is used for options
660 which are strings (they need no further conversion). This function's main
660 which are strings (they need no further conversion). This function's main
661 use is to get a typemap for use with read_dict().
661 use is to get a typemap for use with read_dict().
662 """
662 """
663
663
664 typeconv = {None:'',int:'',float:''}
664 typeconv = {None:'',int:'',float:''}
665 typemap = {'s':None,'i':int,'f':float}
665 typemap = {'s':None,'i':int,'f':float}
666 opt_re = re.compile(r'([\w]*)([^:=]*:?=?)([sif]?)')
666 opt_re = re.compile(r'([\w]*)([^:=]*:?=?)([sif]?)')
667
667
668 for w in ostr.split():
668 for w in ostr.split():
669 oname,alias,otype = opt_re.match(w).groups()
669 oname,alias,otype = opt_re.match(w).groups()
670 if otype == '' or alias == '!': # simple switches are integers too
670 if otype == '' or alias == '!': # simple switches are integers too
671 otype = 'i'
671 otype = 'i'
672 typeconv[typemap[otype]] += oname + ' '
672 typeconv[typemap[otype]] += oname + ' '
673 return typeconv
673 return typeconv
674
674
675 #----------------------------------------------------------------------------
675 #----------------------------------------------------------------------------
676 def read_dict(filename,type_conv=None,**opt):
676 def read_dict(filename,type_conv=None,**opt):
677 r"""Read a dictionary of key=value pairs from an input file, optionally
677 r"""Read a dictionary of key=value pairs from an input file, optionally
678 performing conversions on the resulting values.
678 performing conversions on the resulting values.
679
679
680 read_dict(filename,type_conv,**opt) -> dict
680 read_dict(filename,type_conv,**opt) -> dict
681
681
682 Only one value per line is accepted, the format should be
682 Only one value per line is accepted, the format should be
683 # optional comments are ignored
683 # optional comments are ignored
684 key value\n
684 key value\n
685
685
686 Args:
686 Args:
687
687
688 - type_conv: A dictionary specifying which keys need to be converted to
688 - type_conv: A dictionary specifying which keys need to be converted to
689 which types. By default all keys are read as strings. This dictionary
689 which types. By default all keys are read as strings. This dictionary
690 should have as its keys valid conversion functions for strings
690 should have as its keys valid conversion functions for strings
691 (int,long,float,complex, or your own). The value for each key
691 (int,long,float,complex, or your own). The value for each key
692 (converter) should be a whitespace separated string containing the names
692 (converter) should be a whitespace separated string containing the names
693 of all the entries in the file to be converted using that function. For
693 of all the entries in the file to be converted using that function. For
694 keys to be left alone, use None as the conversion function (only needed
694 keys to be left alone, use None as the conversion function (only needed
695 with purge=1, see below).
695 with purge=1, see below).
696
696
697 - opt: dictionary with extra options as below (default in parens)
697 - opt: dictionary with extra options as below (default in parens)
698
698
699 purge(0): if set to 1, all keys *not* listed in type_conv are purged out
699 purge(0): if set to 1, all keys *not* listed in type_conv are purged out
700 of the dictionary to be returned. If purge is going to be used, the
700 of the dictionary to be returned. If purge is going to be used, the
701 set of keys to be left as strings also has to be explicitly specified
701 set of keys to be left as strings also has to be explicitly specified
702 using the (non-existent) conversion function None.
702 using the (non-existent) conversion function None.
703
703
704 fs(None): field separator. This is the key/value separator to be used
704 fs(None): field separator. This is the key/value separator to be used
705 when parsing the file. The None default means any whitespace [behavior
705 when parsing the file. The None default means any whitespace [behavior
706 of string.split()].
706 of string.split()].
707
707
708 strip(0): if 1, strip string values of leading/trailinig whitespace.
708 strip(0): if 1, strip string values of leading/trailinig whitespace.
709
709
710 warn(1): warning level if requested keys are not found in file.
710 warn(1): warning level if requested keys are not found in file.
711 - 0: silently ignore.
711 - 0: silently ignore.
712 - 1: inform but proceed.
712 - 1: inform but proceed.
713 - 2: raise KeyError exception.
713 - 2: raise KeyError exception.
714
714
715 no_empty(0): if 1, remove keys with whitespace strings as a value.
715 no_empty(0): if 1, remove keys with whitespace strings as a value.
716
716
717 unique([]): list of keys (or space separated string) which can't be
717 unique([]): list of keys (or space separated string) which can't be
718 repeated. If one such key is found in the file, each new instance
718 repeated. If one such key is found in the file, each new instance
719 overwrites the previous one. For keys not listed here, the behavior is
719 overwrites the previous one. For keys not listed here, the behavior is
720 to make a list of all appearances.
720 to make a list of all appearances.
721
721
722 Example:
722 Example:
723
723
724 If the input file test.ini contains (we put it in a string to keep the test
724 If the input file test.ini contains (we put it in a string to keep the test
725 self-contained):
725 self-contained):
726
726
727 >>> test_ini = '''\
727 >>> test_ini = '''\
728 ... i 3
728 ... i 3
729 ... x 4.5
729 ... x 4.5
730 ... y 5.5
730 ... y 5.5
731 ... s hi ho'''
731 ... s hi ho'''
732
732
733 Then we can use it as follows:
733 Then we can use it as follows:
734 >>> type_conv={int:'i',float:'x',None:'s'}
734 >>> type_conv={int:'i',float:'x',None:'s'}
735
735
736 >>> d = read_dict(test_ini)
736 >>> d = read_dict(test_ini)
737
737
738 >>> sorted(d.items())
738 >>> sorted(d.items())
739 [('i', '3'), ('s', 'hi ho'), ('x', '4.5'), ('y', '5.5')]
739 [('i', '3'), ('s', 'hi ho'), ('x', '4.5'), ('y', '5.5')]
740
740
741 >>> d = read_dict(test_ini,type_conv)
741 >>> d = read_dict(test_ini,type_conv)
742
742
743 >>> sorted(d.items())
743 >>> sorted(d.items())
744 [('i', 3), ('s', 'hi ho'), ('x', 4.5), ('y', '5.5')]
744 [('i', 3), ('s', 'hi ho'), ('x', 4.5), ('y', '5.5')]
745
745
746 >>> d = read_dict(test_ini,type_conv,purge=True)
746 >>> d = read_dict(test_ini,type_conv,purge=True)
747
747
748 >>> sorted(d.items())
748 >>> sorted(d.items())
749 [('i', 3), ('s', 'hi ho'), ('x', 4.5)]
749 [('i', 3), ('s', 'hi ho'), ('x', 4.5)]
750 """
750 """
751
751
752 # starting config
752 # starting config
753 opt.setdefault('purge',0)
753 opt.setdefault('purge',0)
754 opt.setdefault('fs',None) # field sep defaults to any whitespace
754 opt.setdefault('fs',None) # field sep defaults to any whitespace
755 opt.setdefault('strip',0)
755 opt.setdefault('strip',0)
756 opt.setdefault('warn',1)
756 opt.setdefault('warn',1)
757 opt.setdefault('no_empty',0)
757 opt.setdefault('no_empty',0)
758 opt.setdefault('unique','')
758 opt.setdefault('unique','')
759 if type(opt['unique']) in StringTypes:
759 if type(opt['unique']) in StringTypes:
760 unique_keys = qw(opt['unique'])
760 unique_keys = qw(opt['unique'])
761 elif type(opt['unique']) in (types.TupleType,types.ListType):
761 elif type(opt['unique']) in (types.TupleType,types.ListType):
762 unique_keys = opt['unique']
762 unique_keys = opt['unique']
763 else:
763 else:
764 raise ValueError, 'Unique keys must be given as a string, List or Tuple'
764 raise ValueError, 'Unique keys must be given as a string, List or Tuple'
765
765
766 dict = {}
766 dict = {}
767
767
768 # first read in table of values as strings
768 # first read in table of values as strings
769 if '\n' in filename:
769 if '\n' in filename:
770 lines = filename.splitlines()
770 lines = filename.splitlines()
771 file = None
771 file = None
772 else:
772 else:
773 file = open(filename,'r')
773 file = open(filename,'r')
774 lines = file.readlines()
774 lines = file.readlines()
775 for line in lines:
775 for line in lines:
776 line = line.strip()
776 line = line.strip()
777 if len(line) and line[0]=='#': continue
777 if len(line) and line[0]=='#': continue
778 if len(line)>0:
778 if len(line)>0:
779 lsplit = line.split(opt['fs'],1)
779 lsplit = line.split(opt['fs'],1)
780 try:
780 try:
781 key,val = lsplit
781 key,val = lsplit
782 except ValueError:
782 except ValueError:
783 key,val = lsplit[0],''
783 key,val = lsplit[0],''
784 key = key.strip()
784 key = key.strip()
785 if opt['strip']: val = val.strip()
785 if opt['strip']: val = val.strip()
786 if val == "''" or val == '""': val = ''
786 if val == "''" or val == '""': val = ''
787 if opt['no_empty'] and (val=='' or val.isspace()):
787 if opt['no_empty'] and (val=='' or val.isspace()):
788 continue
788 continue
789 # if a key is found more than once in the file, build a list
789 # if a key is found more than once in the file, build a list
790 # unless it's in the 'unique' list. In that case, last found in file
790 # unless it's in the 'unique' list. In that case, last found in file
791 # takes precedence. User beware.
791 # takes precedence. User beware.
792 try:
792 try:
793 if dict[key] and key in unique_keys:
793 if dict[key] and key in unique_keys:
794 dict[key] = val
794 dict[key] = val
795 elif type(dict[key]) is types.ListType:
795 elif type(dict[key]) is types.ListType:
796 dict[key].append(val)
796 dict[key].append(val)
797 else:
797 else:
798 dict[key] = [dict[key],val]
798 dict[key] = [dict[key],val]
799 except KeyError:
799 except KeyError:
800 dict[key] = val
800 dict[key] = val
801 # purge if requested
801 # purge if requested
802 if opt['purge']:
802 if opt['purge']:
803 accepted_keys = qwflat(type_conv.values())
803 accepted_keys = qwflat(type_conv.values())
804 for key in dict.keys():
804 for key in dict.keys():
805 if key in accepted_keys: continue
805 if key in accepted_keys: continue
806 del(dict[key])
806 del(dict[key])
807 # now convert if requested
807 # now convert if requested
808 if type_conv==None: return dict
808 if type_conv==None: return dict
809 conversions = type_conv.keys()
809 conversions = type_conv.keys()
810 try: conversions.remove(None)
810 try: conversions.remove(None)
811 except: pass
811 except: pass
812 for convert in conversions:
812 for convert in conversions:
813 for val in qw(type_conv[convert]):
813 for val in qw(type_conv[convert]):
814 try:
814 try:
815 dict[val] = convert(dict[val])
815 dict[val] = convert(dict[val])
816 except KeyError,e:
816 except KeyError,e:
817 if opt['warn'] == 0:
817 if opt['warn'] == 0:
818 pass
818 pass
819 elif opt['warn'] == 1:
819 elif opt['warn'] == 1:
820 print >>sys.stderr, 'Warning: key',val,\
820 print >>sys.stderr, 'Warning: key',val,\
821 'not found in file',filename
821 'not found in file',filename
822 elif opt['warn'] == 2:
822 elif opt['warn'] == 2:
823 raise KeyError,e
823 raise KeyError,e
824 else:
824 else:
825 raise ValueError,'Warning level must be 0,1 or 2'
825 raise ValueError,'Warning level must be 0,1 or 2'
826
826
827 return dict
827 return dict
828
828
829 #----------------------------------------------------------------------------
829 #----------------------------------------------------------------------------
830 def flag_calls(func):
830 def flag_calls(func):
831 """Wrap a function to detect and flag when it gets called.
831 """Wrap a function to detect and flag when it gets called.
832
832
833 This is a decorator which takes a function and wraps it in a function with
833 This is a decorator which takes a function and wraps it in a function with
834 a 'called' attribute. wrapper.called is initialized to False.
834 a 'called' attribute. wrapper.called is initialized to False.
835
835
836 The wrapper.called attribute is set to False right before each call to the
836 The wrapper.called attribute is set to False right before each call to the
837 wrapped function, so if the call fails it remains False. After the call
837 wrapped function, so if the call fails it remains False. After the call
838 completes, wrapper.called is set to True and the output is returned.
838 completes, wrapper.called is set to True and the output is returned.
839
839
840 Testing for truth in wrapper.called allows you to determine if a call to
840 Testing for truth in wrapper.called allows you to determine if a call to
841 func() was attempted and succeeded."""
841 func() was attempted and succeeded."""
842
842
843 def wrapper(*args,**kw):
843 def wrapper(*args,**kw):
844 wrapper.called = False
844 wrapper.called = False
845 out = func(*args,**kw)
845 out = func(*args,**kw)
846 wrapper.called = True
846 wrapper.called = True
847 return out
847 return out
848
848
849 wrapper.called = False
849 wrapper.called = False
850 wrapper.__doc__ = func.__doc__
850 wrapper.__doc__ = func.__doc__
851 return wrapper
851 return wrapper
852
852
853 #----------------------------------------------------------------------------
853 #----------------------------------------------------------------------------
854 def dhook_wrap(func,*a,**k):
854 def dhook_wrap(func,*a,**k):
855 """Wrap a function call in a sys.displayhook controller.
855 """Wrap a function call in a sys.displayhook controller.
856
856
857 Returns a wrapper around func which calls func, with all its arguments and
857 Returns a wrapper around func which calls func, with all its arguments and
858 keywords unmodified, using the default sys.displayhook. Since IPython
858 keywords unmodified, using the default sys.displayhook. Since IPython
859 modifies sys.displayhook, it breaks the behavior of certain systems that
859 modifies sys.displayhook, it breaks the behavior of certain systems that
860 rely on the default behavior, notably doctest.
860 rely on the default behavior, notably doctest.
861 """
861 """
862
862
863 def f(*a,**k):
863 def f(*a,**k):
864
864
865 dhook_s = sys.displayhook
865 dhook_s = sys.displayhook
866 sys.displayhook = sys.__displayhook__
866 sys.displayhook = sys.__displayhook__
867 try:
867 try:
868 out = func(*a,**k)
868 out = func(*a,**k)
869 finally:
869 finally:
870 sys.displayhook = dhook_s
870 sys.displayhook = dhook_s
871
871
872 return out
872 return out
873
873
874 f.__doc__ = func.__doc__
874 f.__doc__ = func.__doc__
875 return f
875 return f
876
876
877 #----------------------------------------------------------------------------
877 #----------------------------------------------------------------------------
878 def doctest_reload():
878 def doctest_reload():
879 """Properly reload doctest to reuse it interactively.
879 """Properly reload doctest to reuse it interactively.
880
880
881 This routine:
881 This routine:
882
882
883 - reloads doctest
883 - reloads doctest
884
884
885 - resets its global 'master' attribute to None, so that multiple uses of
885 - resets its global 'master' attribute to None, so that multiple uses of
886 the module interactively don't produce cumulative reports.
886 the module interactively don't produce cumulative reports.
887
887
888 - Monkeypatches its core test runner method to protect it from IPython's
888 - Monkeypatches its core test runner method to protect it from IPython's
889 modified displayhook. Doctest expects the default displayhook behavior
889 modified displayhook. Doctest expects the default displayhook behavior
890 deep down, so our modification breaks it completely. For this reason, a
890 deep down, so our modification breaks it completely. For this reason, a
891 hard monkeypatch seems like a reasonable solution rather than asking
891 hard monkeypatch seems like a reasonable solution rather than asking
892 users to manually use a different doctest runner when under IPython."""
892 users to manually use a different doctest runner when under IPython."""
893
893
894 import doctest
894 import doctest
895 reload(doctest)
895 reload(doctest)
896 doctest.master=None
896 doctest.master=None
897
897
898 try:
898 try:
899 doctest.DocTestRunner
899 doctest.DocTestRunner
900 except AttributeError:
900 except AttributeError:
901 # This is only for python 2.3 compatibility, remove once we move to
901 # This is only for python 2.3 compatibility, remove once we move to
902 # 2.4 only.
902 # 2.4 only.
903 pass
903 pass
904 else:
904 else:
905 doctest.DocTestRunner.run = dhook_wrap(doctest.DocTestRunner.run)
905 doctest.DocTestRunner.run = dhook_wrap(doctest.DocTestRunner.run)
906
906
907 #----------------------------------------------------------------------------
907 #----------------------------------------------------------------------------
908 class HomeDirError(Error):
908 class HomeDirError(Error):
909 pass
909 pass
910
910
911 def get_home_dir():
911 def get_home_dir():
912 """Return the closest possible equivalent to a 'home' directory.
912 """Return the closest possible equivalent to a 'home' directory.
913
913
914 We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH.
914 We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH.
915
915
916 Currently only Posix and NT are implemented, a HomeDirError exception is
916 Currently only Posix and NT are implemented, a HomeDirError exception is
917 raised for all other OSes. """
917 raised for all other OSes. """
918
918
919 isdir = os.path.isdir
919 isdir = os.path.isdir
920 env = os.environ
920 env = os.environ
921
921
922 # first, check py2exe distribution root directory for _ipython.
922 # first, check py2exe distribution root directory for _ipython.
923 # This overrides all. Normally does not exist.
923 # This overrides all. Normally does not exist.
924
924
925 if hasattr(sys, "frozen"): #Is frozen by py2exe
925 if hasattr(sys, "frozen"): #Is frozen by py2exe
926 if '\\library.zip\\' in IPython.__file__.lower():#libraries compressed to zip-file
926 if '\\library.zip\\' in IPython.__file__.lower():#libraries compressed to zip-file
927 root, rest = IPython.__file__.lower().split('library.zip')
927 root, rest = IPython.__file__.lower().split('library.zip')
928 else:
928 else:
929 root=os.path.join(os.path.split(IPython.__file__)[0],"../../")
929 root=os.path.join(os.path.split(IPython.__file__)[0],"../../")
930 root=os.path.abspath(root).rstrip('\\')
930 root=os.path.abspath(root).rstrip('\\')
931 if isdir(os.path.join(root, '_ipython')):
931 if isdir(os.path.join(root, '_ipython')):
932 os.environ["IPYKITROOT"] = root
932 os.environ["IPYKITROOT"] = root
933 return root
933 return root
934 try:
934 try:
935 homedir = env['HOME']
935 homedir = env['HOME']
936 if not isdir(homedir):
936 if not isdir(homedir):
937 # in case a user stuck some string which does NOT resolve to a
937 # in case a user stuck some string which does NOT resolve to a
938 # valid path, it's as good as if we hadn't foud it
938 # valid path, it's as good as if we hadn't foud it
939 raise KeyError
939 raise KeyError
940 return homedir
940 return homedir
941 except KeyError:
941 except KeyError:
942 if os.name == 'posix':
942 if os.name == 'posix':
943 raise HomeDirError,'undefined $HOME, IPython can not proceed.'
943 raise HomeDirError,'undefined $HOME, IPython can not proceed.'
944 elif os.name == 'nt':
944 elif os.name == 'nt':
945 # For some strange reason, win9x returns 'nt' for os.name.
945 # For some strange reason, win9x returns 'nt' for os.name.
946 try:
946 try:
947 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
947 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
948 if not isdir(homedir):
948 if not isdir(homedir):
949 homedir = os.path.join(env['USERPROFILE'])
949 homedir = os.path.join(env['USERPROFILE'])
950 if not isdir(homedir):
950 if not isdir(homedir):
951 raise HomeDirError
951 raise HomeDirError
952 return homedir
952 return homedir
953 except KeyError:
953 except KeyError:
954 try:
954 try:
955 # Use the registry to get the 'My Documents' folder.
955 # Use the registry to get the 'My Documents' folder.
956 import _winreg as wreg
956 import _winreg as wreg
957 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
957 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
958 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
958 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
959 homedir = wreg.QueryValueEx(key,'Personal')[0]
959 homedir = wreg.QueryValueEx(key,'Personal')[0]
960 key.Close()
960 key.Close()
961 if not isdir(homedir):
961 if not isdir(homedir):
962 e = ('Invalid "Personal" folder registry key '
962 e = ('Invalid "Personal" folder registry key '
963 'typically "My Documents".\n'
963 'typically "My Documents".\n'
964 'Value: %s\n'
964 'Value: %s\n'
965 'This is not a valid directory on your system.' %
965 'This is not a valid directory on your system.' %
966 homedir)
966 homedir)
967 raise HomeDirError(e)
967 raise HomeDirError(e)
968 return homedir
968 return homedir
969 except HomeDirError:
969 except HomeDirError:
970 raise
970 raise
971 except:
971 except:
972 return 'C:\\'
972 return 'C:\\'
973 elif os.name == 'dos':
973 elif os.name == 'dos':
974 # Desperate, may do absurd things in classic MacOS. May work under DOS.
974 # Desperate, may do absurd things in classic MacOS. May work under DOS.
975 return 'C:\\'
975 return 'C:\\'
976 else:
976 else:
977 raise HomeDirError,'support for your operating system not implemented.'
977 raise HomeDirError,'support for your operating system not implemented.'
978
978
979
979
980 def get_ipython_dir():
980 def get_ipython_dir():
981 """Get the IPython directory for this platform and user.
981 """Get the IPython directory for this platform and user.
982
982
983 This uses the logic in `get_home_dir` to find the home directory
983 This uses the logic in `get_home_dir` to find the home directory
984 and the adds either .ipython or _ipython to the end of the path.
984 and the adds either .ipython or _ipython to the end of the path.
985 """
985 """
986 if os.name == 'posix':
986 if os.name == 'posix':
987 ipdir_def = '.ipython'
987 ipdir_def = '.ipython'
988 else:
988 else:
989 ipdir_def = '_ipython'
989 ipdir_def = '_ipython'
990 home_dir = get_home_dir()
990 home_dir = get_home_dir()
991 ipdir = os.path.abspath(os.environ.get('IPYTHONDIR',
991 ipdir = os.path.abspath(os.environ.get('IPYTHONDIR',
992 os.path.join(home_dir, ipdir_def)))
992 os.path.join(home_dir, ipdir_def)))
993 return ipdir.decode(sys.getfilesystemencoding())
993 return ipdir.decode(sys.getfilesystemencoding())
994
994
995 def get_security_dir():
995 def get_security_dir():
996 """Get the IPython security directory.
996 """Get the IPython security directory.
997
997
998 This directory is the default location for all security related files,
998 This directory is the default location for all security related files,
999 including SSL/TLS certificates and FURL files.
999 including SSL/TLS certificates and FURL files.
1000
1000
1001 If the directory does not exist, it is created with 0700 permissions.
1001 If the directory does not exist, it is created with 0700 permissions.
1002 If it exists, permissions are set to 0700.
1002 If it exists, permissions are set to 0700.
1003 """
1003 """
1004 security_dir = os.path.join(get_ipython_dir(), 'security')
1004 security_dir = os.path.join(get_ipython_dir(), 'security')
1005 if not os.path.isdir(security_dir):
1005 if not os.path.isdir(security_dir):
1006 os.mkdir(security_dir, 0700)
1006 os.mkdir(security_dir, 0700)
1007 else:
1007 else:
1008 os.chmod(security_dir, 0700)
1008 os.chmod(security_dir, 0700)
1009 return security_dir
1009 return security_dir
1010
1010
1011 def get_log_dir():
1012 """Get the IPython log directory.
1013
1014 If the log directory does not exist, it is created.
1015 """
1016 log_dir = os.path.join(get_ipython_dir(), 'log')
1017 if not os.path.isdir(log_dir):
1018 os.mkdir(log_dir, 0777)
1019 return log_dir
1020
1011 #****************************************************************************
1021 #****************************************************************************
1012 # strings and text
1022 # strings and text
1013
1023
1014 class LSString(str):
1024 class LSString(str):
1015 """String derivative with a special access attributes.
1025 """String derivative with a special access attributes.
1016
1026
1017 These are normal strings, but with the special attributes:
1027 These are normal strings, but with the special attributes:
1018
1028
1019 .l (or .list) : value as list (split on newlines).
1029 .l (or .list) : value as list (split on newlines).
1020 .n (or .nlstr): original value (the string itself).
1030 .n (or .nlstr): original value (the string itself).
1021 .s (or .spstr): value as whitespace-separated string.
1031 .s (or .spstr): value as whitespace-separated string.
1022 .p (or .paths): list of path objects
1032 .p (or .paths): list of path objects
1023
1033
1024 Any values which require transformations are computed only once and
1034 Any values which require transformations are computed only once and
1025 cached.
1035 cached.
1026
1036
1027 Such strings are very useful to efficiently interact with the shell, which
1037 Such strings are very useful to efficiently interact with the shell, which
1028 typically only understands whitespace-separated options for commands."""
1038 typically only understands whitespace-separated options for commands."""
1029
1039
1030 def get_list(self):
1040 def get_list(self):
1031 try:
1041 try:
1032 return self.__list
1042 return self.__list
1033 except AttributeError:
1043 except AttributeError:
1034 self.__list = self.split('\n')
1044 self.__list = self.split('\n')
1035 return self.__list
1045 return self.__list
1036
1046
1037 l = list = property(get_list)
1047 l = list = property(get_list)
1038
1048
1039 def get_spstr(self):
1049 def get_spstr(self):
1040 try:
1050 try:
1041 return self.__spstr
1051 return self.__spstr
1042 except AttributeError:
1052 except AttributeError:
1043 self.__spstr = self.replace('\n',' ')
1053 self.__spstr = self.replace('\n',' ')
1044 return self.__spstr
1054 return self.__spstr
1045
1055
1046 s = spstr = property(get_spstr)
1056 s = spstr = property(get_spstr)
1047
1057
1048 def get_nlstr(self):
1058 def get_nlstr(self):
1049 return self
1059 return self
1050
1060
1051 n = nlstr = property(get_nlstr)
1061 n = nlstr = property(get_nlstr)
1052
1062
1053 def get_paths(self):
1063 def get_paths(self):
1054 try:
1064 try:
1055 return self.__paths
1065 return self.__paths
1056 except AttributeError:
1066 except AttributeError:
1057 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
1067 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
1058 return self.__paths
1068 return self.__paths
1059
1069
1060 p = paths = property(get_paths)
1070 p = paths = property(get_paths)
1061
1071
1062 def print_lsstring(arg):
1072 def print_lsstring(arg):
1063 """ Prettier (non-repr-like) and more informative printer for LSString """
1073 """ Prettier (non-repr-like) and more informative printer for LSString """
1064 print "LSString (.p, .n, .l, .s available). Value:"
1074 print "LSString (.p, .n, .l, .s available). Value:"
1065 print arg
1075 print arg
1066
1076
1067 print_lsstring = result_display.when_type(LSString)(print_lsstring)
1077 print_lsstring = result_display.when_type(LSString)(print_lsstring)
1068
1078
1069 #----------------------------------------------------------------------------
1079 #----------------------------------------------------------------------------
1070 class SList(list):
1080 class SList(list):
1071 """List derivative with a special access attributes.
1081 """List derivative with a special access attributes.
1072
1082
1073 These are normal lists, but with the special attributes:
1083 These are normal lists, but with the special attributes:
1074
1084
1075 .l (or .list) : value as list (the list itself).
1085 .l (or .list) : value as list (the list itself).
1076 .n (or .nlstr): value as a string, joined on newlines.
1086 .n (or .nlstr): value as a string, joined on newlines.
1077 .s (or .spstr): value as a string, joined on spaces.
1087 .s (or .spstr): value as a string, joined on spaces.
1078 .p (or .paths): list of path objects
1088 .p (or .paths): list of path objects
1079
1089
1080 Any values which require transformations are computed only once and
1090 Any values which require transformations are computed only once and
1081 cached."""
1091 cached."""
1082
1092
1083 def get_list(self):
1093 def get_list(self):
1084 return self
1094 return self
1085
1095
1086 l = list = property(get_list)
1096 l = list = property(get_list)
1087
1097
1088 def get_spstr(self):
1098 def get_spstr(self):
1089 try:
1099 try:
1090 return self.__spstr
1100 return self.__spstr
1091 except AttributeError:
1101 except AttributeError:
1092 self.__spstr = ' '.join(self)
1102 self.__spstr = ' '.join(self)
1093 return self.__spstr
1103 return self.__spstr
1094
1104
1095 s = spstr = property(get_spstr)
1105 s = spstr = property(get_spstr)
1096
1106
1097 def get_nlstr(self):
1107 def get_nlstr(self):
1098 try:
1108 try:
1099 return self.__nlstr
1109 return self.__nlstr
1100 except AttributeError:
1110 except AttributeError:
1101 self.__nlstr = '\n'.join(self)
1111 self.__nlstr = '\n'.join(self)
1102 return self.__nlstr
1112 return self.__nlstr
1103
1113
1104 n = nlstr = property(get_nlstr)
1114 n = nlstr = property(get_nlstr)
1105
1115
1106 def get_paths(self):
1116 def get_paths(self):
1107 try:
1117 try:
1108 return self.__paths
1118 return self.__paths
1109 except AttributeError:
1119 except AttributeError:
1110 self.__paths = [path(p) for p in self if os.path.exists(p)]
1120 self.__paths = [path(p) for p in self if os.path.exists(p)]
1111 return self.__paths
1121 return self.__paths
1112
1122
1113 p = paths = property(get_paths)
1123 p = paths = property(get_paths)
1114
1124
1115 def grep(self, pattern, prune = False, field = None):
1125 def grep(self, pattern, prune = False, field = None):
1116 """ Return all strings matching 'pattern' (a regex or callable)
1126 """ Return all strings matching 'pattern' (a regex or callable)
1117
1127
1118 This is case-insensitive. If prune is true, return all items
1128 This is case-insensitive. If prune is true, return all items
1119 NOT matching the pattern.
1129 NOT matching the pattern.
1120
1130
1121 If field is specified, the match must occur in the specified
1131 If field is specified, the match must occur in the specified
1122 whitespace-separated field.
1132 whitespace-separated field.
1123
1133
1124 Examples::
1134 Examples::
1125
1135
1126 a.grep( lambda x: x.startswith('C') )
1136 a.grep( lambda x: x.startswith('C') )
1127 a.grep('Cha.*log', prune=1)
1137 a.grep('Cha.*log', prune=1)
1128 a.grep('chm', field=-1)
1138 a.grep('chm', field=-1)
1129 """
1139 """
1130
1140
1131 def match_target(s):
1141 def match_target(s):
1132 if field is None:
1142 if field is None:
1133 return s
1143 return s
1134 parts = s.split()
1144 parts = s.split()
1135 try:
1145 try:
1136 tgt = parts[field]
1146 tgt = parts[field]
1137 return tgt
1147 return tgt
1138 except IndexError:
1148 except IndexError:
1139 return ""
1149 return ""
1140
1150
1141 if isinstance(pattern, basestring):
1151 if isinstance(pattern, basestring):
1142 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
1152 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
1143 else:
1153 else:
1144 pred = pattern
1154 pred = pattern
1145 if not prune:
1155 if not prune:
1146 return SList([el for el in self if pred(match_target(el))])
1156 return SList([el for el in self if pred(match_target(el))])
1147 else:
1157 else:
1148 return SList([el for el in self if not pred(match_target(el))])
1158 return SList([el for el in self if not pred(match_target(el))])
1149 def fields(self, *fields):
1159 def fields(self, *fields):
1150 """ Collect whitespace-separated fields from string list
1160 """ Collect whitespace-separated fields from string list
1151
1161
1152 Allows quick awk-like usage of string lists.
1162 Allows quick awk-like usage of string lists.
1153
1163
1154 Example data (in var a, created by 'a = !ls -l')::
1164 Example data (in var a, created by 'a = !ls -l')::
1155 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
1165 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
1156 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
1166 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
1157
1167
1158 a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+']
1168 a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+']
1159 a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+']
1169 a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+']
1160 (note the joining by space).
1170 (note the joining by space).
1161 a.fields(-1) is ['ChangeLog', 'IPython']
1171 a.fields(-1) is ['ChangeLog', 'IPython']
1162
1172
1163 IndexErrors are ignored.
1173 IndexErrors are ignored.
1164
1174
1165 Without args, fields() just split()'s the strings.
1175 Without args, fields() just split()'s the strings.
1166 """
1176 """
1167 if len(fields) == 0:
1177 if len(fields) == 0:
1168 return [el.split() for el in self]
1178 return [el.split() for el in self]
1169
1179
1170 res = SList()
1180 res = SList()
1171 for el in [f.split() for f in self]:
1181 for el in [f.split() for f in self]:
1172 lineparts = []
1182 lineparts = []
1173
1183
1174 for fd in fields:
1184 for fd in fields:
1175 try:
1185 try:
1176 lineparts.append(el[fd])
1186 lineparts.append(el[fd])
1177 except IndexError:
1187 except IndexError:
1178 pass
1188 pass
1179 if lineparts:
1189 if lineparts:
1180 res.append(" ".join(lineparts))
1190 res.append(" ".join(lineparts))
1181
1191
1182 return res
1192 return res
1183 def sort(self,field= None, nums = False):
1193 def sort(self,field= None, nums = False):
1184 """ sort by specified fields (see fields())
1194 """ sort by specified fields (see fields())
1185
1195
1186 Example::
1196 Example::
1187 a.sort(1, nums = True)
1197 a.sort(1, nums = True)
1188
1198
1189 Sorts a by second field, in numerical order (so that 21 > 3)
1199 Sorts a by second field, in numerical order (so that 21 > 3)
1190
1200
1191 """
1201 """
1192
1202
1193 #decorate, sort, undecorate
1203 #decorate, sort, undecorate
1194 if field is not None:
1204 if field is not None:
1195 dsu = [[SList([line]).fields(field), line] for line in self]
1205 dsu = [[SList([line]).fields(field), line] for line in self]
1196 else:
1206 else:
1197 dsu = [[line, line] for line in self]
1207 dsu = [[line, line] for line in self]
1198 if nums:
1208 if nums:
1199 for i in range(len(dsu)):
1209 for i in range(len(dsu)):
1200 numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
1210 numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
1201 try:
1211 try:
1202 n = int(numstr)
1212 n = int(numstr)
1203 except ValueError:
1213 except ValueError:
1204 n = 0;
1214 n = 0;
1205 dsu[i][0] = n
1215 dsu[i][0] = n
1206
1216
1207
1217
1208 dsu.sort()
1218 dsu.sort()
1209 return SList([t[1] for t in dsu])
1219 return SList([t[1] for t in dsu])
1210
1220
1211 def print_slist(arg):
1221 def print_slist(arg):
1212 """ Prettier (non-repr-like) and more informative printer for SList """
1222 """ Prettier (non-repr-like) and more informative printer for SList """
1213 print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
1223 print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
1214 if hasattr(arg, 'hideonce') and arg.hideonce:
1224 if hasattr(arg, 'hideonce') and arg.hideonce:
1215 arg.hideonce = False
1225 arg.hideonce = False
1216 return
1226 return
1217
1227
1218 nlprint(arg)
1228 nlprint(arg)
1219
1229
1220 print_slist = result_display.when_type(SList)(print_slist)
1230 print_slist = result_display.when_type(SList)(print_slist)
1221
1231
1222
1232
1223
1233
1224 #----------------------------------------------------------------------------
1234 #----------------------------------------------------------------------------
1225 def esc_quotes(strng):
1235 def esc_quotes(strng):
1226 """Return the input string with single and double quotes escaped out"""
1236 """Return the input string with single and double quotes escaped out"""
1227
1237
1228 return strng.replace('"','\\"').replace("'","\\'")
1238 return strng.replace('"','\\"').replace("'","\\'")
1229
1239
1230 #----------------------------------------------------------------------------
1240 #----------------------------------------------------------------------------
1231 def make_quoted_expr(s):
1241 def make_quoted_expr(s):
1232 """Return string s in appropriate quotes, using raw string if possible.
1242 """Return string s in appropriate quotes, using raw string if possible.
1233
1243
1234 XXX - example removed because it caused encoding errors in documentation
1244 XXX - example removed because it caused encoding errors in documentation
1235 generation. We need a new example that doesn't contain invalid chars.
1245 generation. We need a new example that doesn't contain invalid chars.
1236
1246
1237 Note the use of raw string and padding at the end to allow trailing
1247 Note the use of raw string and padding at the end to allow trailing
1238 backslash.
1248 backslash.
1239 """
1249 """
1240
1250
1241 tail = ''
1251 tail = ''
1242 tailpadding = ''
1252 tailpadding = ''
1243 raw = ''
1253 raw = ''
1244 if "\\" in s:
1254 if "\\" in s:
1245 raw = 'r'
1255 raw = 'r'
1246 if s.endswith('\\'):
1256 if s.endswith('\\'):
1247 tail = '[:-1]'
1257 tail = '[:-1]'
1248 tailpadding = '_'
1258 tailpadding = '_'
1249 if '"' not in s:
1259 if '"' not in s:
1250 quote = '"'
1260 quote = '"'
1251 elif "'" not in s:
1261 elif "'" not in s:
1252 quote = "'"
1262 quote = "'"
1253 elif '"""' not in s and not s.endswith('"'):
1263 elif '"""' not in s and not s.endswith('"'):
1254 quote = '"""'
1264 quote = '"""'
1255 elif "'''" not in s and not s.endswith("'"):
1265 elif "'''" not in s and not s.endswith("'"):
1256 quote = "'''"
1266 quote = "'''"
1257 else:
1267 else:
1258 # give up, backslash-escaped string will do
1268 # give up, backslash-escaped string will do
1259 return '"%s"' % esc_quotes(s)
1269 return '"%s"' % esc_quotes(s)
1260 res = raw + quote + s + tailpadding + quote + tail
1270 res = raw + quote + s + tailpadding + quote + tail
1261 return res
1271 return res
1262
1272
1263
1273
1264 #----------------------------------------------------------------------------
1274 #----------------------------------------------------------------------------
1265 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
1275 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
1266 """Take multiple lines of input.
1276 """Take multiple lines of input.
1267
1277
1268 A list with each line of input as a separate element is returned when a
1278 A list with each line of input as a separate element is returned when a
1269 termination string is entered (defaults to a single '.'). Input can also
1279 termination string is entered (defaults to a single '.'). Input can also
1270 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1280 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1271
1281
1272 Lines of input which end in \\ are joined into single entries (and a
1282 Lines of input which end in \\ are joined into single entries (and a
1273 secondary continuation prompt is issued as long as the user terminates
1283 secondary continuation prompt is issued as long as the user terminates
1274 lines with \\). This allows entering very long strings which are still
1284 lines with \\). This allows entering very long strings which are still
1275 meant to be treated as single entities.
1285 meant to be treated as single entities.
1276 """
1286 """
1277
1287
1278 try:
1288 try:
1279 if header:
1289 if header:
1280 header += '\n'
1290 header += '\n'
1281 lines = [raw_input(header + ps1)]
1291 lines = [raw_input(header + ps1)]
1282 except EOFError:
1292 except EOFError:
1283 return []
1293 return []
1284 terminate = [terminate_str]
1294 terminate = [terminate_str]
1285 try:
1295 try:
1286 while lines[-1:] != terminate:
1296 while lines[-1:] != terminate:
1287 new_line = raw_input(ps1)
1297 new_line = raw_input(ps1)
1288 while new_line.endswith('\\'):
1298 while new_line.endswith('\\'):
1289 new_line = new_line[:-1] + raw_input(ps2)
1299 new_line = new_line[:-1] + raw_input(ps2)
1290 lines.append(new_line)
1300 lines.append(new_line)
1291
1301
1292 return lines[:-1] # don't return the termination command
1302 return lines[:-1] # don't return the termination command
1293 except EOFError:
1303 except EOFError:
1294 print
1304 print
1295 return lines
1305 return lines
1296
1306
1297 #----------------------------------------------------------------------------
1307 #----------------------------------------------------------------------------
1298 def raw_input_ext(prompt='', ps2='... '):
1308 def raw_input_ext(prompt='', ps2='... '):
1299 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1309 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1300
1310
1301 line = raw_input(prompt)
1311 line = raw_input(prompt)
1302 while line.endswith('\\'):
1312 while line.endswith('\\'):
1303 line = line[:-1] + raw_input(ps2)
1313 line = line[:-1] + raw_input(ps2)
1304 return line
1314 return line
1305
1315
1306 #----------------------------------------------------------------------------
1316 #----------------------------------------------------------------------------
1307 def ask_yes_no(prompt,default=None):
1317 def ask_yes_no(prompt,default=None):
1308 """Asks a question and returns a boolean (y/n) answer.
1318 """Asks a question and returns a boolean (y/n) answer.
1309
1319
1310 If default is given (one of 'y','n'), it is used if the user input is
1320 If default is given (one of 'y','n'), it is used if the user input is
1311 empty. Otherwise the question is repeated until an answer is given.
1321 empty. Otherwise the question is repeated until an answer is given.
1312
1322
1313 An EOF is treated as the default answer. If there is no default, an
1323 An EOF is treated as the default answer. If there is no default, an
1314 exception is raised to prevent infinite loops.
1324 exception is raised to prevent infinite loops.
1315
1325
1316 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1326 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1317
1327
1318 answers = {'y':True,'n':False,'yes':True,'no':False}
1328 answers = {'y':True,'n':False,'yes':True,'no':False}
1319 ans = None
1329 ans = None
1320 while ans not in answers.keys():
1330 while ans not in answers.keys():
1321 try:
1331 try:
1322 ans = raw_input(prompt+' ').lower()
1332 ans = raw_input(prompt+' ').lower()
1323 if not ans: # response was an empty string
1333 if not ans: # response was an empty string
1324 ans = default
1334 ans = default
1325 except KeyboardInterrupt:
1335 except KeyboardInterrupt:
1326 pass
1336 pass
1327 except EOFError:
1337 except EOFError:
1328 if default in answers.keys():
1338 if default in answers.keys():
1329 ans = default
1339 ans = default
1330 print
1340 print
1331 else:
1341 else:
1332 raise
1342 raise
1333
1343
1334 return answers[ans]
1344 return answers[ans]
1335
1345
1336 #----------------------------------------------------------------------------
1346 #----------------------------------------------------------------------------
1337 def marquee(txt='',width=78,mark='*'):
1347 def marquee(txt='',width=78,mark='*'):
1338 """Return the input string centered in a 'marquee'."""
1348 """Return the input string centered in a 'marquee'."""
1339 if not txt:
1349 if not txt:
1340 return (mark*width)[:width]
1350 return (mark*width)[:width]
1341 nmark = (width-len(txt)-2)/len(mark)/2
1351 nmark = (width-len(txt)-2)/len(mark)/2
1342 if nmark < 0: nmark =0
1352 if nmark < 0: nmark =0
1343 marks = mark*nmark
1353 marks = mark*nmark
1344 return '%s %s %s' % (marks,txt,marks)
1354 return '%s %s %s' % (marks,txt,marks)
1345
1355
1346 #----------------------------------------------------------------------------
1356 #----------------------------------------------------------------------------
1347 class EvalDict:
1357 class EvalDict:
1348 """
1358 """
1349 Emulate a dict which evaluates its contents in the caller's frame.
1359 Emulate a dict which evaluates its contents in the caller's frame.
1350
1360
1351 Usage:
1361 Usage:
1352 >>> number = 19
1362 >>> number = 19
1353
1363
1354 >>> text = "python"
1364 >>> text = "python"
1355
1365
1356 >>> print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1366 >>> print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1357 Python 2.1 rules!
1367 Python 2.1 rules!
1358 """
1368 """
1359
1369
1360 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1370 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1361 # modified (shorter) version of:
1371 # modified (shorter) version of:
1362 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1372 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1363 # Skip Montanaro (skip@pobox.com).
1373 # Skip Montanaro (skip@pobox.com).
1364
1374
1365 def __getitem__(self, name):
1375 def __getitem__(self, name):
1366 frame = sys._getframe(1)
1376 frame = sys._getframe(1)
1367 return eval(name, frame.f_globals, frame.f_locals)
1377 return eval(name, frame.f_globals, frame.f_locals)
1368
1378
1369 EvalString = EvalDict # for backwards compatibility
1379 EvalString = EvalDict # for backwards compatibility
1370 #----------------------------------------------------------------------------
1380 #----------------------------------------------------------------------------
1371 def qw(words,flat=0,sep=None,maxsplit=-1):
1381 def qw(words,flat=0,sep=None,maxsplit=-1):
1372 """Similar to Perl's qw() operator, but with some more options.
1382 """Similar to Perl's qw() operator, but with some more options.
1373
1383
1374 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1384 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1375
1385
1376 words can also be a list itself, and with flat=1, the output will be
1386 words can also be a list itself, and with flat=1, the output will be
1377 recursively flattened.
1387 recursively flattened.
1378
1388
1379 Examples:
1389 Examples:
1380
1390
1381 >>> qw('1 2')
1391 >>> qw('1 2')
1382 ['1', '2']
1392 ['1', '2']
1383
1393
1384 >>> qw(['a b','1 2',['m n','p q']])
1394 >>> qw(['a b','1 2',['m n','p q']])
1385 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1395 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1386
1396
1387 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1397 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1388 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q']
1398 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q']
1389 """
1399 """
1390
1400
1391 if type(words) in StringTypes:
1401 if type(words) in StringTypes:
1392 return [word.strip() for word in words.split(sep,maxsplit)
1402 return [word.strip() for word in words.split(sep,maxsplit)
1393 if word and not word.isspace() ]
1403 if word and not word.isspace() ]
1394 if flat:
1404 if flat:
1395 return flatten(map(qw,words,[1]*len(words)))
1405 return flatten(map(qw,words,[1]*len(words)))
1396 return map(qw,words)
1406 return map(qw,words)
1397
1407
1398 #----------------------------------------------------------------------------
1408 #----------------------------------------------------------------------------
1399 def qwflat(words,sep=None,maxsplit=-1):
1409 def qwflat(words,sep=None,maxsplit=-1):
1400 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1410 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1401 return qw(words,1,sep,maxsplit)
1411 return qw(words,1,sep,maxsplit)
1402
1412
1403 #----------------------------------------------------------------------------
1413 #----------------------------------------------------------------------------
1404 def qw_lol(indata):
1414 def qw_lol(indata):
1405 """qw_lol('a b') -> [['a','b']],
1415 """qw_lol('a b') -> [['a','b']],
1406 otherwise it's just a call to qw().
1416 otherwise it's just a call to qw().
1407
1417
1408 We need this to make sure the modules_some keys *always* end up as a
1418 We need this to make sure the modules_some keys *always* end up as a
1409 list of lists."""
1419 list of lists."""
1410
1420
1411 if type(indata) in StringTypes:
1421 if type(indata) in StringTypes:
1412 return [qw(indata)]
1422 return [qw(indata)]
1413 else:
1423 else:
1414 return qw(indata)
1424 return qw(indata)
1415
1425
1416 #-----------------------------------------------------------------------------
1426 #-----------------------------------------------------------------------------
1417 def list_strings(arg):
1427 def list_strings(arg):
1418 """Always return a list of strings, given a string or list of strings
1428 """Always return a list of strings, given a string or list of strings
1419 as input."""
1429 as input."""
1420
1430
1421 if type(arg) in StringTypes: return [arg]
1431 if type(arg) in StringTypes: return [arg]
1422 else: return arg
1432 else: return arg
1423
1433
1424 #----------------------------------------------------------------------------
1434 #----------------------------------------------------------------------------
1425 def grep(pat,list,case=1):
1435 def grep(pat,list,case=1):
1426 """Simple minded grep-like function.
1436 """Simple minded grep-like function.
1427 grep(pat,list) returns occurrences of pat in list, None on failure.
1437 grep(pat,list) returns occurrences of pat in list, None on failure.
1428
1438
1429 It only does simple string matching, with no support for regexps. Use the
1439 It only does simple string matching, with no support for regexps. Use the
1430 option case=0 for case-insensitive matching."""
1440 option case=0 for case-insensitive matching."""
1431
1441
1432 # This is pretty crude. At least it should implement copying only references
1442 # This is pretty crude. At least it should implement copying only references
1433 # to the original data in case it's big. Now it copies the data for output.
1443 # to the original data in case it's big. Now it copies the data for output.
1434 out=[]
1444 out=[]
1435 if case:
1445 if case:
1436 for term in list:
1446 for term in list:
1437 if term.find(pat)>-1: out.append(term)
1447 if term.find(pat)>-1: out.append(term)
1438 else:
1448 else:
1439 lpat=pat.lower()
1449 lpat=pat.lower()
1440 for term in list:
1450 for term in list:
1441 if term.lower().find(lpat)>-1: out.append(term)
1451 if term.lower().find(lpat)>-1: out.append(term)
1442
1452
1443 if len(out): return out
1453 if len(out): return out
1444 else: return None
1454 else: return None
1445
1455
1446 #----------------------------------------------------------------------------
1456 #----------------------------------------------------------------------------
1447 def dgrep(pat,*opts):
1457 def dgrep(pat,*opts):
1448 """Return grep() on dir()+dir(__builtins__).
1458 """Return grep() on dir()+dir(__builtins__).
1449
1459
1450 A very common use of grep() when working interactively."""
1460 A very common use of grep() when working interactively."""
1451
1461
1452 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1462 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1453
1463
1454 #----------------------------------------------------------------------------
1464 #----------------------------------------------------------------------------
1455 def idgrep(pat):
1465 def idgrep(pat):
1456 """Case-insensitive dgrep()"""
1466 """Case-insensitive dgrep()"""
1457
1467
1458 return dgrep(pat,0)
1468 return dgrep(pat,0)
1459
1469
1460 #----------------------------------------------------------------------------
1470 #----------------------------------------------------------------------------
1461 def igrep(pat,list):
1471 def igrep(pat,list):
1462 """Synonym for case-insensitive grep."""
1472 """Synonym for case-insensitive grep."""
1463
1473
1464 return grep(pat,list,case=0)
1474 return grep(pat,list,case=0)
1465
1475
1466 #----------------------------------------------------------------------------
1476 #----------------------------------------------------------------------------
1467 def indent(str,nspaces=4,ntabs=0):
1477 def indent(str,nspaces=4,ntabs=0):
1468 """Indent a string a given number of spaces or tabstops.
1478 """Indent a string a given number of spaces or tabstops.
1469
1479
1470 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1480 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1471 """
1481 """
1472 if str is None:
1482 if str is None:
1473 return
1483 return
1474 ind = '\t'*ntabs+' '*nspaces
1484 ind = '\t'*ntabs+' '*nspaces
1475 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1485 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1476 if outstr.endswith(os.linesep+ind):
1486 if outstr.endswith(os.linesep+ind):
1477 return outstr[:-len(ind)]
1487 return outstr[:-len(ind)]
1478 else:
1488 else:
1479 return outstr
1489 return outstr
1480
1490
1481 #-----------------------------------------------------------------------------
1491 #-----------------------------------------------------------------------------
1482 def native_line_ends(filename,backup=1):
1492 def native_line_ends(filename,backup=1):
1483 """Convert (in-place) a file to line-ends native to the current OS.
1493 """Convert (in-place) a file to line-ends native to the current OS.
1484
1494
1485 If the optional backup argument is given as false, no backup of the
1495 If the optional backup argument is given as false, no backup of the
1486 original file is left. """
1496 original file is left. """
1487
1497
1488 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1498 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1489
1499
1490 bak_filename = filename + backup_suffixes[os.name]
1500 bak_filename = filename + backup_suffixes[os.name]
1491
1501
1492 original = open(filename).read()
1502 original = open(filename).read()
1493 shutil.copy2(filename,bak_filename)
1503 shutil.copy2(filename,bak_filename)
1494 try:
1504 try:
1495 new = open(filename,'wb')
1505 new = open(filename,'wb')
1496 new.write(os.linesep.join(original.splitlines()))
1506 new.write(os.linesep.join(original.splitlines()))
1497 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1507 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1498 new.close()
1508 new.close()
1499 except:
1509 except:
1500 os.rename(bak_filename,filename)
1510 os.rename(bak_filename,filename)
1501 if not backup:
1511 if not backup:
1502 try:
1512 try:
1503 os.remove(bak_filename)
1513 os.remove(bak_filename)
1504 except:
1514 except:
1505 pass
1515 pass
1506
1516
1507 #----------------------------------------------------------------------------
1517 #----------------------------------------------------------------------------
1508 def get_pager_cmd(pager_cmd = None):
1518 def get_pager_cmd(pager_cmd = None):
1509 """Return a pager command.
1519 """Return a pager command.
1510
1520
1511 Makes some attempts at finding an OS-correct one."""
1521 Makes some attempts at finding an OS-correct one."""
1512
1522
1513 if os.name == 'posix':
1523 if os.name == 'posix':
1514 default_pager_cmd = 'less -r' # -r for color control sequences
1524 default_pager_cmd = 'less -r' # -r for color control sequences
1515 elif os.name in ['nt','dos']:
1525 elif os.name in ['nt','dos']:
1516 default_pager_cmd = 'type'
1526 default_pager_cmd = 'type'
1517
1527
1518 if pager_cmd is None:
1528 if pager_cmd is None:
1519 try:
1529 try:
1520 pager_cmd = os.environ['PAGER']
1530 pager_cmd = os.environ['PAGER']
1521 except:
1531 except:
1522 pager_cmd = default_pager_cmd
1532 pager_cmd = default_pager_cmd
1523 return pager_cmd
1533 return pager_cmd
1524
1534
1525 #-----------------------------------------------------------------------------
1535 #-----------------------------------------------------------------------------
1526 def get_pager_start(pager,start):
1536 def get_pager_start(pager,start):
1527 """Return the string for paging files with an offset.
1537 """Return the string for paging files with an offset.
1528
1538
1529 This is the '+N' argument which less and more (under Unix) accept.
1539 This is the '+N' argument which less and more (under Unix) accept.
1530 """
1540 """
1531
1541
1532 if pager in ['less','more']:
1542 if pager in ['less','more']:
1533 if start:
1543 if start:
1534 start_string = '+' + str(start)
1544 start_string = '+' + str(start)
1535 else:
1545 else:
1536 start_string = ''
1546 start_string = ''
1537 else:
1547 else:
1538 start_string = ''
1548 start_string = ''
1539 return start_string
1549 return start_string
1540
1550
1541 #----------------------------------------------------------------------------
1551 #----------------------------------------------------------------------------
1542 # (X)emacs on W32 doesn't like to be bypassed with msvcrt.getch()
1552 # (X)emacs on W32 doesn't like to be bypassed with msvcrt.getch()
1543 if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs':
1553 if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs':
1544 import msvcrt
1554 import msvcrt
1545 def page_more():
1555 def page_more():
1546 """ Smart pausing between pages
1556 """ Smart pausing between pages
1547
1557
1548 @return: True if need print more lines, False if quit
1558 @return: True if need print more lines, False if quit
1549 """
1559 """
1550 Term.cout.write('---Return to continue, q to quit--- ')
1560 Term.cout.write('---Return to continue, q to quit--- ')
1551 ans = msvcrt.getch()
1561 ans = msvcrt.getch()
1552 if ans in ("q", "Q"):
1562 if ans in ("q", "Q"):
1553 result = False
1563 result = False
1554 else:
1564 else:
1555 result = True
1565 result = True
1556 Term.cout.write("\b"*37 + " "*37 + "\b"*37)
1566 Term.cout.write("\b"*37 + " "*37 + "\b"*37)
1557 return result
1567 return result
1558 else:
1568 else:
1559 def page_more():
1569 def page_more():
1560 ans = raw_input('---Return to continue, q to quit--- ')
1570 ans = raw_input('---Return to continue, q to quit--- ')
1561 if ans.lower().startswith('q'):
1571 if ans.lower().startswith('q'):
1562 return False
1572 return False
1563 else:
1573 else:
1564 return True
1574 return True
1565
1575
1566 esc_re = re.compile(r"(\x1b[^m]+m)")
1576 esc_re = re.compile(r"(\x1b[^m]+m)")
1567
1577
1568 def page_dumb(strng,start=0,screen_lines=25):
1578 def page_dumb(strng,start=0,screen_lines=25):
1569 """Very dumb 'pager' in Python, for when nothing else works.
1579 """Very dumb 'pager' in Python, for when nothing else works.
1570
1580
1571 Only moves forward, same interface as page(), except for pager_cmd and
1581 Only moves forward, same interface as page(), except for pager_cmd and
1572 mode."""
1582 mode."""
1573
1583
1574 out_ln = strng.splitlines()[start:]
1584 out_ln = strng.splitlines()[start:]
1575 screens = chop(out_ln,screen_lines-1)
1585 screens = chop(out_ln,screen_lines-1)
1576 if len(screens) == 1:
1586 if len(screens) == 1:
1577 print >>Term.cout, os.linesep.join(screens[0])
1587 print >>Term.cout, os.linesep.join(screens[0])
1578 else:
1588 else:
1579 last_escape = ""
1589 last_escape = ""
1580 for scr in screens[0:-1]:
1590 for scr in screens[0:-1]:
1581 hunk = os.linesep.join(scr)
1591 hunk = os.linesep.join(scr)
1582 print >>Term.cout, last_escape + hunk
1592 print >>Term.cout, last_escape + hunk
1583 if not page_more():
1593 if not page_more():
1584 return
1594 return
1585 esc_list = esc_re.findall(hunk)
1595 esc_list = esc_re.findall(hunk)
1586 if len(esc_list) > 0:
1596 if len(esc_list) > 0:
1587 last_escape = esc_list[-1]
1597 last_escape = esc_list[-1]
1588 print >>Term.cout, last_escape + os.linesep.join(screens[-1])
1598 print >>Term.cout, last_escape + os.linesep.join(screens[-1])
1589
1599
1590 #----------------------------------------------------------------------------
1600 #----------------------------------------------------------------------------
1591 def page(strng,start=0,screen_lines=0,pager_cmd = None):
1601 def page(strng,start=0,screen_lines=0,pager_cmd = None):
1592 """Print a string, piping through a pager after a certain length.
1602 """Print a string, piping through a pager after a certain length.
1593
1603
1594 The screen_lines parameter specifies the number of *usable* lines of your
1604 The screen_lines parameter specifies the number of *usable* lines of your
1595 terminal screen (total lines minus lines you need to reserve to show other
1605 terminal screen (total lines minus lines you need to reserve to show other
1596 information).
1606 information).
1597
1607
1598 If you set screen_lines to a number <=0, page() will try to auto-determine
1608 If you set screen_lines to a number <=0, page() will try to auto-determine
1599 your screen size and will only use up to (screen_size+screen_lines) for
1609 your screen size and will only use up to (screen_size+screen_lines) for
1600 printing, paging after that. That is, if you want auto-detection but need
1610 printing, paging after that. That is, if you want auto-detection but need
1601 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
1611 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
1602 auto-detection without any lines reserved simply use screen_lines = 0.
1612 auto-detection without any lines reserved simply use screen_lines = 0.
1603
1613
1604 If a string won't fit in the allowed lines, it is sent through the
1614 If a string won't fit in the allowed lines, it is sent through the
1605 specified pager command. If none given, look for PAGER in the environment,
1615 specified pager command. If none given, look for PAGER in the environment,
1606 and ultimately default to less.
1616 and ultimately default to less.
1607
1617
1608 If no system pager works, the string is sent through a 'dumb pager'
1618 If no system pager works, the string is sent through a 'dumb pager'
1609 written in python, very simplistic.
1619 written in python, very simplistic.
1610 """
1620 """
1611
1621
1612 # Some routines may auto-compute start offsets incorrectly and pass a
1622 # Some routines may auto-compute start offsets incorrectly and pass a
1613 # negative value. Offset to 0 for robustness.
1623 # negative value. Offset to 0 for robustness.
1614 start = max(0,start)
1624 start = max(0,start)
1615
1625
1616 # first, try the hook
1626 # first, try the hook
1617 ip = IPython.ipapi.get()
1627 ip = IPython.ipapi.get()
1618 if ip:
1628 if ip:
1619 try:
1629 try:
1620 ip.IP.hooks.show_in_pager(strng)
1630 ip.IP.hooks.show_in_pager(strng)
1621 return
1631 return
1622 except IPython.ipapi.TryNext:
1632 except IPython.ipapi.TryNext:
1623 pass
1633 pass
1624
1634
1625 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
1635 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
1626 TERM = os.environ.get('TERM','dumb')
1636 TERM = os.environ.get('TERM','dumb')
1627 if TERM in ['dumb','emacs'] and os.name != 'nt':
1637 if TERM in ['dumb','emacs'] and os.name != 'nt':
1628 print strng
1638 print strng
1629 return
1639 return
1630 # chop off the topmost part of the string we don't want to see
1640 # chop off the topmost part of the string we don't want to see
1631 str_lines = strng.split(os.linesep)[start:]
1641 str_lines = strng.split(os.linesep)[start:]
1632 str_toprint = os.linesep.join(str_lines)
1642 str_toprint = os.linesep.join(str_lines)
1633 num_newlines = len(str_lines)
1643 num_newlines = len(str_lines)
1634 len_str = len(str_toprint)
1644 len_str = len(str_toprint)
1635
1645
1636 # Dumb heuristics to guesstimate number of on-screen lines the string
1646 # Dumb heuristics to guesstimate number of on-screen lines the string
1637 # takes. Very basic, but good enough for docstrings in reasonable
1647 # takes. Very basic, but good enough for docstrings in reasonable
1638 # terminals. If someone later feels like refining it, it's not hard.
1648 # terminals. If someone later feels like refining it, it's not hard.
1639 numlines = max(num_newlines,int(len_str/80)+1)
1649 numlines = max(num_newlines,int(len_str/80)+1)
1640
1650
1641 if os.name == "nt":
1651 if os.name == "nt":
1642 screen_lines_def = get_console_size(defaulty=25)[1]
1652 screen_lines_def = get_console_size(defaulty=25)[1]
1643 else:
1653 else:
1644 screen_lines_def = 25 # default value if we can't auto-determine
1654 screen_lines_def = 25 # default value if we can't auto-determine
1645
1655
1646 # auto-determine screen size
1656 # auto-determine screen size
1647 if screen_lines <= 0:
1657 if screen_lines <= 0:
1648 if TERM=='xterm':
1658 if TERM=='xterm':
1649 use_curses = USE_CURSES
1659 use_curses = USE_CURSES
1650 else:
1660 else:
1651 # curses causes problems on many terminals other than xterm.
1661 # curses causes problems on many terminals other than xterm.
1652 use_curses = False
1662 use_curses = False
1653 if use_curses:
1663 if use_curses:
1654 # There is a bug in curses, where *sometimes* it fails to properly
1664 # There is a bug in curses, where *sometimes* it fails to properly
1655 # initialize, and then after the endwin() call is made, the
1665 # initialize, and then after the endwin() call is made, the
1656 # terminal is left in an unusable state. Rather than trying to
1666 # terminal is left in an unusable state. Rather than trying to
1657 # check everytime for this (by requesting and comparing termios
1667 # check everytime for this (by requesting and comparing termios
1658 # flags each time), we just save the initial terminal state and
1668 # flags each time), we just save the initial terminal state and
1659 # unconditionally reset it every time. It's cheaper than making
1669 # unconditionally reset it every time. It's cheaper than making
1660 # the checks.
1670 # the checks.
1661 term_flags = termios.tcgetattr(sys.stdout)
1671 term_flags = termios.tcgetattr(sys.stdout)
1662 scr = curses.initscr()
1672 scr = curses.initscr()
1663 screen_lines_real,screen_cols = scr.getmaxyx()
1673 screen_lines_real,screen_cols = scr.getmaxyx()
1664 curses.endwin()
1674 curses.endwin()
1665 # Restore terminal state in case endwin() didn't.
1675 # Restore terminal state in case endwin() didn't.
1666 termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
1676 termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
1667 # Now we have what we needed: the screen size in rows/columns
1677 # Now we have what we needed: the screen size in rows/columns
1668 screen_lines += screen_lines_real
1678 screen_lines += screen_lines_real
1669 #print '***Screen size:',screen_lines_real,'lines x',\
1679 #print '***Screen size:',screen_lines_real,'lines x',\
1670 #screen_cols,'columns.' # dbg
1680 #screen_cols,'columns.' # dbg
1671 else:
1681 else:
1672 screen_lines += screen_lines_def
1682 screen_lines += screen_lines_def
1673
1683
1674 #print 'numlines',numlines,'screenlines',screen_lines # dbg
1684 #print 'numlines',numlines,'screenlines',screen_lines # dbg
1675 if numlines <= screen_lines :
1685 if numlines <= screen_lines :
1676 #print '*** normal print' # dbg
1686 #print '*** normal print' # dbg
1677 print >>Term.cout, str_toprint
1687 print >>Term.cout, str_toprint
1678 else:
1688 else:
1679 # Try to open pager and default to internal one if that fails.
1689 # Try to open pager and default to internal one if that fails.
1680 # All failure modes are tagged as 'retval=1', to match the return
1690 # All failure modes are tagged as 'retval=1', to match the return
1681 # value of a failed system command. If any intermediate attempt
1691 # value of a failed system command. If any intermediate attempt
1682 # sets retval to 1, at the end we resort to our own page_dumb() pager.
1692 # sets retval to 1, at the end we resort to our own page_dumb() pager.
1683 pager_cmd = get_pager_cmd(pager_cmd)
1693 pager_cmd = get_pager_cmd(pager_cmd)
1684 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1694 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1685 if os.name == 'nt':
1695 if os.name == 'nt':
1686 if pager_cmd.startswith('type'):
1696 if pager_cmd.startswith('type'):
1687 # The default WinXP 'type' command is failing on complex strings.
1697 # The default WinXP 'type' command is failing on complex strings.
1688 retval = 1
1698 retval = 1
1689 else:
1699 else:
1690 tmpname = tempfile.mktemp('.txt')
1700 tmpname = tempfile.mktemp('.txt')
1691 tmpfile = file(tmpname,'wt')
1701 tmpfile = file(tmpname,'wt')
1692 tmpfile.write(strng)
1702 tmpfile.write(strng)
1693 tmpfile.close()
1703 tmpfile.close()
1694 cmd = "%s < %s" % (pager_cmd,tmpname)
1704 cmd = "%s < %s" % (pager_cmd,tmpname)
1695 if os.system(cmd):
1705 if os.system(cmd):
1696 retval = 1
1706 retval = 1
1697 else:
1707 else:
1698 retval = None
1708 retval = None
1699 os.remove(tmpname)
1709 os.remove(tmpname)
1700 else:
1710 else:
1701 try:
1711 try:
1702 retval = None
1712 retval = None
1703 # if I use popen4, things hang. No idea why.
1713 # if I use popen4, things hang. No idea why.
1704 #pager,shell_out = os.popen4(pager_cmd)
1714 #pager,shell_out = os.popen4(pager_cmd)
1705 pager = os.popen(pager_cmd,'w')
1715 pager = os.popen(pager_cmd,'w')
1706 pager.write(strng)
1716 pager.write(strng)
1707 pager.close()
1717 pager.close()
1708 retval = pager.close() # success returns None
1718 retval = pager.close() # success returns None
1709 except IOError,msg: # broken pipe when user quits
1719 except IOError,msg: # broken pipe when user quits
1710 if msg.args == (32,'Broken pipe'):
1720 if msg.args == (32,'Broken pipe'):
1711 retval = None
1721 retval = None
1712 else:
1722 else:
1713 retval = 1
1723 retval = 1
1714 except OSError:
1724 except OSError:
1715 # Other strange problems, sometimes seen in Win2k/cygwin
1725 # Other strange problems, sometimes seen in Win2k/cygwin
1716 retval = 1
1726 retval = 1
1717 if retval is not None:
1727 if retval is not None:
1718 page_dumb(strng,screen_lines=screen_lines)
1728 page_dumb(strng,screen_lines=screen_lines)
1719
1729
1720 #----------------------------------------------------------------------------
1730 #----------------------------------------------------------------------------
1721 def page_file(fname,start = 0, pager_cmd = None):
1731 def page_file(fname,start = 0, pager_cmd = None):
1722 """Page a file, using an optional pager command and starting line.
1732 """Page a file, using an optional pager command and starting line.
1723 """
1733 """
1724
1734
1725 pager_cmd = get_pager_cmd(pager_cmd)
1735 pager_cmd = get_pager_cmd(pager_cmd)
1726 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1736 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1727
1737
1728 try:
1738 try:
1729 if os.environ['TERM'] in ['emacs','dumb']:
1739 if os.environ['TERM'] in ['emacs','dumb']:
1730 raise EnvironmentError
1740 raise EnvironmentError
1731 xsys(pager_cmd + ' ' + fname)
1741 xsys(pager_cmd + ' ' + fname)
1732 except:
1742 except:
1733 try:
1743 try:
1734 if start > 0:
1744 if start > 0:
1735 start -= 1
1745 start -= 1
1736 page(open(fname).read(),start)
1746 page(open(fname).read(),start)
1737 except:
1747 except:
1738 print 'Unable to show file',`fname`
1748 print 'Unable to show file',`fname`
1739
1749
1740
1750
1741 #----------------------------------------------------------------------------
1751 #----------------------------------------------------------------------------
1742 def snip_print(str,width = 75,print_full = 0,header = ''):
1752 def snip_print(str,width = 75,print_full = 0,header = ''):
1743 """Print a string snipping the midsection to fit in width.
1753 """Print a string snipping the midsection to fit in width.
1744
1754
1745 print_full: mode control:
1755 print_full: mode control:
1746 - 0: only snip long strings
1756 - 0: only snip long strings
1747 - 1: send to page() directly.
1757 - 1: send to page() directly.
1748 - 2: snip long strings and ask for full length viewing with page()
1758 - 2: snip long strings and ask for full length viewing with page()
1749 Return 1 if snipping was necessary, 0 otherwise."""
1759 Return 1 if snipping was necessary, 0 otherwise."""
1750
1760
1751 if print_full == 1:
1761 if print_full == 1:
1752 page(header+str)
1762 page(header+str)
1753 return 0
1763 return 0
1754
1764
1755 print header,
1765 print header,
1756 if len(str) < width:
1766 if len(str) < width:
1757 print str
1767 print str
1758 snip = 0
1768 snip = 0
1759 else:
1769 else:
1760 whalf = int((width -5)/2)
1770 whalf = int((width -5)/2)
1761 print str[:whalf] + ' <...> ' + str[-whalf:]
1771 print str[:whalf] + ' <...> ' + str[-whalf:]
1762 snip = 1
1772 snip = 1
1763 if snip and print_full == 2:
1773 if snip and print_full == 2:
1764 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
1774 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
1765 page(str)
1775 page(str)
1766 return snip
1776 return snip
1767
1777
1768 #****************************************************************************
1778 #****************************************************************************
1769 # lists, dicts and structures
1779 # lists, dicts and structures
1770
1780
1771 def belong(candidates,checklist):
1781 def belong(candidates,checklist):
1772 """Check whether a list of items appear in a given list of options.
1782 """Check whether a list of items appear in a given list of options.
1773
1783
1774 Returns a list of 1 and 0, one for each candidate given."""
1784 Returns a list of 1 and 0, one for each candidate given."""
1775
1785
1776 return [x in checklist for x in candidates]
1786 return [x in checklist for x in candidates]
1777
1787
1778 #----------------------------------------------------------------------------
1788 #----------------------------------------------------------------------------
1779 def uniq_stable(elems):
1789 def uniq_stable(elems):
1780 """uniq_stable(elems) -> list
1790 """uniq_stable(elems) -> list
1781
1791
1782 Return from an iterable, a list of all the unique elements in the input,
1792 Return from an iterable, a list of all the unique elements in the input,
1783 but maintaining the order in which they first appear.
1793 but maintaining the order in which they first appear.
1784
1794
1785 A naive solution to this problem which just makes a dictionary with the
1795 A naive solution to this problem which just makes a dictionary with the
1786 elements as keys fails to respect the stability condition, since
1796 elements as keys fails to respect the stability condition, since
1787 dictionaries are unsorted by nature.
1797 dictionaries are unsorted by nature.
1788
1798
1789 Note: All elements in the input must be valid dictionary keys for this
1799 Note: All elements in the input must be valid dictionary keys for this
1790 routine to work, as it internally uses a dictionary for efficiency
1800 routine to work, as it internally uses a dictionary for efficiency
1791 reasons."""
1801 reasons."""
1792
1802
1793 unique = []
1803 unique = []
1794 unique_dict = {}
1804 unique_dict = {}
1795 for nn in elems:
1805 for nn in elems:
1796 if nn not in unique_dict:
1806 if nn not in unique_dict:
1797 unique.append(nn)
1807 unique.append(nn)
1798 unique_dict[nn] = None
1808 unique_dict[nn] = None
1799 return unique
1809 return unique
1800
1810
1801 #----------------------------------------------------------------------------
1811 #----------------------------------------------------------------------------
1802 class NLprinter:
1812 class NLprinter:
1803 """Print an arbitrarily nested list, indicating index numbers.
1813 """Print an arbitrarily nested list, indicating index numbers.
1804
1814
1805 An instance of this class called nlprint is available and callable as a
1815 An instance of this class called nlprint is available and callable as a
1806 function.
1816 function.
1807
1817
1808 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1818 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1809 and using 'sep' to separate the index from the value. """
1819 and using 'sep' to separate the index from the value. """
1810
1820
1811 def __init__(self):
1821 def __init__(self):
1812 self.depth = 0
1822 self.depth = 0
1813
1823
1814 def __call__(self,lst,pos='',**kw):
1824 def __call__(self,lst,pos='',**kw):
1815 """Prints the nested list numbering levels."""
1825 """Prints the nested list numbering levels."""
1816 kw.setdefault('indent',' ')
1826 kw.setdefault('indent',' ')
1817 kw.setdefault('sep',': ')
1827 kw.setdefault('sep',': ')
1818 kw.setdefault('start',0)
1828 kw.setdefault('start',0)
1819 kw.setdefault('stop',len(lst))
1829 kw.setdefault('stop',len(lst))
1820 # we need to remove start and stop from kw so they don't propagate
1830 # we need to remove start and stop from kw so they don't propagate
1821 # into a recursive call for a nested list.
1831 # into a recursive call for a nested list.
1822 start = kw['start']; del kw['start']
1832 start = kw['start']; del kw['start']
1823 stop = kw['stop']; del kw['stop']
1833 stop = kw['stop']; del kw['stop']
1824 if self.depth == 0 and 'header' in kw.keys():
1834 if self.depth == 0 and 'header' in kw.keys():
1825 print kw['header']
1835 print kw['header']
1826
1836
1827 for idx in range(start,stop):
1837 for idx in range(start,stop):
1828 elem = lst[idx]
1838 elem = lst[idx]
1829 if type(elem)==type([]):
1839 if type(elem)==type([]):
1830 self.depth += 1
1840 self.depth += 1
1831 self.__call__(elem,itpl('$pos$idx,'),**kw)
1841 self.__call__(elem,itpl('$pos$idx,'),**kw)
1832 self.depth -= 1
1842 self.depth -= 1
1833 else:
1843 else:
1834 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1844 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1835
1845
1836 nlprint = NLprinter()
1846 nlprint = NLprinter()
1837 #----------------------------------------------------------------------------
1847 #----------------------------------------------------------------------------
1838 def all_belong(candidates,checklist):
1848 def all_belong(candidates,checklist):
1839 """Check whether a list of items ALL appear in a given list of options.
1849 """Check whether a list of items ALL appear in a given list of options.
1840
1850
1841 Returns a single 1 or 0 value."""
1851 Returns a single 1 or 0 value."""
1842
1852
1843 return 1-(0 in [x in checklist for x in candidates])
1853 return 1-(0 in [x in checklist for x in candidates])
1844
1854
1845 #----------------------------------------------------------------------------
1855 #----------------------------------------------------------------------------
1846 def sort_compare(lst1,lst2,inplace = 1):
1856 def sort_compare(lst1,lst2,inplace = 1):
1847 """Sort and compare two lists.
1857 """Sort and compare two lists.
1848
1858
1849 By default it does it in place, thus modifying the lists. Use inplace = 0
1859 By default it does it in place, thus modifying the lists. Use inplace = 0
1850 to avoid that (at the cost of temporary copy creation)."""
1860 to avoid that (at the cost of temporary copy creation)."""
1851 if not inplace:
1861 if not inplace:
1852 lst1 = lst1[:]
1862 lst1 = lst1[:]
1853 lst2 = lst2[:]
1863 lst2 = lst2[:]
1854 lst1.sort(); lst2.sort()
1864 lst1.sort(); lst2.sort()
1855 return lst1 == lst2
1865 return lst1 == lst2
1856
1866
1857 #----------------------------------------------------------------------------
1867 #----------------------------------------------------------------------------
1858 def list2dict(lst):
1868 def list2dict(lst):
1859 """Takes a list of (key,value) pairs and turns it into a dict."""
1869 """Takes a list of (key,value) pairs and turns it into a dict."""
1860
1870
1861 dic = {}
1871 dic = {}
1862 for k,v in lst: dic[k] = v
1872 for k,v in lst: dic[k] = v
1863 return dic
1873 return dic
1864
1874
1865 #----------------------------------------------------------------------------
1875 #----------------------------------------------------------------------------
1866 def list2dict2(lst,default=''):
1876 def list2dict2(lst,default=''):
1867 """Takes a list and turns it into a dict.
1877 """Takes a list and turns it into a dict.
1868 Much slower than list2dict, but more versatile. This version can take
1878 Much slower than list2dict, but more versatile. This version can take
1869 lists with sublists of arbitrary length (including sclars)."""
1879 lists with sublists of arbitrary length (including sclars)."""
1870
1880
1871 dic = {}
1881 dic = {}
1872 for elem in lst:
1882 for elem in lst:
1873 if type(elem) in (types.ListType,types.TupleType):
1883 if type(elem) in (types.ListType,types.TupleType):
1874 size = len(elem)
1884 size = len(elem)
1875 if size == 0:
1885 if size == 0:
1876 pass
1886 pass
1877 elif size == 1:
1887 elif size == 1:
1878 dic[elem] = default
1888 dic[elem] = default
1879 else:
1889 else:
1880 k,v = elem[0], elem[1:]
1890 k,v = elem[0], elem[1:]
1881 if len(v) == 1: v = v[0]
1891 if len(v) == 1: v = v[0]
1882 dic[k] = v
1892 dic[k] = v
1883 else:
1893 else:
1884 dic[elem] = default
1894 dic[elem] = default
1885 return dic
1895 return dic
1886
1896
1887 #----------------------------------------------------------------------------
1897 #----------------------------------------------------------------------------
1888 def flatten(seq):
1898 def flatten(seq):
1889 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1899 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1890
1900
1891 return [x for subseq in seq for x in subseq]
1901 return [x for subseq in seq for x in subseq]
1892
1902
1893 #----------------------------------------------------------------------------
1903 #----------------------------------------------------------------------------
1894 def get_slice(seq,start=0,stop=None,step=1):
1904 def get_slice(seq,start=0,stop=None,step=1):
1895 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1905 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1896 if stop == None:
1906 if stop == None:
1897 stop = len(seq)
1907 stop = len(seq)
1898 item = lambda i: seq[i]
1908 item = lambda i: seq[i]
1899 return map(item,xrange(start,stop,step))
1909 return map(item,xrange(start,stop,step))
1900
1910
1901 #----------------------------------------------------------------------------
1911 #----------------------------------------------------------------------------
1902 def chop(seq,size):
1912 def chop(seq,size):
1903 """Chop a sequence into chunks of the given size."""
1913 """Chop a sequence into chunks of the given size."""
1904 chunk = lambda i: seq[i:i+size]
1914 chunk = lambda i: seq[i:i+size]
1905 return map(chunk,xrange(0,len(seq),size))
1915 return map(chunk,xrange(0,len(seq),size))
1906
1916
1907 #----------------------------------------------------------------------------
1917 #----------------------------------------------------------------------------
1908 # with is a keyword as of python 2.5, so this function is renamed to withobj
1918 # with is a keyword as of python 2.5, so this function is renamed to withobj
1909 # from its old 'with' name.
1919 # from its old 'with' name.
1910 def with_obj(object, **args):
1920 def with_obj(object, **args):
1911 """Set multiple attributes for an object, similar to Pascal's with.
1921 """Set multiple attributes for an object, similar to Pascal's with.
1912
1922
1913 Example:
1923 Example:
1914 with_obj(jim,
1924 with_obj(jim,
1915 born = 1960,
1925 born = 1960,
1916 haircolour = 'Brown',
1926 haircolour = 'Brown',
1917 eyecolour = 'Green')
1927 eyecolour = 'Green')
1918
1928
1919 Credit: Greg Ewing, in
1929 Credit: Greg Ewing, in
1920 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1930 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1921
1931
1922 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1932 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1923 has become a keyword for Python 2.5, so we had to rename it."""
1933 has become a keyword for Python 2.5, so we had to rename it."""
1924
1934
1925 object.__dict__.update(args)
1935 object.__dict__.update(args)
1926
1936
1927 #----------------------------------------------------------------------------
1937 #----------------------------------------------------------------------------
1928 def setattr_list(obj,alist,nspace = None):
1938 def setattr_list(obj,alist,nspace = None):
1929 """Set a list of attributes for an object taken from a namespace.
1939 """Set a list of attributes for an object taken from a namespace.
1930
1940
1931 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1941 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1932 alist with their values taken from nspace, which must be a dict (something
1942 alist with their values taken from nspace, which must be a dict (something
1933 like locals() will often do) If nspace isn't given, locals() of the
1943 like locals() will often do) If nspace isn't given, locals() of the
1934 *caller* is used, so in most cases you can omit it.
1944 *caller* is used, so in most cases you can omit it.
1935
1945
1936 Note that alist can be given as a string, which will be automatically
1946 Note that alist can be given as a string, which will be automatically
1937 split into a list on whitespace. If given as a list, it must be a list of
1947 split into a list on whitespace. If given as a list, it must be a list of
1938 *strings* (the variable names themselves), not of variables."""
1948 *strings* (the variable names themselves), not of variables."""
1939
1949
1940 # this grabs the local variables from the *previous* call frame -- that is
1950 # this grabs the local variables from the *previous* call frame -- that is
1941 # the locals from the function that called setattr_list().
1951 # the locals from the function that called setattr_list().
1942 # - snipped from weave.inline()
1952 # - snipped from weave.inline()
1943 if nspace is None:
1953 if nspace is None:
1944 call_frame = sys._getframe().f_back
1954 call_frame = sys._getframe().f_back
1945 nspace = call_frame.f_locals
1955 nspace = call_frame.f_locals
1946
1956
1947 if type(alist) in StringTypes:
1957 if type(alist) in StringTypes:
1948 alist = alist.split()
1958 alist = alist.split()
1949 for attr in alist:
1959 for attr in alist:
1950 val = eval(attr,nspace)
1960 val = eval(attr,nspace)
1951 setattr(obj,attr,val)
1961 setattr(obj,attr,val)
1952
1962
1953 #----------------------------------------------------------------------------
1963 #----------------------------------------------------------------------------
1954 def getattr_list(obj,alist,*args):
1964 def getattr_list(obj,alist,*args):
1955 """getattr_list(obj,alist[, default]) -> attribute list.
1965 """getattr_list(obj,alist[, default]) -> attribute list.
1956
1966
1957 Get a list of named attributes for an object. When a default argument is
1967 Get a list of named attributes for an object. When a default argument is
1958 given, it is returned when the attribute doesn't exist; without it, an
1968 given, it is returned when the attribute doesn't exist; without it, an
1959 exception is raised in that case.
1969 exception is raised in that case.
1960
1970
1961 Note that alist can be given as a string, which will be automatically
1971 Note that alist can be given as a string, which will be automatically
1962 split into a list on whitespace. If given as a list, it must be a list of
1972 split into a list on whitespace. If given as a list, it must be a list of
1963 *strings* (the variable names themselves), not of variables."""
1973 *strings* (the variable names themselves), not of variables."""
1964
1974
1965 if type(alist) in StringTypes:
1975 if type(alist) in StringTypes:
1966 alist = alist.split()
1976 alist = alist.split()
1967 if args:
1977 if args:
1968 if len(args)==1:
1978 if len(args)==1:
1969 default = args[0]
1979 default = args[0]
1970 return map(lambda attr: getattr(obj,attr,default),alist)
1980 return map(lambda attr: getattr(obj,attr,default),alist)
1971 else:
1981 else:
1972 raise ValueError,'getattr_list() takes only one optional argument'
1982 raise ValueError,'getattr_list() takes only one optional argument'
1973 else:
1983 else:
1974 return map(lambda attr: getattr(obj,attr),alist)
1984 return map(lambda attr: getattr(obj,attr),alist)
1975
1985
1976 #----------------------------------------------------------------------------
1986 #----------------------------------------------------------------------------
1977 def map_method(method,object_list,*argseq,**kw):
1987 def map_method(method,object_list,*argseq,**kw):
1978 """map_method(method,object_list,*args,**kw) -> list
1988 """map_method(method,object_list,*args,**kw) -> list
1979
1989
1980 Return a list of the results of applying the methods to the items of the
1990 Return a list of the results of applying the methods to the items of the
1981 argument sequence(s). If more than one sequence is given, the method is
1991 argument sequence(s). If more than one sequence is given, the method is
1982 called with an argument list consisting of the corresponding item of each
1992 called with an argument list consisting of the corresponding item of each
1983 sequence. All sequences must be of the same length.
1993 sequence. All sequences must be of the same length.
1984
1994
1985 Keyword arguments are passed verbatim to all objects called.
1995 Keyword arguments are passed verbatim to all objects called.
1986
1996
1987 This is Python code, so it's not nearly as fast as the builtin map()."""
1997 This is Python code, so it's not nearly as fast as the builtin map()."""
1988
1998
1989 out_list = []
1999 out_list = []
1990 idx = 0
2000 idx = 0
1991 for object in object_list:
2001 for object in object_list:
1992 try:
2002 try:
1993 handler = getattr(object, method)
2003 handler = getattr(object, method)
1994 except AttributeError:
2004 except AttributeError:
1995 out_list.append(None)
2005 out_list.append(None)
1996 else:
2006 else:
1997 if argseq:
2007 if argseq:
1998 args = map(lambda lst:lst[idx],argseq)
2008 args = map(lambda lst:lst[idx],argseq)
1999 #print 'ob',object,'hand',handler,'ar',args # dbg
2009 #print 'ob',object,'hand',handler,'ar',args # dbg
2000 out_list.append(handler(args,**kw))
2010 out_list.append(handler(args,**kw))
2001 else:
2011 else:
2002 out_list.append(handler(**kw))
2012 out_list.append(handler(**kw))
2003 idx += 1
2013 idx += 1
2004 return out_list
2014 return out_list
2005
2015
2006 #----------------------------------------------------------------------------
2016 #----------------------------------------------------------------------------
2007 def get_class_members(cls):
2017 def get_class_members(cls):
2008 ret = dir(cls)
2018 ret = dir(cls)
2009 if hasattr(cls,'__bases__'):
2019 if hasattr(cls,'__bases__'):
2010 for base in cls.__bases__:
2020 for base in cls.__bases__:
2011 ret.extend(get_class_members(base))
2021 ret.extend(get_class_members(base))
2012 return ret
2022 return ret
2013
2023
2014 #----------------------------------------------------------------------------
2024 #----------------------------------------------------------------------------
2015 def dir2(obj):
2025 def dir2(obj):
2016 """dir2(obj) -> list of strings
2026 """dir2(obj) -> list of strings
2017
2027
2018 Extended version of the Python builtin dir(), which does a few extra
2028 Extended version of the Python builtin dir(), which does a few extra
2019 checks, and supports common objects with unusual internals that confuse
2029 checks, and supports common objects with unusual internals that confuse
2020 dir(), such as Traits and PyCrust.
2030 dir(), such as Traits and PyCrust.
2021
2031
2022 This version is guaranteed to return only a list of true strings, whereas
2032 This version is guaranteed to return only a list of true strings, whereas
2023 dir() returns anything that objects inject into themselves, even if they
2033 dir() returns anything that objects inject into themselves, even if they
2024 are later not really valid for attribute access (many extension libraries
2034 are later not really valid for attribute access (many extension libraries
2025 have such bugs).
2035 have such bugs).
2026 """
2036 """
2027
2037
2028 # Start building the attribute list via dir(), and then complete it
2038 # Start building the attribute list via dir(), and then complete it
2029 # with a few extra special-purpose calls.
2039 # with a few extra special-purpose calls.
2030 words = dir(obj)
2040 words = dir(obj)
2031
2041
2032 if hasattr(obj,'__class__'):
2042 if hasattr(obj,'__class__'):
2033 words.append('__class__')
2043 words.append('__class__')
2034 words.extend(get_class_members(obj.__class__))
2044 words.extend(get_class_members(obj.__class__))
2035 #if '__base__' in words: 1/0
2045 #if '__base__' in words: 1/0
2036
2046
2037 # Some libraries (such as traits) may introduce duplicates, we want to
2047 # Some libraries (such as traits) may introduce duplicates, we want to
2038 # track and clean this up if it happens
2048 # track and clean this up if it happens
2039 may_have_dupes = False
2049 may_have_dupes = False
2040
2050
2041 # this is the 'dir' function for objects with Enthought's traits
2051 # this is the 'dir' function for objects with Enthought's traits
2042 if hasattr(obj, 'trait_names'):
2052 if hasattr(obj, 'trait_names'):
2043 try:
2053 try:
2044 words.extend(obj.trait_names())
2054 words.extend(obj.trait_names())
2045 may_have_dupes = True
2055 may_have_dupes = True
2046 except TypeError:
2056 except TypeError:
2047 # This will happen if `obj` is a class and not an instance.
2057 # This will happen if `obj` is a class and not an instance.
2048 pass
2058 pass
2049
2059
2050 # Support for PyCrust-style _getAttributeNames magic method.
2060 # Support for PyCrust-style _getAttributeNames magic method.
2051 if hasattr(obj, '_getAttributeNames'):
2061 if hasattr(obj, '_getAttributeNames'):
2052 try:
2062 try:
2053 words.extend(obj._getAttributeNames())
2063 words.extend(obj._getAttributeNames())
2054 may_have_dupes = True
2064 may_have_dupes = True
2055 except TypeError:
2065 except TypeError:
2056 # `obj` is a class and not an instance. Ignore
2066 # `obj` is a class and not an instance. Ignore
2057 # this error.
2067 # this error.
2058 pass
2068 pass
2059
2069
2060 if may_have_dupes:
2070 if may_have_dupes:
2061 # eliminate possible duplicates, as some traits may also
2071 # eliminate possible duplicates, as some traits may also
2062 # appear as normal attributes in the dir() call.
2072 # appear as normal attributes in the dir() call.
2063 words = list(set(words))
2073 words = list(set(words))
2064 words.sort()
2074 words.sort()
2065
2075
2066 # filter out non-string attributes which may be stuffed by dir() calls
2076 # filter out non-string attributes which may be stuffed by dir() calls
2067 # and poor coding in third-party modules
2077 # and poor coding in third-party modules
2068 return [w for w in words if isinstance(w, basestring)]
2078 return [w for w in words if isinstance(w, basestring)]
2069
2079
2070 #----------------------------------------------------------------------------
2080 #----------------------------------------------------------------------------
2071 def import_fail_info(mod_name,fns=None):
2081 def import_fail_info(mod_name,fns=None):
2072 """Inform load failure for a module."""
2082 """Inform load failure for a module."""
2073
2083
2074 if fns == None:
2084 if fns == None:
2075 warn("Loading of %s failed.\n" % (mod_name,))
2085 warn("Loading of %s failed.\n" % (mod_name,))
2076 else:
2086 else:
2077 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
2087 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
2078
2088
2079 #----------------------------------------------------------------------------
2089 #----------------------------------------------------------------------------
2080 # Proposed popitem() extension, written as a method
2090 # Proposed popitem() extension, written as a method
2081
2091
2082
2092
2083 class NotGiven: pass
2093 class NotGiven: pass
2084
2094
2085 def popkey(dct,key,default=NotGiven):
2095 def popkey(dct,key,default=NotGiven):
2086 """Return dct[key] and delete dct[key].
2096 """Return dct[key] and delete dct[key].
2087
2097
2088 If default is given, return it if dct[key] doesn't exist, otherwise raise
2098 If default is given, return it if dct[key] doesn't exist, otherwise raise
2089 KeyError. """
2099 KeyError. """
2090
2100
2091 try:
2101 try:
2092 val = dct[key]
2102 val = dct[key]
2093 except KeyError:
2103 except KeyError:
2094 if default is NotGiven:
2104 if default is NotGiven:
2095 raise
2105 raise
2096 else:
2106 else:
2097 return default
2107 return default
2098 else:
2108 else:
2099 del dct[key]
2109 del dct[key]
2100 return val
2110 return val
2101
2111
2102 def wrap_deprecated(func, suggest = '<nothing>'):
2112 def wrap_deprecated(func, suggest = '<nothing>'):
2103 def newFunc(*args, **kwargs):
2113 def newFunc(*args, **kwargs):
2104 warnings.warn("Call to deprecated function %s, use %s instead" %
2114 warnings.warn("Call to deprecated function %s, use %s instead" %
2105 ( func.__name__, suggest),
2115 ( func.__name__, suggest),
2106 category=DeprecationWarning,
2116 category=DeprecationWarning,
2107 stacklevel = 2)
2117 stacklevel = 2)
2108 return func(*args, **kwargs)
2118 return func(*args, **kwargs)
2109 return newFunc
2119 return newFunc
2110
2120
2111
2121
2112 def _num_cpus_unix():
2122 def _num_cpus_unix():
2113 """Return the number of active CPUs on a Unix system."""
2123 """Return the number of active CPUs on a Unix system."""
2114 return os.sysconf("SC_NPROCESSORS_ONLN")
2124 return os.sysconf("SC_NPROCESSORS_ONLN")
2115
2125
2116
2126
2117 def _num_cpus_darwin():
2127 def _num_cpus_darwin():
2118 """Return the number of active CPUs on a Darwin system."""
2128 """Return the number of active CPUs on a Darwin system."""
2119 p = subprocess.Popen(['sysctl','-n','hw.ncpu'],stdout=subprocess.PIPE)
2129 p = subprocess.Popen(['sysctl','-n','hw.ncpu'],stdout=subprocess.PIPE)
2120 return p.stdout.read()
2130 return p.stdout.read()
2121
2131
2122
2132
2123 def _num_cpus_windows():
2133 def _num_cpus_windows():
2124 """Return the number of active CPUs on a Windows system."""
2134 """Return the number of active CPUs on a Windows system."""
2125 return os.environ.get("NUMBER_OF_PROCESSORS")
2135 return os.environ.get("NUMBER_OF_PROCESSORS")
2126
2136
2127
2137
2128 def num_cpus():
2138 def num_cpus():
2129 """Return the effective number of CPUs in the system as an integer.
2139 """Return the effective number of CPUs in the system as an integer.
2130
2140
2131 This cross-platform function makes an attempt at finding the total number of
2141 This cross-platform function makes an attempt at finding the total number of
2132 available CPUs in the system, as returned by various underlying system and
2142 available CPUs in the system, as returned by various underlying system and
2133 python calls.
2143 python calls.
2134
2144
2135 If it can't find a sensible answer, it returns 1 (though an error *may* make
2145 If it can't find a sensible answer, it returns 1 (though an error *may* make
2136 it return a large positive number that's actually incorrect).
2146 it return a large positive number that's actually incorrect).
2137 """
2147 """
2138
2148
2139 # Many thanks to the Parallel Python project (http://www.parallelpython.com)
2149 # Many thanks to the Parallel Python project (http://www.parallelpython.com)
2140 # for the names of the keys we needed to look up for this function. This
2150 # for the names of the keys we needed to look up for this function. This
2141 # code was inspired by their equivalent function.
2151 # code was inspired by their equivalent function.
2142
2152
2143 ncpufuncs = {'Linux':_num_cpus_unix,
2153 ncpufuncs = {'Linux':_num_cpus_unix,
2144 'Darwin':_num_cpus_darwin,
2154 'Darwin':_num_cpus_darwin,
2145 'Windows':_num_cpus_windows,
2155 'Windows':_num_cpus_windows,
2146 # On Vista, python < 2.5.2 has a bug and returns 'Microsoft'
2156 # On Vista, python < 2.5.2 has a bug and returns 'Microsoft'
2147 # See http://bugs.python.org/issue1082 for details.
2157 # See http://bugs.python.org/issue1082 for details.
2148 'Microsoft':_num_cpus_windows,
2158 'Microsoft':_num_cpus_windows,
2149 }
2159 }
2150
2160
2151 ncpufunc = ncpufuncs.get(platform.system(),
2161 ncpufunc = ncpufuncs.get(platform.system(),
2152 # default to unix version (Solaris, AIX, etc)
2162 # default to unix version (Solaris, AIX, etc)
2153 _num_cpus_unix)
2163 _num_cpus_unix)
2154
2164
2155 try:
2165 try:
2156 ncpus = max(1,int(ncpufunc()))
2166 ncpus = max(1,int(ncpufunc()))
2157 except:
2167 except:
2158 ncpus = 1
2168 ncpus = 1
2159 return ncpus
2169 return ncpus
2160
2170
2161 #*************************** end of file <genutils.py> **********************
2171 #*************************** end of file <genutils.py> **********************
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now