##// END OF EJS Templates
rollback to working
Tom Fetherston -
r1939:c31442ed merge
parent child Browse files
Show More
@@ -0,0 +1,68 b''
1 from IPython.demo import Demo,IPythonDemo,LineDemo,IPythonLineDemo,ClearDemo,ClearIPDemo
2 import tempfile, os, StringIO, shutil
3
4 example1 = """
5 '''A simple interactive demo to illustrate the use of IPython's Demo class.'''
6
7 print 'Hello, welcome to an interactive IPython demo.'
8
9 # The mark below defines a block boundary, which is a point where IPython will
10 # stop execution and return to the interactive prompt. The dashes are actually
11 # optional and used only as a visual aid to clearly separate blocks while
12 # editing the demo code.
13 # <demo> stop
14
15 x = 1
16 y = 2
17
18 # <demo> stop
19
20 # the mark below makes this block as silent
21 # <demo> silent
22
23 print 'This is a silent block, which gets executed but not printed.'
24
25 # <demo> stop
26 # <demo> auto
27 print 'This is an automatic block.'
28 print 'It is executed without asking for confirmation, but printed.'
29 z = x+y
30
31 print 'z=',x
32
33 # <demo> stop
34 # This is just another normal block.
35 print 'z is now:', z
36
37 print 'bye!'
38 """
39 fp = tempfile.mkdtemp(prefix = 'DemoTmp')
40 fd, filename = tempfile.mkstemp(prefix = 'demoExample1File', suffix = '.py', dir = fp)
41 f = os.fdopen(fd, 'wt')
42
43 f.write(example1)
44 f.close()
45
46 my_d = Demo(filename)
47 my_cd = ClearDemo(filename)
48
49 fobj = StringIO.StringIO(example1)
50 str_d = Demo(fobj, title='via stringio')
51 #~ def tmpcleanup():
52 #~ global my_d, my_cd, fp
53 #~ del my_d
54 #~ del my_cd
55 #~ shutil.rmtree(fp, False)
56
57 print '''
58 The example that is embeded in demo.py file has been used to create
59 the following 3 demos, and should now be available to use:
60 my_d() -- created from a file
61 my_cd() -- created from a file, a ClearDemo
62 str_d() -- same as above, but created via a stringi\o object
63 Call by typing their name, (with parentheses), at the
64 ipython prompt, interact with the block, then call again
65 to run the next block.
66 '''
67 # call tmpcleanup to delete the temporary files created. -not implemented
68
@@ -1,526 +1,552 b''
1 1 """Module for interactive demos using IPython.
2 2
3 3 This module implements a few classes for running Python scripts interactively
4 4 in IPython for demonstrations. With very simple markup (a few tags in
5 5 comments), you can control points where the script stops executing and returns
6 6 control to IPython.
7 7
8 8
9 9 Provided classes
10 10 ================
11 11
12 12 The classes are (see their docstrings for further details):
13 13
14 14 - Demo: pure python demos
15 15
16 16 - IPythonDemo: demos with input to be processed by IPython as if it had been
17 17 typed interactively (so magics work, as well as any other special syntax you
18 18 may have added via input prefilters).
19 19
20 20 - LineDemo: single-line version of the Demo class. These demos are executed
21 21 one line at a time, and require no markup.
22 22
23 23 - IPythonLineDemo: IPython version of the LineDemo class (the demo is
24 24 executed a line at a time, but processed via IPython).
25 25
26 26 - ClearMixin: mixin to make Demo classes with less visual clutter. It
27 27 declares an empty marquee and a pre_cmd that clears the screen before each
28 28 block (see Subclassing below).
29 29
30 30 - ClearDemo, ClearIPDemo: mixin-enabled versions of the Demo and IPythonDemo
31 31 classes.
32 32
33 33
34 34 Subclassing
35 35 ===========
36 36
37 37 The classes here all include a few methods meant to make customization by
38 38 subclassing more convenient. Their docstrings below have some more details:
39 39
40 40 - marquee(): generates a marquee to provide visible on-screen markers at each
41 41 block start and end.
42 42
43 43 - pre_cmd(): run right before the execution of each block.
44 44
45 45 - post_cmd(): run right after the execution of each block. If the block
46 46 raises an exception, this is NOT called.
47 47
48 48
49 49 Operation
50 50 =========
51 51
52 52 The file is run in its own empty namespace (though you can pass it a string of
53 53 arguments as if in a command line environment, and it will see those as
54 54 sys.argv). But at each stop, the global IPython namespace is updated with the
55 55 current internal demo namespace, so you can work interactively with the data
56 56 accumulated so far.
57 57
58 58 By default, each block of code is printed (with syntax highlighting) before
59 59 executing it and you have to confirm execution. This is intended to show the
60 60 code to an audience first so you can discuss it, and only proceed with
61 61 execution once you agree. There are a few tags which allow you to modify this
62 62 behavior.
63 63
64 64 The supported tags are:
65 65
66 66 # <demo> stop
67 67
68 68 Defines block boundaries, the points where IPython stops execution of the
69 69 file and returns to the interactive prompt.
70 70
71 71 You can optionally mark the stop tag with extra dashes before and after the
72 72 word 'stop', to help visually distinguish the blocks in a text editor:
73 73
74 74 # <demo> --- stop ---
75 75
76 76
77 77 # <demo> silent
78 78
79 79 Make a block execute silently (and hence automatically). Typically used in
80 80 cases where you have some boilerplate or initialization code which you need
81 81 executed but do not want to be seen in the demo.
82 82
83 83 # <demo> auto
84 84
85 85 Make a block execute automatically, but still being printed. Useful for
86 86 simple code which does not warrant discussion, since it avoids the extra
87 87 manual confirmation.
88 88
89 89 # <demo> auto_all
90 90
91 91 This tag can _only_ be in the first block, and if given it overrides the
92 92 individual auto tags to make the whole demo fully automatic (no block asks
93 93 for confirmation). It can also be given at creation time (or the attribute
94 94 set later) to override what's in the file.
95 95
96 96 While _any_ python file can be run as a Demo instance, if there are no stop
97 97 tags the whole file will run in a single block (no different that calling
98 98 first %pycat and then %run). The minimal markup to make this useful is to
99 99 place a set of stop tags; the other tags are only there to let you fine-tune
100 100 the execution.
101 101
102 102 This is probably best explained with the simple example file below. You can
103 103 copy this into a file named ex_demo.py, and try running it via:
104 104
105 105 from IPython.demo import Demo
106 106 d = Demo('ex_demo.py')
107 107 d() <--- Call the d object (omit the parens if you have autocall set to 2).
108 108
109 109 Each time you call the demo object, it runs the next block. The demo object
110 110 has a few useful methods for navigation, like again(), edit(), jump(), seek()
111 111 and back(). It can be reset for a new run via reset() or reloaded from disk
112 112 (in case you've edited the source) via reload(). See their docstrings below.
113 113
114
114 Note: To make this simpler to explore, a file called "demoExercizer.py" has
115 been added to the \ipython\docs\examples\core. Just cd to this directory in
116 an IPython session, and type:
117 run demoExercizer.py
118 and then follow the directions.
115 119 Example
116 120 =======
117 121
118 122 The following is a very simple example of a valid demo file.
119 123
120 124 #################### EXAMPLE DEMO <ex_demo.py> ###############################
121 125 '''A simple interactive demo to illustrate the use of IPython's Demo class.'''
122 126
123 127 print 'Hello, welcome to an interactive IPython demo.'
124 128
125 129 # The mark below defines a block boundary, which is a point where IPython will
126 130 # stop execution and return to the interactive prompt. The dashes are actually
127 131 # optional and used only as a visual aid to clearly separate blocks while
128 editing the demo code.
132 # editing the demo code.
129 133 # <demo> stop
130 134
131 135 x = 1
132 136 y = 2
133 137
134 138 # <demo> stop
135 139
136 140 # the mark below makes this block as silent
137 141 # <demo> silent
138 142
139 143 print 'This is a silent block, which gets executed but not printed.'
140 144
141 145 # <demo> stop
142 146 # <demo> auto
143 147 print 'This is an automatic block.'
144 148 print 'It is executed without asking for confirmation, but printed.'
145 149 z = x+y
146 150
147 151 print 'z=',x
148 152
149 153 # <demo> stop
150 154 # This is just another normal block.
151 155 print 'z is now:', z
152 156
153 157 print 'bye!'
154 158 ################### END EXAMPLE DEMO <ex_demo.py> ############################
155 159 """
156 160
157 161 #*****************************************************************************
158 162 # Copyright (C) 2005-2006 Fernando Perez. <Fernando.Perez@colorado.edu>
159 163 #
160 164 # Distributed under the terms of the BSD License. The full license is in
161 165 # the file COPYING, distributed as part of this software.
162 166 #
163 167 #*****************************************************************************
164 168
165 169 import exceptions
166 170 import os
167 171 import re
168 172 import shlex
169 173 import sys
170 174
171 175 from IPython.PyColorize import Parser
172 176 from IPython.genutils import marquee, file_read, file_readlines
177 from genutils import Term
173 178
174 179 __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError']
175 180
176 181 class DemoError(exceptions.Exception): pass
177 182
178 183 def re_mark(mark):
179 184 return re.compile(r'^\s*#\s+<demo>\s+%s\s*$' % mark,re.MULTILINE)
180 185
181 186 class Demo(object):
182 187
183 188 re_stop = re_mark('-*\s?stop\s?-*')
184 189 re_silent = re_mark('silent')
185 190 re_auto = re_mark('auto')
186 191 re_auto_all = re_mark('auto_all')
187 192
188 def __init__(self,fname,arg_str='',auto_all=None):
193 def __init__(self,src,title='',arg_str='',auto_all=None):
189 194 """Make a new demo object. To run the demo, simply call the object.
190 195
191 196 See the module docstring for full details and an example (you can use
192 197 IPython.Demo? in IPython to see it).
193 198
194 199 Inputs:
195 200
196 - fname = filename.
201 - src is either a file, or file-like object, or a
202 string that can be resolved to a filename.
197 203
198 204 Optional inputs:
205
206 - title: a string to use as the demo name. Of most use when the demo
207 you are making comes from an object that has no filename, or if you
208 want an alternate denotation distinct from the filename.
199 209
200 210 - arg_str(''): a string of arguments, internally converted to a list
201 211 just like sys.argv, so the demo script can see a similar
202 212 environment.
203 213
204 214 - auto_all(None): global flag to run all blocks automatically without
205 215 confirmation. This attribute overrides the block-level tags and
206 216 applies to the whole demo. It is an attribute of the object, and
207 217 can be changed at runtime simply by reassigning it to a boolean
208 218 value.
209 219 """
210
211 self.fname = fname
212 self.sys_argv = [fname] + shlex.split(arg_str)
220 if hasattr(src, "read"):
221 # It seems to be a file or a file-like object
222 self.fobj = src
223 self.fname = "from a file-like object"
224 if title == '':
225 self.title = "from a file-like object"
226 else:
227 self.title = title
228 else:
229 # Assume it's a string or something that can be converted to one
230 self.fobj = open(src)
231 self.fname = src
232 if title == '':
233 (filepath, filename) = os.path.split(src)
234 self.title = filename
235 else:
236 self.title = title
237 self.sys_argv = [src] + shlex.split(arg_str)
213 238 self.auto_all = auto_all
214 239
215 240 # get a few things from ipython. While it's a bit ugly design-wise,
216 241 # it ensures that things like color scheme and the like are always in
217 242 # sync with the ipython mode being used. This class is only meant to
218 243 # be used inside ipython anyways, so it's OK.
219 244 self.ip_ns = __IPYTHON__.user_ns
220 245 self.ip_colorize = __IPYTHON__.pycolorize
221 246 self.ip_showtb = __IPYTHON__.showtraceback
222 247 self.ip_runlines = __IPYTHON__.runlines
223 248 self.shell = __IPYTHON__
224 249
225 250 # load user data and initialize data structures
226 251 self.reload()
227 252
228 253 def reload(self):
229 254 """Reload source from disk and initialize state."""
230 255 # read data and parse into blocks
231 self.src = file_read(self.fname)
256 self.src = self.fobj.read()
232 257 src_b = [b.strip() for b in self.re_stop.split(self.src) if b]
233 258 self._silent = [bool(self.re_silent.findall(b)) for b in src_b]
234 259 self._auto = [bool(self.re_auto.findall(b)) for b in src_b]
235 260
236 261 # if auto_all is not given (def. None), we read it from the file
237 262 if self.auto_all is None:
238 263 self.auto_all = bool(self.re_auto_all.findall(src_b[0]))
239 264 else:
240 265 self.auto_all = bool(self.auto_all)
241 266
242 267 # Clean the sources from all markup so it doesn't get displayed when
243 268 # running the demo
244 269 src_blocks = []
245 270 auto_strip = lambda s: self.re_auto.sub('',s)
246 271 for i,b in enumerate(src_b):
247 272 if self._auto[i]:
248 273 src_blocks.append(auto_strip(b))
249 274 else:
250 275 src_blocks.append(b)
251 276 # remove the auto_all marker
252 277 src_blocks[0] = self.re_auto_all.sub('',src_blocks[0])
253 278
254 279 self.nblocks = len(src_blocks)
255 280 self.src_blocks = src_blocks
256 281
257 282 # also build syntax-highlighted source
258 283 self.src_blocks_colored = map(self.ip_colorize,self.src_blocks)
259 284
260 285 # ensure clean namespace and seek offset
261 286 self.reset()
262 287
263 288 def reset(self):
264 289 """Reset the namespace and seek pointer to restart the demo"""
265 290 self.user_ns = {}
266 291 self.finished = False
267 292 self.block_index = 0
268 293
269 294 def _validate_index(self,index):
270 295 if index<0 or index>=self.nblocks:
271 296 raise ValueError('invalid block index %s' % index)
272 297
273 298 def _get_index(self,index):
274 299 """Get the current block index, validating and checking status.
275 300
276 301 Returns None if the demo is finished"""
277 302
278 303 if index is None:
279 304 if self.finished:
280 print 'Demo finished. Use reset() if you want to rerun it.'
305 print >>Term.cout, 'Demo finished. Use <demo_name>.reset() if you want to rerun it.'
281 306 return None
282 307 index = self.block_index
283 308 else:
284 309 self._validate_index(index)
285 310 return index
286 311
287 312 def seek(self,index):
288 313 """Move the current seek pointer to the given block.
289 314
290 315 You can use negative indices to seek from the end, with identical
291 316 semantics to those of Python lists."""
292 317 if index<0:
293 318 index = self.nblocks + index
294 319 self._validate_index(index)
295 320 self.block_index = index
296 321 self.finished = False
297 322
298 323 def back(self,num=1):
299 324 """Move the seek pointer back num blocks (default is 1)."""
300 325 self.seek(self.block_index-num)
301 326
302 327 def jump(self,num=1):
303 328 """Jump a given number of blocks relative to the current one.
304 329
305 330 The offset can be positive or negative, defaults to 1."""
306 331 self.seek(self.block_index+num)
307 332
308 333 def again(self):
309 334 """Move the seek pointer back one block and re-execute."""
310 335 self.back(1)
311 336 self()
312 337
313 338 def edit(self,index=None):
314 339 """Edit a block.
315 340
316 341 If no number is given, use the last block executed.
317 342
318 343 This edits the in-memory copy of the demo, it does NOT modify the
319 344 original source file. If you want to do that, simply open the file in
320 345 an editor and use reload() when you make changes to the file. This
321 346 method is meant to let you change a block during a demonstration for
322 347 explanatory purposes, without damaging your original script."""
323 348
324 349 index = self._get_index(index)
325 350 if index is None:
326 351 return
327 352 # decrease the index by one (unless we're at the very beginning), so
328 353 # that the default demo.edit() call opens up the sblock we've last run
329 354 if index>0:
330 355 index -= 1
331 356
332 357 filename = self.shell.mktempfile(self.src_blocks[index])
333 358 self.shell.hooks.editor(filename,1)
334 359 new_block = file_read(filename)
335 360 # update the source and colored block
336 361 self.src_blocks[index] = new_block
337 362 self.src_blocks_colored[index] = self.ip_colorize(new_block)
338 363 self.block_index = index
339 364 # call to run with the newly edited index
340 365 self()
341 366
342 367 def show(self,index=None):
343 368 """Show a single block on screen"""
344 369
345 370 index = self._get_index(index)
346 371 if index is None:
347 372 return
348 373
349 print self.marquee('<%s> block # %s (%s remaining)' %
350 (self.fname,index,self.nblocks-index-1))
351 sys.stdout.write(self.src_blocks_colored[index])
374 print >>Term.cout, self.marquee('<%s> block # %s (%s remaining)' %
375 (self.title,index,self.nblocks-index-1))
376 print >>Term.cout,(self.src_blocks_colored[index])
352 377 sys.stdout.flush()
353 378
354 379 def show_all(self):
355 380 """Show entire demo on screen, block by block"""
356 381
357 fname = self.fname
382 fname = self.title
383 title = self.title
358 384 nblocks = self.nblocks
359 385 silent = self._silent
360 386 marquee = self.marquee
361 387 for index,block in enumerate(self.src_blocks_colored):
362 388 if silent[index]:
363 print marquee('<%s> SILENT block # %s (%s remaining)' %
364 (fname,index,nblocks-index-1))
389 print >>Term.cout, marquee('<%s> SILENT block # %s (%s remaining)' %
390 (title,index,nblocks-index-1))
365 391 else:
366 print marquee('<%s> block # %s (%s remaining)' %
367 (fname,index,nblocks-index-1))
368 print block,
392 print >>Term.cout, marquee('<%s> block # %s (%s remaining)' %
393 (title,index,nblocks-index-1))
394 print >>Term.cout, block,
369 395 sys.stdout.flush()
370 396
371 397 def runlines(self,source):
372 398 """Execute a string with one or more lines of code"""
373 399
374 400 exec source in self.user_ns
375 401
376 402 def __call__(self,index=None):
377 403 """run a block of the demo.
378 404
379 405 If index is given, it should be an integer >=1 and <= nblocks. This
380 406 means that the calling convention is one off from typical Python
381 407 lists. The reason for the inconsistency is that the demo always
382 408 prints 'Block n/N, and N is the total, so it would be very odd to use
383 409 zero-indexing here."""
384 410
385 411 index = self._get_index(index)
386 412 if index is None:
387 413 return
388 414 try:
389 415 marquee = self.marquee
390 416 next_block = self.src_blocks[index]
391 417 self.block_index += 1
392 418 if self._silent[index]:
393 print marquee('Executing silent block # %s (%s remaining)' %
419 print >>Term.cout, marquee('Executing silent block # %s (%s remaining)' %
394 420 (index,self.nblocks-index-1))
395 421 else:
396 422 self.pre_cmd()
397 423 self.show(index)
398 424 if self.auto_all or self._auto[index]:
399 print marquee('output:')
425 print >>Term.cout, marquee('output:')
400 426 else:
401 print marquee('Press <q> to quit, <Enter> to execute...'),
427 print >>Term.cout, marquee('Press <q> to quit, <Enter> to execute...'),
402 428 ans = raw_input().strip()
403 429 if ans:
404 print marquee('Block NOT executed')
430 print >>Term.cout, marquee('Block NOT executed')
405 431 return
406 432 try:
407 433 save_argv = sys.argv
408 434 sys.argv = self.sys_argv
409 435 self.runlines(next_block)
410 436 self.post_cmd()
411 437 finally:
412 438 sys.argv = save_argv
413 439
414 440 except:
415 441 self.ip_showtb(filename=self.fname)
416 442 else:
417 443 self.ip_ns.update(self.user_ns)
418 444
419 445 if self.block_index == self.nblocks:
420 446 mq1 = self.marquee('END OF DEMO')
421 447 if mq1:
422 # avoid spurious prints if empty marquees are used
423 print
424 print mq1
425 print self.marquee('Use reset() if you want to rerun it.')
448 # avoid spurious print >>Term.cout,s if empty marquees are used
449 print >>Term.cout
450 print >>Term.cout, mq1
451 print >>Term.cout, self.marquee('Use <demo_name>.reset() if you want to rerun it.')
426 452 self.finished = True
427 453
428 454 # These methods are meant to be overridden by subclasses who may wish to
429 455 # customize the behavior of of their demos.
430 456 def marquee(self,txt='',width=78,mark='*'):
431 457 """Return the input string centered in a 'marquee'."""
432 458 return marquee(txt,width,mark)
433 459
434 460 def pre_cmd(self):
435 461 """Method called before executing each block."""
436 462 pass
437 463
438 464 def post_cmd(self):
439 465 """Method called after executing each block."""
440 466 pass
441 467
442 468
443 469 class IPythonDemo(Demo):
444 470 """Class for interactive demos with IPython's input processing applied.
445 471
446 472 This subclasses Demo, but instead of executing each block by the Python
447 473 interpreter (via exec), it actually calls IPython on it, so that any input
448 474 filters which may be in place are applied to the input block.
449 475
450 476 If you have an interactive environment which exposes special input
451 477 processing, you can use this class instead to write demo scripts which
452 478 operate exactly as if you had typed them interactively. The default Demo
453 479 class requires the input to be valid, pure Python code.
454 480 """
455 481
456 482 def runlines(self,source):
457 483 """Execute a string with one or more lines of code"""
458 484
459 485 self.shell.runlines(source)
460 486
461 487 class LineDemo(Demo):
462 488 """Demo where each line is executed as a separate block.
463 489
464 490 The input script should be valid Python code.
465 491
466 492 This class doesn't require any markup at all, and it's meant for simple
467 493 scripts (with no nesting or any kind of indentation) which consist of
468 494 multiple lines of input to be executed, one at a time, as if they had been
469 495 typed in the interactive prompt."""
470 496
471 497 def reload(self):
472 498 """Reload source from disk and initialize state."""
473 499 # read data and parse into blocks
474 src_b = [l for l in file_readlines(self.fname) if l.strip()]
500 src_b = [l for l in self.fobj.readline() if l.strip()]
475 501 nblocks = len(src_b)
476 self.src = os.linesep.join(file_readlines(self.fname))
502 self.src = os.linesep.join(self.fobj.readlines())
477 503 self._silent = [False]*nblocks
478 504 self._auto = [True]*nblocks
479 505 self.auto_all = True
480 506 self.nblocks = nblocks
481 507 self.src_blocks = src_b
482 508
483 509 # also build syntax-highlighted source
484 510 self.src_blocks_colored = map(self.ip_colorize,self.src_blocks)
485 511
486 512 # ensure clean namespace and seek offset
487 513 self.reset()
488 514
489 515
490 516 class IPythonLineDemo(IPythonDemo,LineDemo):
491 517 """Variant of the LineDemo class whose input is processed by IPython."""
492 518 pass
493 519
494 520
495 521 class ClearMixin(object):
496 522 """Use this mixin to make Demo classes with less visual clutter.
497
523
498 524 Demos using this mixin will clear the screen before every block and use
499 525 blank marquees.
500
526
501 527 Note that in order for the methods defined here to actually override those
502 528 of the classes it's mixed with, it must go /first/ in the inheritance
503 529 tree. For example:
504
530
505 531 class ClearIPDemo(ClearMixin,IPythonDemo): pass
506
532
507 533 will provide an IPythonDemo class with the mixin's features.
508 534 """
509 535
510 536 def marquee(self,txt='',width=78,mark='*'):
511 537 """Blank marquee that returns '' no matter what the input."""
512 538 return ''
513
539
514 540 def pre_cmd(self):
515 541 """Method called before executing each block.
516
542
517 543 This one simply clears the screen."""
518 os.system('clear')
519
544 import IPython.platutils
545 IPython.platutils.term_clear()
520 546
521 547 class ClearDemo(ClearMixin,Demo):
522 548 pass
523 549
524 550
525 551 class ClearIPDemo(ClearMixin,IPythonDemo):
526 552 pass
@@ -1,70 +1,75 b''
1 1 # -*- coding: utf-8 -*-
2 2 """ Proxy module for accessing platform specific utility functions.
3 3
4 4 Importing this module should give you the implementations that are correct
5 5 for your operation system, from platutils_PLATFORMNAME module.
6 6 """
7 7
8 8 #*****************************************************************************
9 9 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #*****************************************************************************
14 14
15 15 import os
16 16 import sys
17 17
18 18 # Import the platform-specific implementations
19 19 if os.name == 'posix':
20 20 import platutils_posix as _platutils
21 21 elif sys.platform == 'win32':
22 22 import platutils_win32 as _platutils
23 23 else:
24 24 import platutils_dummy as _platutils
25 25 import warnings
26 26 warnings.warn("Platutils not available for platform '%s', some features may be missing" %
27 27 os.name)
28 28 del warnings
29 29
30 30
31 31 # Functionality that's logically common to all platforms goes here, each
32 32 # platform-specific module only provides the bits that are OS-dependent.
33 33
34 34 # XXX - I'm still not happy with a module global for this, but at least now
35 35 # there is a public, cross-platform way of toggling the term title control on
36 36 # and off. We should make this a stateful object later on so that each user
37 37 # can have its own instance if needed.
38 def term_clear():
39 _platutils.term_clear()
40
38 41 def toggle_set_term_title(val):
39 42 """Control whether set_term_title is active or not.
40 43
41 44 set_term_title() allows writing to the console titlebar. In embedded
42 45 widgets this can cause problems, so this call can be used to toggle it on
43 46 or off as needed.
44 47
45 48 The default state of the module is for the function to be disabled.
46 49
47 50 Parameters
48 51 ----------
49 52 val : bool
50 53 If True, set_term_title() actually writes to the terminal (using the
51 54 appropriate platform-specific module). If False, it is a no-op.
52 55 """
53 56 _platutils.ignore_termtitle = not(val)
54 57
55 58
56 59 def set_term_title(title):
57 60 """Set terminal title using the necessary platform-dependent calls."""
58 61
59 62 if _platutils.ignore_termtitle:
60 63 return
61 64 _platutils.set_term_title(title)
62 65
63 66
64 67 #-----------------------------------------------------------------------------
65 68 # Deprecated functions
66 69 #-----------------------------------------------------------------------------
67 70 def freeze_term_title():
71 import warnings
68 72 warnings.warn("This function is deprecated, use toggle_set_term_title()")
69 73 _platutils.ignore_termtitle = True
74 del warnings
70 75
@@ -1,32 +1,34 b''
1 1 # -*- coding: utf-8 -*-
2 2 """ Platform specific utility functions, posix version
3 3
4 4 Importing this module directly is not portable - rather, import platutils
5 5 to use these functions in platform agnostic fashion.
6 6 """
7 7
8 8 #*****************************************************************************
9 9 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #*****************************************************************************
14 14
15 15 import sys
16 16 import os
17 17
18 18 ignore_termtitle = True
19 19
20 20 def _dummy_op(*a, **b):
21 21 """ A no-op function """
22 22
23 23 def _set_term_title_xterm(title):
24 24 """ Change virtual terminal title in xterm-workalikes """
25 25
26 26 sys.stdout.write('\033]0;%s\007' % title)
27 27
28 28
29 29 if os.environ.get('TERM','') == 'xterm':
30 30 set_term_title = _set_term_title_xterm
31 31 else:
32 32 set_term_title = _dummy_op
33 def term_clear():
34 os.system('clear')
@@ -1,43 +1,47 b''
1 1 # -*- coding: utf-8 -*-
2 2 """ Platform specific utility functions, win32 version
3 3
4 4 Importing this module directly is not portable - rather, import platutils
5 5 to use these functions in platform agnostic fashion.
6 6 """
7 7
8 8 #*****************************************************************************
9 9 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #*****************************************************************************
14 14
15 15 import os
16 16
17 17 ignore_termtitle = True
18 18
19 19 try:
20 20 import ctypes
21 21
22 22 SetConsoleTitleW = ctypes.windll.kernel32.SetConsoleTitleW
23 23 SetConsoleTitleW.argtypes = [ctypes.c_wchar_p]
24 24
25 25 def set_term_title(title):
26 26 """Set terminal title using ctypes to access the Win32 APIs."""
27 27 SetConsoleTitleW(title)
28 28
29 29 except ImportError:
30 30 def set_term_title(title):
31 31 """Set terminal title using the 'title' command."""
32 32 global ignore_termtitle
33 33
34 34 try:
35 35 # Cannot be on network share when issuing system commands
36 36 curr = os.getcwd()
37 37 os.chdir("C:")
38 38 ret = os.system("title " + title)
39 39 finally:
40 40 os.chdir(curr)
41 41 if ret:
42 42 # non-zero return code signals error, don't try again
43 43 ignore_termtitle = True
44
45 def term_clear():
46 os.system('cls')
47
General Comments 0
You need to be logged in to leave comments. Login now