##// END OF EJS Templates
Apply patch by Paul Mueller <gakusei-AT-dakotacom.net>, to fix deprecated...
fperez -
Show More

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

@@ -1,671 +1,693 b''
1 1 # -*- coding: utf-8 -*-
2 2 """DPyGetOpt -- Demiurge Python GetOptions Module
3 3
4 $Id: DPyGetOpt.py 1980 2006-12-12 21:48:46Z vivainio $
4 $Id: DPyGetOpt.py 2872 2007-11-25 17:58:05Z fperez $
5 5
6 6 This module is modeled after perl's Getopt::Long module-- which
7 7 is, in turn, modeled after GNU's extended getopt() function.
8 8
9 9 Upon instantiation, the option specification should be a sequence
10 10 (list) of option definitions.
11 11
12 12 Options that take no arguments should simply contain the name of
13 13 the option. If a ! is post-pended, the option can be negated by
14 14 prepending 'no'; ie 'debug!' specifies that -debug and -nodebug
15 15 should be accepted.
16 16
17 17 Mandatory arguments to options are specified using a postpended
18 18 '=' + a type specifier. '=s' specifies a mandatory string
19 19 argument, '=i' specifies a mandatory integer argument, and '=f'
20 20 specifies a mandatory real number. In all cases, the '=' can be
21 21 substituted with ':' to specify that the argument is optional.
22 22
23 23 Dashes '-' in option names are allowed.
24 24
25 25 If an option has the character '@' postpended (after the
26 26 argumentation specification), it can appear multiple times within
27 27 each argument list that is processed. The results will be stored
28 28 in a list.
29 29
30 30 The option name can actually be a list of names separated by '|'
31 31 characters; ie-- 'foo|bar|baz=f@' specifies that all -foo, -bar,
32 32 and -baz options that appear on within the parsed argument list
33 33 must have a real number argument and that the accumulated list
34 34 of values will be available under the name 'foo'
35 35
36 $Id: DPyGetOpt.py 1980 2006-12-12 21:48:46Z vivainio $"""
36 $Id: DPyGetOpt.py 2872 2007-11-25 17:58:05Z fperez $"""
37 37
38 38 #*****************************************************************************
39 39 #
40 40 # Copyright (c) 2001 Bill Bumgarner <bbum@friday.com>
41 41 #
42 42 #
43 43 # Published under the terms of the MIT license, hereby reproduced:
44 44 #
45 45 # Permission is hereby granted, free of charge, to any person obtaining a copy
46 46 # of this software and associated documentation files (the "Software"), to
47 47 # deal in the Software without restriction, including without limitation the
48 48 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
49 49 # sell copies of the Software, and to permit persons to whom the Software is
50 50 # furnished to do so, subject to the following conditions:
51 51 #
52 52 # The above copyright notice and this permission notice shall be included in
53 53 # all copies or substantial portions of the Software.
54 54 #
55 55 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
56 56 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
57 57 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
58 58 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
59 59 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
60 60 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
61 61 # IN THE SOFTWARE.
62 62 #
63 63 #*****************************************************************************
64 64
65 65 __author__ = 'Bill Bumgarner <bbum@friday.com>'
66 66 __license__ = 'MIT'
67 67 __version__ = '1.2'
68 68
69 69 # Modified to use re instead of regex and regsub modules.
70 70 # 2001/5/7, Jonathan Hogg <jonathan@onegoodidea.com>
71 71
72 72 import re
73 73 import string
74 74 import sys
75 75 import types
76 76
77 arg_error = 'DPyGetOpt Argument Error'
78 spec_error = 'DPyGetOpt Specification Error'
79 term_error = 'DPyGetOpt Termination Error'
77 class Error(Exception):
78 """Base class for exceptions in the DPyGetOpt module."""
79
80 class ArgumentError(Error):
81 """Exception indicating an error in the arguments passed to
82 DPyGetOpt.processArguments."""
83
84 class SpecificationError(Error):
85 """Exception indicating an error with an option specification."""
86
87 class TerminationError(Error):
88 """Exception indicating an error with an option processing terminator."""
80 89
81 90 specificationExpr = re.compile('(?P<required>.)(?P<type>.)(?P<multi>@?)')
82 91
83 92 ArgRequired = 'Requires an Argument'
84 93 ArgOptional = 'Argument Optional'
85 94
86 95 # The types modules is not used for these identifiers because there
87 96 # is no identifier for 'boolean' or 'generic'
88 97 StringArgType = 'String Argument Type'
89 98 IntegerArgType = 'Integer Argument Type'
90 99 RealArgType = 'Real Argument Type'
91 100 BooleanArgType = 'Boolean Argument Type'
92 101 GenericArgType = 'Generic Argument Type'
93 102
94 103 # dictionary of conversion functions-- boolean and generic options
95 104 # do not accept arguments and do not need conversion functions;
96 105 # the identity function is used purely for convenience.
97 106 ConversionFunctions = {
98 107 StringArgType : lambda x: x,
99 108 IntegerArgType : string.atoi,
100 109 RealArgType : string.atof,
101 110 BooleanArgType : lambda x: x,
102 111 GenericArgType : lambda x: x,
103 112 }
104 113
105 114 class DPyGetOpt:
106 115
107 116 def __init__(self, spec = None, terminators = ['--']):
108 117 """
109 118 Declare and intialize instance variables
110 119
111 120 Yes, declaration is not necessary... but one of the things
112 121 I sorely miss from C/Obj-C is the concept of having an
113 122 interface definition that clearly declares all instance
114 123 variables and methods without providing any implementation
115 124 details. it is a useful reference!
116 125
117 126 all instance variables are initialized to 0/Null/None of
118 127 the appropriate type-- not even the default value...
119 128 """
120 129
121 130 # sys.stderr.write(string.join(spec) + "\n")
122 131
123 132 self.allowAbbreviations = 1 # boolean, 1 if abbreviations will
124 133 # be expanded
125 134 self.freeValues = [] # list, contains free values
126 135 self.ignoreCase = 0 # boolean, YES if ignoring case
127 136 self.needsParse = 0 # boolean, YES if need to reparse parameter spec
128 137 self.optionNames = {} # dict, all option names-- value is index of tuple
129 138 self.optionStartExpr = None # regexp defining the start of an option (ie; '-', '--')
130 139 self.optionTuples = [] # list o' tuples containing defn of options AND aliases
131 140 self.optionValues = {} # dict, option names (after alias expansion) -> option value(s)
132 141 self.orderMixed = 0 # boolean, YES if options can be mixed with args
133 142 self.posixCompliance = 0 # boolean, YES indicates posix like behaviour
134 143 self.spec = [] # list, raw specs (in case it must be reparsed)
135 144 self.terminators = terminators # list, strings that terminate argument processing
136 145 self.termValues = [] # list, values after terminator
137 146 self.terminator = None # full name of terminator that ended
138 147 # option processing
139 148
140 149 # set up defaults
141 150 self.setPosixCompliance()
142 151 self.setIgnoreCase()
143 152 self.setAllowAbbreviations()
144 153
145 154 # parse spec-- if present
146 155 if spec:
147 156 self.parseConfiguration(spec)
148 157
149 158 def setPosixCompliance(self, aFlag = 0):
150 159 """
151 160 Enables and disables posix compliance.
152 161
153 162 When enabled, '+' can be used as an option prefix and free
154 163 values can be mixed with options.
155 164 """
156 165 self.posixCompliance = aFlag
157 166 self.needsParse = 1
158 167
159 168 if self.posixCompliance:
160 169 self.optionStartExpr = re.compile('(--|-)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?')
161 170 self.orderMixed = 0
162 171 else:
163 172 self.optionStartExpr = re.compile('(--|-|\+)(?P<option>[A-Za-z0-9_-]+)(?P<arg>=.*)?')
164 173 self.orderMixed = 1
165 174
166 175 def isPosixCompliant(self):
167 176 """
168 177 Returns the value of the posix compliance flag.
169 178 """
170 179 return self.posixCompliance
171 180
172 181 def setIgnoreCase(self, aFlag = 1):
173 182 """
174 183 Enables and disables ignoring case during option processing.
175 184 """
176 185 self.needsParse = 1
177 186 self.ignoreCase = aFlag
178 187
179 188 def ignoreCase(self):
180 189 """
181 190 Returns 1 if the option processor will ignore case when
182 191 processing options.
183 192 """
184 193 return self.ignoreCase
185 194
186 195 def setAllowAbbreviations(self, aFlag = 1):
187 196 """
188 197 Enables and disables the expansion of abbreviations during
189 198 option processing.
190 199 """
191 200 self.allowAbbreviations = aFlag
192 201
193 202 def willAllowAbbreviations(self):
194 203 """
195 204 Returns 1 if abbreviated options will be automatically
196 205 expanded to the non-abbreviated form (instead of causing an
197 206 unrecognized option error).
198 207 """
199 208 return self.allowAbbreviations
200 209
201 210 def addTerminator(self, newTerm):
202 211 """
203 212 Adds newTerm as terminator of option processing.
204 213
205 214 Whenever the option processor encounters one of the terminators
206 215 during option processing, the processing of options terminates
207 216 immediately, all remaining options are stored in the termValues
208 217 instance variable and the full name of the terminator is stored
209 218 in the terminator instance variable.
210 219 """
211 220 self.terminators = self.terminators + [newTerm]
212 221
213 222 def _addOption(self, oTuple):
214 223 """
215 224 Adds the option described by oTuple (name, (type, mode,
216 225 default), alias) to optionTuples. Adds index keyed under name
217 to optionNames. Raises spec_error if name already in
226 to optionNames. Raises SpecificationError if name already in
218 227 optionNames
219 228 """
220 229 (name, (type, mode, default, multi), realName) = oTuple
221 230
222 231 # verify name and add to option names dictionary
223 232 if self.optionNames.has_key(name):
224 233 if realName:
225 raise spec_error, 'Alias \'' + name + '\' for \'' + realName + \
226 '\' already used for another option or alias.'
234 raise SpecificationError('Alias \'' + name + '\' for \'' +
235 realName +
236 '\' already used for another option or alias.')
227 237 else:
228 raise spec_error, 'Option named \'' + name + \
229 '\' specified more than once. Specification: ' + option
238 raise SpecificationError('Option named \'' + name +
239 '\' specified more than once. Specification: '
240 + option)
230 241
231 242 # validated. add to optionNames
232 243 self.optionNames[name] = self.tupleIndex
233 244 self.tupleIndex = self.tupleIndex + 1
234 245
235 246 # add to optionTuples
236 247 self.optionTuples = self.optionTuples + [oTuple]
237 248
238 249 # if type is boolean, add negation
239 250 if type == BooleanArgType:
240 251 alias = 'no' + name
241 252 specTuple = (type, mode, 0, multi)
242 253 oTuple = (alias, specTuple, name)
243 254
244 255 # verify name and add to option names dictionary
245 256 if self.optionNames.has_key(alias):
246 257 if realName:
247 raise spec_error, 'Negated alias \'' + name + '\' for \'' + realName + \
248 '\' already used for another option or alias.'
258 raise SpecificationError('Negated alias \'' + name +
259 '\' for \'' + realName +
260 '\' already used for another option or alias.')
249 261 else:
250 raise spec_error, 'Negated option named \'' + name + \
251 '\' specified more than once. Specification: ' + option
262 raise SpecificationError('Negated option named \'' + name +
263 '\' specified more than once. Specification: '
264 + option)
252 265
253 266 # validated. add to optionNames
254 267 self.optionNames[alias] = self.tupleIndex
255 268 self.tupleIndex = self.tupleIndex + 1
256 269
257 270 # add to optionTuples
258 271 self.optionTuples = self.optionTuples + [oTuple]
259 272
260 273 def addOptionConfigurationTuple(self, oTuple):
261 274 (name, argSpec, realName) = oTuple
262 275 if self.ignoreCase:
263 276 name = string.lower(name)
264 277 if realName:
265 278 realName = string.lower(realName)
266 279 else:
267 280 realName = name
268 281
269 282 oTuple = (name, argSpec, realName)
270 283
271 284 # add option
272 285 self._addOption(oTuple)
273 286
274 287 def addOptionConfigurationTuples(self, oTuple):
275 288 if type(oTuple) is ListType:
276 289 for t in oTuple:
277 290 self.addOptionConfigurationTuple(t)
278 291 else:
279 292 self.addOptionConfigurationTuple(oTuple)
280 293
281 294 def parseConfiguration(self, spec):
282 295 # destroy previous stored information + store raw spec
283 296 self.spec = spec
284 297 self.optionTuples = []
285 298 self.optionNames = {}
286 299 self.tupleIndex = 0
287 300
288 301 tupleIndex = 0
289 302
290 303 # create some regex's for parsing each spec
291 304 splitExpr = \
292 305 re.compile('(?P<names>\w+[-A-Za-z0-9|]*)?(?P<spec>!|[=:][infs]@?)?')
293 306 for option in spec:
294 307 # push to lower case (does not negatively affect
295 308 # specification)
296 309 if self.ignoreCase:
297 310 option = string.lower(option)
298 311
299 312 # break into names, specification
300 313 match = splitExpr.match(option)
301 314 if match is None:
302 raise spec_error, 'Invalid specification {' + option + '}'
315 raise SpecificationError('Invalid specification {' + option +
316 '}')
303 317
304 318 names = match.group('names')
305 319 specification = match.group('spec')
306 320
307 321 # break name into name, aliases
308 322 nlist = string.split(names, '|')
309 323
310 324 # get name
311 325 name = nlist[0]
312 326 aliases = nlist[1:]
313 327
314 328 # specificationExpr = regex.symcomp('\(<required>.\)\(<type>.\)\(<multi>@?\)')
315 329 if not specification:
316 330 #spec tuple is ('type', 'arg mode', 'default value', 'multiple')
317 331 argType = GenericArgType
318 332 argMode = None
319 333 argDefault = 1
320 334 argMultiple = 0
321 335 elif specification == '!':
322 336 argType = BooleanArgType
323 337 argMode = None
324 338 argDefault = 1
325 339 argMultiple = 0
326 340 else:
327 341 # parse
328 342 match = specificationExpr.match(specification)
329 343 if match is None:
330 344 # failed to parse, die
331 raise spec_error, 'Invalid configuration for option \'' + option + '\''
345 raise SpecificationError('Invalid configuration for option \''
346 + option + '\'')
332 347
333 348 # determine mode
334 349 required = match.group('required')
335 350 if required == '=':
336 351 argMode = ArgRequired
337 352 elif required == ':':
338 353 argMode = ArgOptional
339 354 else:
340 raise spec_error, 'Unknown requirement configuration \'' + required + '\''
355 raise SpecificationError('Unknown requirement configuration \''
356 + required + '\'')
341 357
342 358 # determine type
343 359 type = match.group('type')
344 360 if type == 's':
345 361 argType = StringArgType
346 362 argDefault = ''
347 363 elif type == 'i':
348 364 argType = IntegerArgType
349 365 argDefault = 1
350 366 elif type == 'f' or type == 'n':
351 367 argType = RealArgType
352 368 argDefault = 1
353 369 else:
354 raise spec_error, 'Unknown type specifier \'' + type + '\''
370 raise SpecificationError('Unknown type specifier \'' +
371 type + '\'')
355 372
356 373 # determine quantity
357 374 if match.group('multi') == '@':
358 375 argMultiple = 1
359 376 else:
360 377 argMultiple = 0
361 378 ## end else (of not specification)
362 379
363 380 # construct specification tuple
364 381 specTuple = (argType, argMode, argDefault, argMultiple)
365 382
366 383 # add the option-- option tuple is (name, specTuple, real name)
367 384 oTuple = (name, specTuple, name)
368 385 self._addOption(oTuple)
369 386
370 387 for alias in aliases:
371 388 # drop to all lower (if configured to do so)
372 389 if self.ignoreCase:
373 390 alias = string.lower(alias)
374 391 # create configuration tuple
375 392 oTuple = (alias, specTuple, name)
376 393 # add
377 394 self._addOption(oTuple)
378 395
379 396 # successfully parsed....
380 397 self.needsParse = 0
381 398
382 399 def _getArgTuple(self, argName):
383 400 """
384 401 Returns a list containing all the specification tuples that
385 402 match argName. If none match, None is returned. If one
386 403 matches, a list with one tuple is returned. If more than one
387 404 match, a list containing all the tuples that matched is
388 405 returned.
389 406
390 407 In other words, this function does not pass judgement upon the
391 408 validity of multiple matches.
392 409 """
393 410 # is it in the optionNames dict?
394 411
395 412 try:
396 413 # sys.stderr.write(argName + string.join(self.optionNames.keys()) + "\n")
397 414
398 415 # yes, get index
399 416 tupleIndex = self.optionNames[argName]
400 417 # and return tuple as element of list
401 418 return [self.optionTuples[tupleIndex]]
402 419 except KeyError:
403 420 # are abbreviations allowed?
404 421 if not self.allowAbbreviations:
405 422 # No! terefore, this cannot be valid argument-- nothing found
406 423 return None
407 424
408 425 # argName might be an abbreviation (and, abbreviations must
409 426 # be allowed... or this would not have been reached!)
410 427
411 428 # create regex for argName
412 429 argExpr = re.compile('^' + argName)
413 430
414 431 tuples = filter(lambda x, argExpr=argExpr: argExpr.search(x[0]) is not None,
415 432 self.optionTuples)
416 433
417 434 if not len(tuples):
418 435 return None
419 436 else:
420 437 return tuples
421 438
422 439 def _isTerminator(self, optionName):
423 440 """
424 441 Returns the full name of the terminator if optionName is a valid
425 442 terminator. If it is, sets self.terminator to the full name of
426 443 the terminator.
427 444
428 If more than one terminator matched, raises a term_error with a
445 If more than one terminator matched, raises a TerminationError with a
429 446 string describing the ambiguity.
430 447 """
431 448
432 449 # sys.stderr.write(optionName + "\n")
433 450 # sys.stderr.write(repr(self.terminators))
434 451
435 452 if optionName in self.terminators:
436 453 self.terminator = optionName
437 454 elif not self.allowAbbreviations:
438 455 return None
439 456
440 457 # regex thing in bogus
441 458 # termExpr = regex.compile('^' + optionName)
442 459
443 460 terms = filter(lambda x, on=optionName: string.find(x,on) == 0, self.terminators)
444 461
445 462 if not len(terms):
446 463 return None
447 464 elif len(terms) > 1:
448 raise term_error, 'Ambiguous terminator \'' + optionName + \
449 '\' matches ' + repr(terms)
465 raise TerminationError('Ambiguous terminator \'' + optionName +
466 '\' matches ' + repr(terms))
450 467
451 468 self.terminator = terms[0]
452 469 return self.terminator
453 470
454 471 def processArguments(self, args = None):
455 472 """
456 473 Processes args, a list of arguments (including options).
457 474
458 475 If args is the same as sys.argv, automatically trims the first
459 476 argument (the executable name/path).
460 477
461 478 If an exception is not raised, the argument list was parsed
462 479 correctly.
463 480
464 481 Upon successful completion, the freeValues instance variable
465 482 will contain all the arguments that were not associated with an
466 483 option in the order they were encountered. optionValues is a
467 484 dictionary containing the value of each option-- the method
468 485 valueForOption() can be used to query this dictionary.
469 486 terminator will contain the argument encountered that terminated
470 487 option processing (or None, if a terminator was never
471 488 encountered) and termValues will contain all of the options that
472 489 appeared after the Terminator (or an empty list).
473 490 """
474 491
475 492 if hasattr(sys, "argv") and args == sys.argv:
476 493 args = sys.argv[1:]
477 494
478 495 max = len(args) # maximum index + 1
479 496 self.freeValues = [] # array to hold return values
480 497 self.optionValues= {}
481 498 index = 0 # initial index
482 499 self.terminator = None
483 500 self.termValues = []
484 501
485 502 while index < max:
486 503 # obtain argument
487 504 arg = args[index]
488 505 # increment index -- REMEMBER; it is NOW incremented
489 506 index = index + 1
490 507
491 508 # terminate immediately if option terminator encountered
492 509 if self._isTerminator(arg):
493 510 self.freeValues = self.freeValues + args[index:]
494 511 self.termValues = args[index:]
495 512 return
496 513
497 514 # is this possibly an option?
498 515 match = self.optionStartExpr.match(arg)
499 516 if match is None:
500 517 # not an option-- add to freeValues
501 518 self.freeValues = self.freeValues + [arg]
502 519 if not self.orderMixed:
503 520 # mixing not allowed; add rest of args as freeValues
504 521 self.freeValues = self.freeValues + args[index:]
505 522 # return to caller
506 523 return
507 524 else:
508 525 continue
509 526
510 527 # grab name
511 528 optName = match.group('option')
512 529
513 530 # obtain next argument-- index has already been incremented
514 531 nextArg = match.group('arg')
515 532 if nextArg:
516 533 nextArg = nextArg[1:]
517 534 index = index - 1 # put it back
518 535 else:
519 536 try:
520 537 nextArg = args[index]
521 538 except:
522 539 nextArg = None
523 540
524 541 # transpose to lower case, if necessary
525 542 if self.ignoreCase:
526 543 optName = string.lower(optName)
527 544
528 545 # obtain defining tuple
529 546 tuples = self._getArgTuple(optName)
530 547
531 548 if tuples == None:
532 raise arg_error, 'Illegal option \'' + arg + '\''
549 raise ArgumentError('Illegal option \'' + arg + '\'')
533 550 elif len(tuples) > 1:
534 raise arg_error, 'Ambiguous option \'' + arg + '\'; matches ' + \
535 repr(map(lambda x: x[0], tuples))
551 raise ArgumentError('Ambiguous option \'' + arg +
552 '\'; matches ' +
553 repr(map(lambda x: x[0], tuples)))
536 554 else:
537 555 config = tuples[0]
538 556
539 557 # config is now set to the configuration tuple for the
540 558 # argument
541 559 (fullName, spec, realName) = config
542 560 (optType, optMode, optDefault, optMultiple) = spec
543 561
544 562 # if opt mode required, but nextArg is none, raise an error
545 563 if (optMode == ArgRequired):
546 564 if (not nextArg) or self._isTerminator(nextArg):
547 565 # print nextArg
548 raise arg_error, 'Option \'' + arg + \
549 '\' requires an argument of type ' + optType
566 raise ArgumentError('Option \'' + arg +
567 '\' requires an argument of type ' +
568 optType)
550 569
551 570 if (not optMode == None) and nextArg and (not self._isTerminator(nextArg)):
552 571 # nextArg defined, option configured to possibly consume arg
553 572 try:
554 573 # grab conversion function-- the try is more for internal diagnostics
555 574 func = ConversionFunctions[optType]
556 575 try:
557 576 optionValue = func(nextArg)
558 577 index = index + 1
559 578 except:
560 579 # only raise conversion error if REQUIRED to consume argument
561 580 if optMode == ArgRequired:
562 raise arg_error, 'Invalid argument to option \'' + arg + \
563 '\'; should be \'' + optType + '\''
581 raise ArgumentError('Invalid argument to option \''
582 + arg + '\'; should be \'' +
583 optType + '\'')
564 584 else:
565 585 optionValue = optDefault
566 except arg_error:
567 raise arg_error, sys.exc_value
586 except ArgumentError:
587 raise
568 588 except:
569 raise arg_error, '(' + arg + \
570 ') Conversion function for \'' + optType + '\' not found.'
589 raise ArgumentError('(' + arg +
590 ') Conversion function for \'' +
591 optType + '\' not found.')
571 592 else:
572 593 optionValue = optDefault
573 594
574 595 # add value to options dictionary
575 596 if optMultiple:
576 597 # can be multiple values
577 598 try:
578 599 # try to append element
579 600 self.optionValues[realName] = self.optionValues[realName] + [optionValue]
580 601 except:
581 602 # failed-- must not exist; add it
582 603 self.optionValues[realName] = [optionValue]
583 604 else:
584 605 # only one value per
585 606 if self.isPosixCompliant and self.optionValues.has_key(realName):
586 raise arg_error, 'Argument \'' + arg + '\' occurs multiple times.'
607 raise ArgumentError('Argument \'' + arg +
608 '\' occurs multiple times.')
587 609
588 610 self.optionValues[realName] = optionValue
589 611
590 612 def valueForOption(self, optionName, defaultValue = None):
591 613 """
592 614 Return the value associated with optionName. If optionName was
593 615 not encountered during parsing of the arguments, returns the
594 616 defaultValue (which defaults to None).
595 617 """
596 618 try:
597 619 optionValue = self.optionValues[optionName]
598 620 except:
599 621 optionValue = defaultValue
600 622
601 623 return optionValue
602 624
603 625 ##
604 626 ## test/example section
605 627 ##
606 628 test_error = 'Test Run Amok!'
607 629 def _test():
608 630 """
609 631 A relatively complete test suite.
610 632 """
611 633 try:
612 634 DPyGetOpt(['foo', 'bar=s', 'foo'])
613 except:
614 print 'EXCEPTION (should be \'foo\' already used..): ' + sys.exc_value
635 except Error, exc:
636 print 'EXCEPTION (should be \'foo\' already used..): %s' % exc
615 637
616 638 try:
617 639 DPyGetOpt(['foo|bar|apple=s@', 'baz|apple!'])
618 except:
619 print 'EXCEPTION (should be duplicate alias/name error): ' + sys.exc_value
640 except Error, exc:
641 print 'EXCEPTION (should be duplicate alias/name error): %s' % exc
620 642
621 643 x = DPyGetOpt(['apple|atlas=i@', 'application|executable=f@'])
622 644 try:
623 645 x.processArguments(['-app', '29.3'])
624 except:
625 print 'EXCEPTION (should be ambiguous argument): ' + sys.exc_value
646 except Error, exc:
647 print 'EXCEPTION (should be ambiguous argument): %s' % exc
626 648
627 649 x = DPyGetOpt(['foo'], ['antigravity', 'antithesis'])
628 650 try:
629 651 x.processArguments(['-foo', 'anti'])
630 except:
631 print 'EXCEPTION (should be ambiguous terminator): ' + sys.exc_value
652 except Error, exc:
653 print 'EXCEPTION (should be ambiguous terminator): %s' % exc
632 654
633 655 profile = ['plain-option',
634 656 'boolean-option!',
635 657 'list-of-integers=i@',
636 658 'list-real-option|list-real-alias|list-real-pseudonym=f@',
637 659 'optional-string-option:s',
638 660 'abbreviated-string-list=s@']
639 661
640 662 terminators = ['terminator']
641 663
642 664 args = ['-plain-option',
643 665 '+noboolean-option',
644 666 '--list-of-integers', '1',
645 667 '+list-of-integers', '2',
646 668 '-list-of-integers', '3',
647 669 'freeargone',
648 670 '-list-real-option', '1.1',
649 671 '+list-real-alias', '1.2',
650 672 '--list-real-pseudonym', '1.3',
651 673 'freeargtwo',
652 674 '-abbreviated-string-list', 'String1',
653 675 '--abbreviated-s', 'String2',
654 676 '-abbrev', 'String3',
655 677 '-a', 'String4',
656 678 '-optional-string-option',
657 679 'term',
658 680 'next option should look like an invalid arg',
659 681 '-a']
660 682
661 683
662 684 print 'Using profile: ' + repr(profile)
663 685 print 'With terminator: ' + repr(terminators)
664 686 print 'Processing arguments: ' + repr(args)
665 687
666 688 go = DPyGetOpt(profile, terminators)
667 689 go.processArguments(args)
668 690
669 691 print 'Options (and values): ' + repr(go.optionValues)
670 692 print 'free args: ' + repr(go.freeValues)
671 693 print 'term args: ' + repr(go.termValues)
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,1984 +1,1984 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 General purpose utilities.
4 4
5 5 This is a grab-bag of stuff I find useful in most programs I write. Some of
6 6 these things are also convenient when working at the command line.
7 7
8 $Id: genutils.py 2847 2007-10-24 15:16:24Z vivainio $"""
8 $Id: genutils.py 2872 2007-11-25 17:58:05Z fperez $"""
9 9
10 10 #*****************************************************************************
11 11 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
12 12 #
13 13 # Distributed under the terms of the BSD License. The full license is in
14 14 # the file COPYING, distributed as part of this software.
15 15 #*****************************************************************************
16 16
17 17 from IPython import Release
18 18 __author__ = '%s <%s>' % Release.authors['Fernando']
19 19 __license__ = Release.license
20 20
21 21 #****************************************************************************
22 22 # required modules from the Python standard library
23 23 import __main__
24 24 import commands
25 25 import doctest
26 26 import os
27 27 import re
28 28 import shlex
29 29 import shutil
30 30 import sys
31 31 import tempfile
32 32 import time
33 33 import types
34 34 import warnings
35 35
36 36 # Other IPython utilities
37 37 import IPython
38 38 from IPython.Itpl import Itpl,itpl,printpl
39 39 from IPython import DPyGetOpt, platutils
40 40 from IPython.generics import result_display
41 41 from path import path
42 42 if os.name == "nt":
43 43 from IPython.winconsole import get_console_size
44 44
45 45 #****************************************************************************
46 46 # Exceptions
47 47 class Error(Exception):
48 48 """Base class for exceptions in this module."""
49 49 pass
50 50
51 51 #----------------------------------------------------------------------------
52 52 class IOStream:
53 53 def __init__(self,stream,fallback):
54 54 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
55 55 stream = fallback
56 56 self.stream = stream
57 57 self._swrite = stream.write
58 58 self.flush = stream.flush
59 59
60 60 def write(self,data):
61 61 try:
62 62 self._swrite(data)
63 63 except:
64 64 try:
65 65 # print handles some unicode issues which may trip a plain
66 66 # write() call. Attempt to emulate write() by using a
67 67 # trailing comma
68 68 print >> self.stream, data,
69 69 except:
70 70 # if we get here, something is seriously broken.
71 71 print >> sys.stderr, \
72 72 'ERROR - failed to write data to stream:', self.stream
73 73
74 74 def close(self):
75 75 pass
76 76
77 77
78 78 class IOTerm:
79 79 """ Term holds the file or file-like objects for handling I/O operations.
80 80
81 81 These are normally just sys.stdin, sys.stdout and sys.stderr but for
82 82 Windows they can can replaced to allow editing the strings before they are
83 83 displayed."""
84 84
85 85 # In the future, having IPython channel all its I/O operations through
86 86 # this class will make it easier to embed it into other environments which
87 87 # are not a normal terminal (such as a GUI-based shell)
88 88 def __init__(self,cin=None,cout=None,cerr=None):
89 89 self.cin = IOStream(cin,sys.stdin)
90 90 self.cout = IOStream(cout,sys.stdout)
91 91 self.cerr = IOStream(cerr,sys.stderr)
92 92
93 93 # Global variable to be used for all I/O
94 94 Term = IOTerm()
95 95
96 96 import IPython.rlineimpl as readline
97 97 # Remake Term to use the readline i/o facilities
98 98 if sys.platform == 'win32' and readline.have_readline:
99 99
100 100 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
101 101
102 102
103 103 #****************************************************************************
104 104 # Generic warning/error printer, used by everything else
105 105 def warn(msg,level=2,exit_val=1):
106 106 """Standard warning printer. Gives formatting consistency.
107 107
108 108 Output is sent to Term.cerr (sys.stderr by default).
109 109
110 110 Options:
111 111
112 112 -level(2): allows finer control:
113 113 0 -> Do nothing, dummy function.
114 114 1 -> Print message.
115 115 2 -> Print 'WARNING:' + message. (Default level).
116 116 3 -> Print 'ERROR:' + message.
117 117 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
118 118
119 119 -exit_val (1): exit value returned by sys.exit() for a level 4
120 120 warning. Ignored for all other levels."""
121 121
122 122 if level>0:
123 123 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
124 124 print >> Term.cerr, '%s%s' % (header[level],msg)
125 125 if level == 4:
126 126 print >> Term.cerr,'Exiting.\n'
127 127 sys.exit(exit_val)
128 128
129 129 def info(msg):
130 130 """Equivalent to warn(msg,level=1)."""
131 131
132 132 warn(msg,level=1)
133 133
134 134 def error(msg):
135 135 """Equivalent to warn(msg,level=3)."""
136 136
137 137 warn(msg,level=3)
138 138
139 139 def fatal(msg,exit_val=1):
140 140 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
141 141
142 142 warn(msg,exit_val=exit_val,level=4)
143 143
144 144 #---------------------------------------------------------------------------
145 145 # Debugging routines
146 146 #
147 147 def debugx(expr,pre_msg=''):
148 148 """Print the value of an expression from the caller's frame.
149 149
150 150 Takes an expression, evaluates it in the caller's frame and prints both
151 151 the given expression and the resulting value (as well as a debug mark
152 152 indicating the name of the calling function. The input must be of a form
153 153 suitable for eval().
154 154
155 155 An optional message can be passed, which will be prepended to the printed
156 156 expr->value pair."""
157 157
158 158 cf = sys._getframe(1)
159 159 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
160 160 eval(expr,cf.f_globals,cf.f_locals))
161 161
162 162 # deactivate it by uncommenting the following line, which makes it a no-op
163 163 #def debugx(expr,pre_msg=''): pass
164 164
165 165 #----------------------------------------------------------------------------
166 166 StringTypes = types.StringTypes
167 167
168 168 # Basic timing functionality
169 169
170 170 # If possible (Unix), use the resource module instead of time.clock()
171 171 try:
172 172 import resource
173 173 def clocku():
174 174 """clocku() -> floating point number
175 175
176 176 Return the *USER* CPU time in seconds since the start of the process.
177 177 This is done via a call to resource.getrusage, so it avoids the
178 178 wraparound problems in time.clock()."""
179 179
180 180 return resource.getrusage(resource.RUSAGE_SELF)[0]
181 181
182 182 def clocks():
183 183 """clocks() -> floating point number
184 184
185 185 Return the *SYSTEM* CPU time in seconds since the start of the process.
186 186 This is done via a call to resource.getrusage, so it avoids the
187 187 wraparound problems in time.clock()."""
188 188
189 189 return resource.getrusage(resource.RUSAGE_SELF)[1]
190 190
191 191 def clock():
192 192 """clock() -> floating point number
193 193
194 194 Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
195 195 the process. This is done via a call to resource.getrusage, so it
196 196 avoids the wraparound problems in time.clock()."""
197 197
198 198 u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
199 199 return u+s
200 200
201 201 def clock2():
202 202 """clock2() -> (t_user,t_system)
203 203
204 204 Similar to clock(), but return a tuple of user/system times."""
205 205 return resource.getrusage(resource.RUSAGE_SELF)[:2]
206 206
207 207 except ImportError:
208 208 # There is no distinction of user/system time under windows, so we just use
209 209 # time.clock() for everything...
210 210 clocku = clocks = clock = time.clock
211 211 def clock2():
212 212 """Under windows, system CPU time can't be measured.
213 213
214 214 This just returns clock() and zero."""
215 215 return time.clock(),0.0
216 216
217 217 def timings_out(reps,func,*args,**kw):
218 218 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
219 219
220 220 Execute a function reps times, return a tuple with the elapsed total
221 221 CPU time in seconds, the time per call and the function's output.
222 222
223 223 Under Unix, the return value is the sum of user+system time consumed by
224 224 the process, computed via the resource module. This prevents problems
225 225 related to the wraparound effect which the time.clock() function has.
226 226
227 227 Under Windows the return value is in wall clock seconds. See the
228 228 documentation for the time module for more details."""
229 229
230 230 reps = int(reps)
231 231 assert reps >=1, 'reps must be >= 1'
232 232 if reps==1:
233 233 start = clock()
234 234 out = func(*args,**kw)
235 235 tot_time = clock()-start
236 236 else:
237 237 rng = xrange(reps-1) # the last time is executed separately to store output
238 238 start = clock()
239 239 for dummy in rng: func(*args,**kw)
240 240 out = func(*args,**kw) # one last time
241 241 tot_time = clock()-start
242 242 av_time = tot_time / reps
243 243 return tot_time,av_time,out
244 244
245 245 def timings(reps,func,*args,**kw):
246 246 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
247 247
248 248 Execute a function reps times, return a tuple with the elapsed total CPU
249 249 time in seconds and the time per call. These are just the first two values
250 250 in timings_out()."""
251 251
252 252 return timings_out(reps,func,*args,**kw)[0:2]
253 253
254 254 def timing(func,*args,**kw):
255 255 """timing(func,*args,**kw) -> t_total
256 256
257 257 Execute a function once, return the elapsed total CPU time in
258 258 seconds. This is just the first value in timings_out()."""
259 259
260 260 return timings_out(1,func,*args,**kw)[0]
261 261
262 262 #****************************************************************************
263 263 # file and system
264 264
265 265 def arg_split(s,posix=False):
266 266 """Split a command line's arguments in a shell-like manner.
267 267
268 268 This is a modified version of the standard library's shlex.split()
269 269 function, but with a default of posix=False for splitting, so that quotes
270 270 in inputs are respected."""
271 271
272 272 # XXX - there may be unicode-related problems here!!! I'm not sure that
273 273 # shlex is truly unicode-safe, so it might be necessary to do
274 274 #
275 275 # s = s.encode(sys.stdin.encoding)
276 276 #
277 277 # first, to ensure that shlex gets a normal string. Input from anyone who
278 278 # knows more about unicode and shlex than I would be good to have here...
279 279 lex = shlex.shlex(s, posix=posix)
280 280 lex.whitespace_split = True
281 281 return list(lex)
282 282
283 283 def system(cmd,verbose=0,debug=0,header=''):
284 284 """Execute a system command, return its exit status.
285 285
286 286 Options:
287 287
288 288 - verbose (0): print the command to be executed.
289 289
290 290 - debug (0): only print, do not actually execute.
291 291
292 292 - header (''): Header to print on screen prior to the executed command (it
293 293 is only prepended to the command, no newlines are added).
294 294
295 295 Note: a stateful version of this function is available through the
296 296 SystemExec class."""
297 297
298 298 stat = 0
299 299 if verbose or debug: print header+cmd
300 300 sys.stdout.flush()
301 301 if not debug: stat = os.system(cmd)
302 302 return stat
303 303
304 304 def abbrev_cwd():
305 305 """ Return abbreviated version of cwd, e.g. d:mydir """
306 306 cwd = os.getcwd()
307 307 drivepart = ''
308 308 if sys.platform == 'win32':
309 309 if len(cwd) < 4:
310 310 return cwd
311 311 drivepart = os.path.splitdrive(cwd)[0]
312 312 return (drivepart + (
313 313 cwd == '/' and '/' or \
314 314 os.path.basename(cwd)))
315 315
316 316
317 317 # This function is used by ipython in a lot of places to make system calls.
318 318 # We need it to be slightly different under win32, due to the vagaries of
319 319 # 'network shares'. A win32 override is below.
320 320
321 321 def shell(cmd,verbose=0,debug=0,header=''):
322 322 """Execute a command in the system shell, always return None.
323 323
324 324 Options:
325 325
326 326 - verbose (0): print the command to be executed.
327 327
328 328 - debug (0): only print, do not actually execute.
329 329
330 330 - header (''): Header to print on screen prior to the executed command (it
331 331 is only prepended to the command, no newlines are added).
332 332
333 333 Note: this is similar to genutils.system(), but it returns None so it can
334 334 be conveniently used in interactive loops without getting the return value
335 335 (typically 0) printed many times."""
336 336
337 337 stat = 0
338 338 if verbose or debug: print header+cmd
339 339 # flush stdout so we don't mangle python's buffering
340 340 sys.stdout.flush()
341 341
342 342 if not debug:
343 343 platutils.set_term_title("IPy " + cmd)
344 344 os.system(cmd)
345 345 platutils.set_term_title("IPy " + abbrev_cwd())
346 346
347 347 # override shell() for win32 to deal with network shares
348 348 if os.name in ('nt','dos'):
349 349
350 350 shell_ori = shell
351 351
352 352 def shell(cmd,verbose=0,debug=0,header=''):
353 353 if os.getcwd().startswith(r"\\"):
354 354 path = os.getcwd()
355 355 # change to c drive (cannot be on UNC-share when issuing os.system,
356 356 # as cmd.exe cannot handle UNC addresses)
357 357 os.chdir("c:")
358 358 # issue pushd to the UNC-share and then run the command
359 359 try:
360 360 shell_ori('"pushd %s&&"'%path+cmd,verbose,debug,header)
361 361 finally:
362 362 os.chdir(path)
363 363 else:
364 364 shell_ori(cmd,verbose,debug,header)
365 365
366 366 shell.__doc__ = shell_ori.__doc__
367 367
368 368 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
369 369 """Dummy substitute for perl's backquotes.
370 370
371 371 Executes a command and returns the output.
372 372
373 373 Accepts the same arguments as system(), plus:
374 374
375 375 - split(0): if true, the output is returned as a list split on newlines.
376 376
377 377 Note: a stateful version of this function is available through the
378 378 SystemExec class.
379 379
380 380 This is pretty much deprecated and rarely used,
381 381 genutils.getoutputerror may be what you need.
382 382
383 383 """
384 384
385 385 if verbose or debug: print header+cmd
386 386 if not debug:
387 387 output = os.popen(cmd).read()
388 388 # stipping last \n is here for backwards compat.
389 389 if output.endswith('\n'):
390 390 output = output[:-1]
391 391 if split:
392 392 return output.split('\n')
393 393 else:
394 394 return output
395 395
396 396 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
397 397 """Return (standard output,standard error) of executing cmd in a shell.
398 398
399 399 Accepts the same arguments as system(), plus:
400 400
401 401 - split(0): if true, each of stdout/err is returned as a list split on
402 402 newlines.
403 403
404 404 Note: a stateful version of this function is available through the
405 405 SystemExec class."""
406 406
407 407 if verbose or debug: print header+cmd
408 408 if not cmd:
409 409 if split:
410 410 return [],[]
411 411 else:
412 412 return '',''
413 413 if not debug:
414 414 pin,pout,perr = os.popen3(cmd)
415 415 tout = pout.read().rstrip()
416 416 terr = perr.read().rstrip()
417 417 pin.close()
418 418 pout.close()
419 419 perr.close()
420 420 if split:
421 421 return tout.split('\n'),terr.split('\n')
422 422 else:
423 423 return tout,terr
424 424
425 425 # for compatibility with older naming conventions
426 426 xsys = system
427 427 bq = getoutput
428 428
429 429 class SystemExec:
430 430 """Access the system and getoutput functions through a stateful interface.
431 431
432 432 Note: here we refer to the system and getoutput functions from this
433 433 library, not the ones from the standard python library.
434 434
435 435 This class offers the system and getoutput functions as methods, but the
436 436 verbose, debug and header parameters can be set for the instance (at
437 437 creation time or later) so that they don't need to be specified on each
438 438 call.
439 439
440 440 For efficiency reasons, there's no way to override the parameters on a
441 441 per-call basis other than by setting instance attributes. If you need
442 442 local overrides, it's best to directly call system() or getoutput().
443 443
444 444 The following names are provided as alternate options:
445 445 - xsys: alias to system
446 446 - bq: alias to getoutput
447 447
448 448 An instance can then be created as:
449 449 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
450 450
451 451 And used as:
452 452 >>> sysexec.xsys('pwd')
453 453 >>> dirlist = sysexec.bq('ls -l')
454 454 """
455 455
456 456 def __init__(self,verbose=0,debug=0,header='',split=0):
457 457 """Specify the instance's values for verbose, debug and header."""
458 458 setattr_list(self,'verbose debug header split')
459 459
460 460 def system(self,cmd):
461 461 """Stateful interface to system(), with the same keyword parameters."""
462 462
463 463 system(cmd,self.verbose,self.debug,self.header)
464 464
465 465 def shell(self,cmd):
466 466 """Stateful interface to shell(), with the same keyword parameters."""
467 467
468 468 shell(cmd,self.verbose,self.debug,self.header)
469 469
470 470 xsys = system # alias
471 471
472 472 def getoutput(self,cmd):
473 473 """Stateful interface to getoutput()."""
474 474
475 475 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
476 476
477 477 def getoutputerror(self,cmd):
478 478 """Stateful interface to getoutputerror()."""
479 479
480 480 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
481 481
482 482 bq = getoutput # alias
483 483
484 484 #-----------------------------------------------------------------------------
485 485 def mutex_opts(dict,ex_op):
486 486 """Check for presence of mutually exclusive keys in a dict.
487 487
488 488 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
489 489 for op1,op2 in ex_op:
490 490 if op1 in dict and op2 in dict:
491 491 raise ValueError,'\n*** ERROR in Arguments *** '\
492 492 'Options '+op1+' and '+op2+' are mutually exclusive.'
493 493
494 494 #-----------------------------------------------------------------------------
495 495 def get_py_filename(name):
496 496 """Return a valid python filename in the current directory.
497 497
498 498 If the given name is not a file, it adds '.py' and searches again.
499 499 Raises IOError with an informative message if the file isn't found."""
500 500
501 501 name = os.path.expanduser(name)
502 502 if not os.path.isfile(name) and not name.endswith('.py'):
503 503 name += '.py'
504 504 if os.path.isfile(name):
505 505 return name
506 506 else:
507 507 raise IOError,'File `%s` not found.' % name
508 508
509 509 #-----------------------------------------------------------------------------
510 510 def filefind(fname,alt_dirs = None):
511 511 """Return the given filename either in the current directory, if it
512 512 exists, or in a specified list of directories.
513 513
514 514 ~ expansion is done on all file and directory names.
515 515
516 516 Upon an unsuccessful search, raise an IOError exception."""
517 517
518 518 if alt_dirs is None:
519 519 try:
520 520 alt_dirs = get_home_dir()
521 521 except HomeDirError:
522 522 alt_dirs = os.getcwd()
523 523 search = [fname] + list_strings(alt_dirs)
524 524 search = map(os.path.expanduser,search)
525 525 #print 'search list for',fname,'list:',search # dbg
526 526 fname = search[0]
527 527 if os.path.isfile(fname):
528 528 return fname
529 529 for direc in search[1:]:
530 530 testname = os.path.join(direc,fname)
531 531 #print 'testname',testname # dbg
532 532 if os.path.isfile(testname):
533 533 return testname
534 534 raise IOError,'File' + `fname` + \
535 535 ' not found in current or supplied directories:' + `alt_dirs`
536 536
537 537 #----------------------------------------------------------------------------
538 538 def file_read(filename):
539 539 """Read a file and close it. Returns the file source."""
540 540 fobj = open(filename,'r');
541 541 source = fobj.read();
542 542 fobj.close()
543 543 return source
544 544
545 545 def file_readlines(filename):
546 546 """Read a file and close it. Returns the file source using readlines()."""
547 547 fobj = open(filename,'r');
548 548 lines = fobj.readlines();
549 549 fobj.close()
550 550 return lines
551 551
552 552 #----------------------------------------------------------------------------
553 553 def target_outdated(target,deps):
554 554 """Determine whether a target is out of date.
555 555
556 556 target_outdated(target,deps) -> 1/0
557 557
558 558 deps: list of filenames which MUST exist.
559 559 target: single filename which may or may not exist.
560 560
561 561 If target doesn't exist or is older than any file listed in deps, return
562 562 true, otherwise return false.
563 563 """
564 564 try:
565 565 target_time = os.path.getmtime(target)
566 566 except os.error:
567 567 return 1
568 568 for dep in deps:
569 569 dep_time = os.path.getmtime(dep)
570 570 if dep_time > target_time:
571 571 #print "For target",target,"Dep failed:",dep # dbg
572 572 #print "times (dep,tar):",dep_time,target_time # dbg
573 573 return 1
574 574 return 0
575 575
576 576 #-----------------------------------------------------------------------------
577 577 def target_update(target,deps,cmd):
578 578 """Update a target with a given command given a list of dependencies.
579 579
580 580 target_update(target,deps,cmd) -> runs cmd if target is outdated.
581 581
582 582 This is just a wrapper around target_outdated() which calls the given
583 583 command if target is outdated."""
584 584
585 585 if target_outdated(target,deps):
586 586 xsys(cmd)
587 587
588 588 #----------------------------------------------------------------------------
589 589 def unquote_ends(istr):
590 590 """Remove a single pair of quotes from the endpoints of a string."""
591 591
592 592 if not istr:
593 593 return istr
594 594 if (istr[0]=="'" and istr[-1]=="'") or \
595 595 (istr[0]=='"' and istr[-1]=='"'):
596 596 return istr[1:-1]
597 597 else:
598 598 return istr
599 599
600 600 #----------------------------------------------------------------------------
601 601 def process_cmdline(argv,names=[],defaults={},usage=''):
602 602 """ Process command-line options and arguments.
603 603
604 604 Arguments:
605 605
606 606 - argv: list of arguments, typically sys.argv.
607 607
608 608 - names: list of option names. See DPyGetOpt docs for details on options
609 609 syntax.
610 610
611 611 - defaults: dict of default values.
612 612
613 613 - usage: optional usage notice to print if a wrong argument is passed.
614 614
615 615 Return a dict of options and a list of free arguments."""
616 616
617 617 getopt = DPyGetOpt.DPyGetOpt()
618 618 getopt.setIgnoreCase(0)
619 619 getopt.parseConfiguration(names)
620 620
621 621 try:
622 622 getopt.processArguments(argv)
623 except:
623 except DPyGetOpt.ArgumentError, exc:
624 624 print usage
625 warn(`sys.exc_value`,level=4)
625 warn('"%s"' % exc,level=4)
626 626
627 627 defaults.update(getopt.optionValues)
628 628 args = getopt.freeValues
629 629
630 630 return defaults,args
631 631
632 632 #----------------------------------------------------------------------------
633 633 def optstr2types(ostr):
634 634 """Convert a string of option names to a dict of type mappings.
635 635
636 636 optstr2types(str) -> {None:'string_opts',int:'int_opts',float:'float_opts'}
637 637
638 638 This is used to get the types of all the options in a string formatted
639 639 with the conventions of DPyGetOpt. The 'type' None is used for options
640 640 which are strings (they need no further conversion). This function's main
641 641 use is to get a typemap for use with read_dict().
642 642 """
643 643
644 644 typeconv = {None:'',int:'',float:''}
645 645 typemap = {'s':None,'i':int,'f':float}
646 646 opt_re = re.compile(r'([\w]*)([^:=]*:?=?)([sif]?)')
647 647
648 648 for w in ostr.split():
649 649 oname,alias,otype = opt_re.match(w).groups()
650 650 if otype == '' or alias == '!': # simple switches are integers too
651 651 otype = 'i'
652 652 typeconv[typemap[otype]] += oname + ' '
653 653 return typeconv
654 654
655 655 #----------------------------------------------------------------------------
656 656 def read_dict(filename,type_conv=None,**opt):
657 657
658 658 """Read a dictionary of key=value pairs from an input file, optionally
659 659 performing conversions on the resulting values.
660 660
661 661 read_dict(filename,type_conv,**opt) -> dict
662 662
663 663 Only one value per line is accepted, the format should be
664 664 # optional comments are ignored
665 665 key value\n
666 666
667 667 Args:
668 668
669 669 - type_conv: A dictionary specifying which keys need to be converted to
670 670 which types. By default all keys are read as strings. This dictionary
671 671 should have as its keys valid conversion functions for strings
672 672 (int,long,float,complex, or your own). The value for each key
673 673 (converter) should be a whitespace separated string containing the names
674 674 of all the entries in the file to be converted using that function. For
675 675 keys to be left alone, use None as the conversion function (only needed
676 676 with purge=1, see below).
677 677
678 678 - opt: dictionary with extra options as below (default in parens)
679 679
680 680 purge(0): if set to 1, all keys *not* listed in type_conv are purged out
681 681 of the dictionary to be returned. If purge is going to be used, the
682 682 set of keys to be left as strings also has to be explicitly specified
683 683 using the (non-existent) conversion function None.
684 684
685 685 fs(None): field separator. This is the key/value separator to be used
686 686 when parsing the file. The None default means any whitespace [behavior
687 687 of string.split()].
688 688
689 689 strip(0): if 1, strip string values of leading/trailinig whitespace.
690 690
691 691 warn(1): warning level if requested keys are not found in file.
692 692 - 0: silently ignore.
693 693 - 1: inform but proceed.
694 694 - 2: raise KeyError exception.
695 695
696 696 no_empty(0): if 1, remove keys with whitespace strings as a value.
697 697
698 698 unique([]): list of keys (or space separated string) which can't be
699 699 repeated. If one such key is found in the file, each new instance
700 700 overwrites the previous one. For keys not listed here, the behavior is
701 701 to make a list of all appearances.
702 702
703 703 Example:
704 704 If the input file test.ini has:
705 705 i 3
706 706 x 4.5
707 707 y 5.5
708 708 s hi ho
709 709 Then:
710 710
711 711 >>> type_conv={int:'i',float:'x',None:'s'}
712 712 >>> read_dict('test.ini')
713 713 {'i': '3', 's': 'hi ho', 'x': '4.5', 'y': '5.5'}
714 714 >>> read_dict('test.ini',type_conv)
715 715 {'i': 3, 's': 'hi ho', 'x': 4.5, 'y': '5.5'}
716 716 >>> read_dict('test.ini',type_conv,purge=1)
717 717 {'i': 3, 's': 'hi ho', 'x': 4.5}
718 718 """
719 719
720 720 # starting config
721 721 opt.setdefault('purge',0)
722 722 opt.setdefault('fs',None) # field sep defaults to any whitespace
723 723 opt.setdefault('strip',0)
724 724 opt.setdefault('warn',1)
725 725 opt.setdefault('no_empty',0)
726 726 opt.setdefault('unique','')
727 727 if type(opt['unique']) in StringTypes:
728 728 unique_keys = qw(opt['unique'])
729 729 elif type(opt['unique']) in (types.TupleType,types.ListType):
730 730 unique_keys = opt['unique']
731 731 else:
732 732 raise ValueError, 'Unique keys must be given as a string, List or Tuple'
733 733
734 734 dict = {}
735 735 # first read in table of values as strings
736 736 file = open(filename,'r')
737 737 for line in file.readlines():
738 738 line = line.strip()
739 739 if len(line) and line[0]=='#': continue
740 740 if len(line)>0:
741 741 lsplit = line.split(opt['fs'],1)
742 742 try:
743 743 key,val = lsplit
744 744 except ValueError:
745 745 key,val = lsplit[0],''
746 746 key = key.strip()
747 747 if opt['strip']: val = val.strip()
748 748 if val == "''" or val == '""': val = ''
749 749 if opt['no_empty'] and (val=='' or val.isspace()):
750 750 continue
751 751 # if a key is found more than once in the file, build a list
752 752 # unless it's in the 'unique' list. In that case, last found in file
753 753 # takes precedence. User beware.
754 754 try:
755 755 if dict[key] and key in unique_keys:
756 756 dict[key] = val
757 757 elif type(dict[key]) is types.ListType:
758 758 dict[key].append(val)
759 759 else:
760 760 dict[key] = [dict[key],val]
761 761 except KeyError:
762 762 dict[key] = val
763 763 # purge if requested
764 764 if opt['purge']:
765 765 accepted_keys = qwflat(type_conv.values())
766 766 for key in dict.keys():
767 767 if key in accepted_keys: continue
768 768 del(dict[key])
769 769 # now convert if requested
770 770 if type_conv==None: return dict
771 771 conversions = type_conv.keys()
772 772 try: conversions.remove(None)
773 773 except: pass
774 774 for convert in conversions:
775 775 for val in qw(type_conv[convert]):
776 776 try:
777 777 dict[val] = convert(dict[val])
778 778 except KeyError,e:
779 779 if opt['warn'] == 0:
780 780 pass
781 781 elif opt['warn'] == 1:
782 782 print >>sys.stderr, 'Warning: key',val,\
783 783 'not found in file',filename
784 784 elif opt['warn'] == 2:
785 785 raise KeyError,e
786 786 else:
787 787 raise ValueError,'Warning level must be 0,1 or 2'
788 788
789 789 return dict
790 790
791 791 #----------------------------------------------------------------------------
792 792 def flag_calls(func):
793 793 """Wrap a function to detect and flag when it gets called.
794 794
795 795 This is a decorator which takes a function and wraps it in a function with
796 796 a 'called' attribute. wrapper.called is initialized to False.
797 797
798 798 The wrapper.called attribute is set to False right before each call to the
799 799 wrapped function, so if the call fails it remains False. After the call
800 800 completes, wrapper.called is set to True and the output is returned.
801 801
802 802 Testing for truth in wrapper.called allows you to determine if a call to
803 803 func() was attempted and succeeded."""
804 804
805 805 def wrapper(*args,**kw):
806 806 wrapper.called = False
807 807 out = func(*args,**kw)
808 808 wrapper.called = True
809 809 return out
810 810
811 811 wrapper.called = False
812 812 wrapper.__doc__ = func.__doc__
813 813 return wrapper
814 814
815 815 #----------------------------------------------------------------------------
816 816 def dhook_wrap(func,*a,**k):
817 817 """Wrap a function call in a sys.displayhook controller.
818 818
819 819 Returns a wrapper around func which calls func, with all its arguments and
820 820 keywords unmodified, using the default sys.displayhook. Since IPython
821 821 modifies sys.displayhook, it breaks the behavior of certain systems that
822 822 rely on the default behavior, notably doctest.
823 823 """
824 824
825 825 def f(*a,**k):
826 826
827 827 dhook_s = sys.displayhook
828 828 sys.displayhook = sys.__displayhook__
829 829 try:
830 830 out = func(*a,**k)
831 831 finally:
832 832 sys.displayhook = dhook_s
833 833
834 834 return out
835 835
836 836 f.__doc__ = func.__doc__
837 837 return f
838 838
839 839 #----------------------------------------------------------------------------
840 840 def doctest_reload():
841 841 """Properly reload doctest to reuse it interactively.
842 842
843 843 This routine:
844 844
845 845 - reloads doctest
846 846
847 847 - resets its global 'master' attribute to None, so that multiple uses of
848 848 the module interactively don't produce cumulative reports.
849 849
850 850 - Monkeypatches its core test runner method to protect it from IPython's
851 851 modified displayhook. Doctest expects the default displayhook behavior
852 852 deep down, so our modification breaks it completely. For this reason, a
853 853 hard monkeypatch seems like a reasonable solution rather than asking
854 854 users to manually use a different doctest runner when under IPython."""
855 855
856 856 import doctest
857 857 reload(doctest)
858 858 doctest.master=None
859 859
860 860 try:
861 861 doctest.DocTestRunner
862 862 except AttributeError:
863 863 # This is only for python 2.3 compatibility, remove once we move to
864 864 # 2.4 only.
865 865 pass
866 866 else:
867 867 doctest.DocTestRunner.run = dhook_wrap(doctest.DocTestRunner.run)
868 868
869 869 #----------------------------------------------------------------------------
870 870 class HomeDirError(Error):
871 871 pass
872 872
873 873 def get_home_dir():
874 874 """Return the closest possible equivalent to a 'home' directory.
875 875
876 876 We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH.
877 877
878 878 Currently only Posix and NT are implemented, a HomeDirError exception is
879 879 raised for all other OSes. """
880 880
881 881 isdir = os.path.isdir
882 882 env = os.environ
883 883
884 884 # first, check py2exe distribution root directory for _ipython.
885 885 # This overrides all. Normally does not exist.
886 886
887 887 if '\\library.zip\\' in IPython.__file__.lower():
888 888 root, rest = IPython.__file__.lower().split('library.zip')
889 889 if isdir(root + '_ipython'):
890 890 os.environ["IPYKITROOT"] = root.rstrip('\\')
891 891 return root
892 892
893 893 try:
894 894 homedir = env['HOME']
895 895 if not isdir(homedir):
896 896 # in case a user stuck some string which does NOT resolve to a
897 897 # valid path, it's as good as if we hadn't foud it
898 898 raise KeyError
899 899 return homedir
900 900 except KeyError:
901 901 if os.name == 'posix':
902 902 raise HomeDirError,'undefined $HOME, IPython can not proceed.'
903 903 elif os.name == 'nt':
904 904 # For some strange reason, win9x returns 'nt' for os.name.
905 905 try:
906 906 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
907 907 if not isdir(homedir):
908 908 homedir = os.path.join(env['USERPROFILE'])
909 909 if not isdir(homedir):
910 910 raise HomeDirError
911 911 return homedir
912 912 except:
913 913 try:
914 914 # Use the registry to get the 'My Documents' folder.
915 915 import _winreg as wreg
916 916 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
917 917 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
918 918 homedir = wreg.QueryValueEx(key,'Personal')[0]
919 919 key.Close()
920 920 if not isdir(homedir):
921 921 e = ('Invalid "Personal" folder registry key '
922 922 'typically "My Documents".\n'
923 923 'Value: %s\n'
924 924 'This is not a valid directory on your system.' %
925 925 homedir)
926 926 raise HomeDirError(e)
927 927 return homedir
928 928 except HomeDirError:
929 929 raise
930 930 except:
931 931 return 'C:\\'
932 932 elif os.name == 'dos':
933 933 # Desperate, may do absurd things in classic MacOS. May work under DOS.
934 934 return 'C:\\'
935 935 else:
936 936 raise HomeDirError,'support for your operating system not implemented.'
937 937
938 938 #****************************************************************************
939 939 # strings and text
940 940
941 941 class LSString(str):
942 942 """String derivative with a special access attributes.
943 943
944 944 These are normal strings, but with the special attributes:
945 945
946 946 .l (or .list) : value as list (split on newlines).
947 947 .n (or .nlstr): original value (the string itself).
948 948 .s (or .spstr): value as whitespace-separated string.
949 949 .p (or .paths): list of path objects
950 950
951 951 Any values which require transformations are computed only once and
952 952 cached.
953 953
954 954 Such strings are very useful to efficiently interact with the shell, which
955 955 typically only understands whitespace-separated options for commands."""
956 956
957 957 def get_list(self):
958 958 try:
959 959 return self.__list
960 960 except AttributeError:
961 961 self.__list = self.split('\n')
962 962 return self.__list
963 963
964 964 l = list = property(get_list)
965 965
966 966 def get_spstr(self):
967 967 try:
968 968 return self.__spstr
969 969 except AttributeError:
970 970 self.__spstr = self.replace('\n',' ')
971 971 return self.__spstr
972 972
973 973 s = spstr = property(get_spstr)
974 974
975 975 def get_nlstr(self):
976 976 return self
977 977
978 978 n = nlstr = property(get_nlstr)
979 979
980 980 def get_paths(self):
981 981 try:
982 982 return self.__paths
983 983 except AttributeError:
984 984 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
985 985 return self.__paths
986 986
987 987 p = paths = property(get_paths)
988 988
989 989 def print_lsstring(arg):
990 990 """ Prettier (non-repr-like) and more informative printer for LSString """
991 991 print "LSString (.p, .n, .l, .s available). Value:"
992 992 print arg
993 993
994 994 print_lsstring = result_display.when_type(LSString)(print_lsstring)
995 995
996 996 #----------------------------------------------------------------------------
997 997 class SList(list):
998 998 """List derivative with a special access attributes.
999 999
1000 1000 These are normal lists, but with the special attributes:
1001 1001
1002 1002 .l (or .list) : value as list (the list itself).
1003 1003 .n (or .nlstr): value as a string, joined on newlines.
1004 1004 .s (or .spstr): value as a string, joined on spaces.
1005 1005 .p (or .paths): list of path objects
1006 1006
1007 1007 Any values which require transformations are computed only once and
1008 1008 cached."""
1009 1009
1010 1010 def get_list(self):
1011 1011 return self
1012 1012
1013 1013 l = list = property(get_list)
1014 1014
1015 1015 def get_spstr(self):
1016 1016 try:
1017 1017 return self.__spstr
1018 1018 except AttributeError:
1019 1019 self.__spstr = ' '.join(self)
1020 1020 return self.__spstr
1021 1021
1022 1022 s = spstr = property(get_spstr)
1023 1023
1024 1024 def get_nlstr(self):
1025 1025 try:
1026 1026 return self.__nlstr
1027 1027 except AttributeError:
1028 1028 self.__nlstr = '\n'.join(self)
1029 1029 return self.__nlstr
1030 1030
1031 1031 n = nlstr = property(get_nlstr)
1032 1032
1033 1033 def get_paths(self):
1034 1034 try:
1035 1035 return self.__paths
1036 1036 except AttributeError:
1037 1037 self.__paths = [path(p) for p in self if os.path.exists(p)]
1038 1038 return self.__paths
1039 1039
1040 1040 p = paths = property(get_paths)
1041 1041
1042 1042 def grep(self, pattern, prune = False):
1043 1043 """ Return all strings matching 'pattern' (a regex or callable)
1044 1044
1045 1045 This is case-insensitive. If prune is true, return all items
1046 1046 NOT matching the pattern.
1047 1047
1048 1048 Examples::
1049 1049
1050 1050 a.grep( lambda x: x.startswith('C') )
1051 1051 a.grep('Cha.*log', prune=1)
1052 1052 """
1053 1053 if isinstance(pattern, basestring):
1054 1054 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
1055 1055 else:
1056 1056 pred = pattern
1057 1057 if not prune:
1058 1058 return SList([el for el in self if pred(el)])
1059 1059 else:
1060 1060 return SList([el for el in self if not pred(el)])
1061 1061 def fields(self, *fields):
1062 1062 """ Collect whitespace-separated fields from string list
1063 1063
1064 1064 Allows quick awk-like usage of string lists.
1065 1065
1066 1066 Example data (in var a, created by 'a = !ls -l')::
1067 1067 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
1068 1068 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
1069 1069
1070 1070 a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+']
1071 1071 a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+']
1072 1072 (note the joining by space).
1073 1073
1074 1074 IndexErrors are ignored.
1075 1075
1076 1076 Without args, fields() just split()'s the strings.
1077 1077 """
1078 1078 if len(fields) == 0:
1079 1079 return [el.split() for el in self]
1080 1080
1081 1081 res = SList()
1082 1082 for el in [f.split() for f in self]:
1083 1083 lineparts = []
1084 1084
1085 1085 for fd in fields:
1086 1086 try:
1087 1087 lineparts.append(el[fd])
1088 1088 except IndexError:
1089 1089 pass
1090 1090 if lineparts:
1091 1091 res.append(" ".join(lineparts))
1092 1092
1093 1093 return res
1094 1094
1095 1095
1096 1096
1097 1097
1098 1098
1099 1099 def print_slist(arg):
1100 1100 """ Prettier (non-repr-like) and more informative printer for SList """
1101 1101 print "SList (.p, .n, .l, .s, .grep(), .fields() available). Value:"
1102 1102 nlprint(arg)
1103 1103
1104 1104 print_slist = result_display.when_type(SList)(print_slist)
1105 1105
1106 1106
1107 1107
1108 1108 #----------------------------------------------------------------------------
1109 1109 def esc_quotes(strng):
1110 1110 """Return the input string with single and double quotes escaped out"""
1111 1111
1112 1112 return strng.replace('"','\\"').replace("'","\\'")
1113 1113
1114 1114 #----------------------------------------------------------------------------
1115 1115 def make_quoted_expr(s):
1116 1116 """Return string s in appropriate quotes, using raw string if possible.
1117 1117
1118 1118 Effectively this turns string: cd \ao\ao\
1119 1119 to: r"cd \ao\ao\_"[:-1]
1120 1120
1121 1121 Note the use of raw string and padding at the end to allow trailing backslash.
1122 1122
1123 1123 """
1124 1124
1125 1125 tail = ''
1126 1126 tailpadding = ''
1127 1127 raw = ''
1128 1128 if "\\" in s:
1129 1129 raw = 'r'
1130 1130 if s.endswith('\\'):
1131 1131 tail = '[:-1]'
1132 1132 tailpadding = '_'
1133 1133 if '"' not in s:
1134 1134 quote = '"'
1135 1135 elif "'" not in s:
1136 1136 quote = "'"
1137 1137 elif '"""' not in s and not s.endswith('"'):
1138 1138 quote = '"""'
1139 1139 elif "'''" not in s and not s.endswith("'"):
1140 1140 quote = "'''"
1141 1141 else:
1142 1142 # give up, backslash-escaped string will do
1143 1143 return '"%s"' % esc_quotes(s)
1144 1144 res = raw + quote + s + tailpadding + quote + tail
1145 1145 return res
1146 1146
1147 1147
1148 1148 #----------------------------------------------------------------------------
1149 1149 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
1150 1150 """Take multiple lines of input.
1151 1151
1152 1152 A list with each line of input as a separate element is returned when a
1153 1153 termination string is entered (defaults to a single '.'). Input can also
1154 1154 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1155 1155
1156 1156 Lines of input which end in \\ are joined into single entries (and a
1157 1157 secondary continuation prompt is issued as long as the user terminates
1158 1158 lines with \\). This allows entering very long strings which are still
1159 1159 meant to be treated as single entities.
1160 1160 """
1161 1161
1162 1162 try:
1163 1163 if header:
1164 1164 header += '\n'
1165 1165 lines = [raw_input(header + ps1)]
1166 1166 except EOFError:
1167 1167 return []
1168 1168 terminate = [terminate_str]
1169 1169 try:
1170 1170 while lines[-1:] != terminate:
1171 1171 new_line = raw_input(ps1)
1172 1172 while new_line.endswith('\\'):
1173 1173 new_line = new_line[:-1] + raw_input(ps2)
1174 1174 lines.append(new_line)
1175 1175
1176 1176 return lines[:-1] # don't return the termination command
1177 1177 except EOFError:
1178 1178 print
1179 1179 return lines
1180 1180
1181 1181 #----------------------------------------------------------------------------
1182 1182 def raw_input_ext(prompt='', ps2='... '):
1183 1183 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1184 1184
1185 1185 line = raw_input(prompt)
1186 1186 while line.endswith('\\'):
1187 1187 line = line[:-1] + raw_input(ps2)
1188 1188 return line
1189 1189
1190 1190 #----------------------------------------------------------------------------
1191 1191 def ask_yes_no(prompt,default=None):
1192 1192 """Asks a question and returns a boolean (y/n) answer.
1193 1193
1194 1194 If default is given (one of 'y','n'), it is used if the user input is
1195 1195 empty. Otherwise the question is repeated until an answer is given.
1196 1196
1197 1197 An EOF is treated as the default answer. If there is no default, an
1198 1198 exception is raised to prevent infinite loops.
1199 1199
1200 1200 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1201 1201
1202 1202 answers = {'y':True,'n':False,'yes':True,'no':False}
1203 1203 ans = None
1204 1204 while ans not in answers.keys():
1205 1205 try:
1206 1206 ans = raw_input(prompt+' ').lower()
1207 1207 if not ans: # response was an empty string
1208 1208 ans = default
1209 1209 except KeyboardInterrupt:
1210 1210 pass
1211 1211 except EOFError:
1212 1212 if default in answers.keys():
1213 1213 ans = default
1214 1214 print
1215 1215 else:
1216 1216 raise
1217 1217
1218 1218 return answers[ans]
1219 1219
1220 1220 #----------------------------------------------------------------------------
1221 1221 def marquee(txt='',width=78,mark='*'):
1222 1222 """Return the input string centered in a 'marquee'."""
1223 1223 if not txt:
1224 1224 return (mark*width)[:width]
1225 1225 nmark = (width-len(txt)-2)/len(mark)/2
1226 1226 if nmark < 0: nmark =0
1227 1227 marks = mark*nmark
1228 1228 return '%s %s %s' % (marks,txt,marks)
1229 1229
1230 1230 #----------------------------------------------------------------------------
1231 1231 class EvalDict:
1232 1232 """
1233 1233 Emulate a dict which evaluates its contents in the caller's frame.
1234 1234
1235 1235 Usage:
1236 1236 >>>number = 19
1237 1237 >>>text = "python"
1238 1238 >>>print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1239 1239 """
1240 1240
1241 1241 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1242 1242 # modified (shorter) version of:
1243 1243 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1244 1244 # Skip Montanaro (skip@pobox.com).
1245 1245
1246 1246 def __getitem__(self, name):
1247 1247 frame = sys._getframe(1)
1248 1248 return eval(name, frame.f_globals, frame.f_locals)
1249 1249
1250 1250 EvalString = EvalDict # for backwards compatibility
1251 1251 #----------------------------------------------------------------------------
1252 1252 def qw(words,flat=0,sep=None,maxsplit=-1):
1253 1253 """Similar to Perl's qw() operator, but with some more options.
1254 1254
1255 1255 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1256 1256
1257 1257 words can also be a list itself, and with flat=1, the output will be
1258 1258 recursively flattened. Examples:
1259 1259
1260 1260 >>> qw('1 2')
1261 1261 ['1', '2']
1262 1262 >>> qw(['a b','1 2',['m n','p q']])
1263 1263 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1264 1264 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1265 1265 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q'] """
1266 1266
1267 1267 if type(words) in StringTypes:
1268 1268 return [word.strip() for word in words.split(sep,maxsplit)
1269 1269 if word and not word.isspace() ]
1270 1270 if flat:
1271 1271 return flatten(map(qw,words,[1]*len(words)))
1272 1272 return map(qw,words)
1273 1273
1274 1274 #----------------------------------------------------------------------------
1275 1275 def qwflat(words,sep=None,maxsplit=-1):
1276 1276 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1277 1277 return qw(words,1,sep,maxsplit)
1278 1278
1279 1279 #----------------------------------------------------------------------------
1280 1280 def qw_lol(indata):
1281 1281 """qw_lol('a b') -> [['a','b']],
1282 1282 otherwise it's just a call to qw().
1283 1283
1284 1284 We need this to make sure the modules_some keys *always* end up as a
1285 1285 list of lists."""
1286 1286
1287 1287 if type(indata) in StringTypes:
1288 1288 return [qw(indata)]
1289 1289 else:
1290 1290 return qw(indata)
1291 1291
1292 1292 #-----------------------------------------------------------------------------
1293 1293 def list_strings(arg):
1294 1294 """Always return a list of strings, given a string or list of strings
1295 1295 as input."""
1296 1296
1297 1297 if type(arg) in StringTypes: return [arg]
1298 1298 else: return arg
1299 1299
1300 1300 #----------------------------------------------------------------------------
1301 1301 def grep(pat,list,case=1):
1302 1302 """Simple minded grep-like function.
1303 1303 grep(pat,list) returns occurrences of pat in list, None on failure.
1304 1304
1305 1305 It only does simple string matching, with no support for regexps. Use the
1306 1306 option case=0 for case-insensitive matching."""
1307 1307
1308 1308 # This is pretty crude. At least it should implement copying only references
1309 1309 # to the original data in case it's big. Now it copies the data for output.
1310 1310 out=[]
1311 1311 if case:
1312 1312 for term in list:
1313 1313 if term.find(pat)>-1: out.append(term)
1314 1314 else:
1315 1315 lpat=pat.lower()
1316 1316 for term in list:
1317 1317 if term.lower().find(lpat)>-1: out.append(term)
1318 1318
1319 1319 if len(out): return out
1320 1320 else: return None
1321 1321
1322 1322 #----------------------------------------------------------------------------
1323 1323 def dgrep(pat,*opts):
1324 1324 """Return grep() on dir()+dir(__builtins__).
1325 1325
1326 1326 A very common use of grep() when working interactively."""
1327 1327
1328 1328 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1329 1329
1330 1330 #----------------------------------------------------------------------------
1331 1331 def idgrep(pat):
1332 1332 """Case-insensitive dgrep()"""
1333 1333
1334 1334 return dgrep(pat,0)
1335 1335
1336 1336 #----------------------------------------------------------------------------
1337 1337 def igrep(pat,list):
1338 1338 """Synonym for case-insensitive grep."""
1339 1339
1340 1340 return grep(pat,list,case=0)
1341 1341
1342 1342 #----------------------------------------------------------------------------
1343 1343 def indent(str,nspaces=4,ntabs=0):
1344 1344 """Indent a string a given number of spaces or tabstops.
1345 1345
1346 1346 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1347 1347 """
1348 1348 if str is None:
1349 1349 return
1350 1350 ind = '\t'*ntabs+' '*nspaces
1351 1351 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1352 1352 if outstr.endswith(os.linesep+ind):
1353 1353 return outstr[:-len(ind)]
1354 1354 else:
1355 1355 return outstr
1356 1356
1357 1357 #-----------------------------------------------------------------------------
1358 1358 def native_line_ends(filename,backup=1):
1359 1359 """Convert (in-place) a file to line-ends native to the current OS.
1360 1360
1361 1361 If the optional backup argument is given as false, no backup of the
1362 1362 original file is left. """
1363 1363
1364 1364 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1365 1365
1366 1366 bak_filename = filename + backup_suffixes[os.name]
1367 1367
1368 1368 original = open(filename).read()
1369 1369 shutil.copy2(filename,bak_filename)
1370 1370 try:
1371 1371 new = open(filename,'wb')
1372 1372 new.write(os.linesep.join(original.splitlines()))
1373 1373 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1374 1374 new.close()
1375 1375 except:
1376 1376 os.rename(bak_filename,filename)
1377 1377 if not backup:
1378 1378 try:
1379 1379 os.remove(bak_filename)
1380 1380 except:
1381 1381 pass
1382 1382
1383 1383 #----------------------------------------------------------------------------
1384 1384 def get_pager_cmd(pager_cmd = None):
1385 1385 """Return a pager command.
1386 1386
1387 1387 Makes some attempts at finding an OS-correct one."""
1388 1388
1389 1389 if os.name == 'posix':
1390 1390 default_pager_cmd = 'less -r' # -r for color control sequences
1391 1391 elif os.name in ['nt','dos']:
1392 1392 default_pager_cmd = 'type'
1393 1393
1394 1394 if pager_cmd is None:
1395 1395 try:
1396 1396 pager_cmd = os.environ['PAGER']
1397 1397 except:
1398 1398 pager_cmd = default_pager_cmd
1399 1399 return pager_cmd
1400 1400
1401 1401 #-----------------------------------------------------------------------------
1402 1402 def get_pager_start(pager,start):
1403 1403 """Return the string for paging files with an offset.
1404 1404
1405 1405 This is the '+N' argument which less and more (under Unix) accept.
1406 1406 """
1407 1407
1408 1408 if pager in ['less','more']:
1409 1409 if start:
1410 1410 start_string = '+' + str(start)
1411 1411 else:
1412 1412 start_string = ''
1413 1413 else:
1414 1414 start_string = ''
1415 1415 return start_string
1416 1416
1417 1417 #----------------------------------------------------------------------------
1418 1418 # (X)emacs on W32 doesn't like to be bypassed with msvcrt.getch()
1419 1419 if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs':
1420 1420 import msvcrt
1421 1421 def page_more():
1422 1422 """ Smart pausing between pages
1423 1423
1424 1424 @return: True if need print more lines, False if quit
1425 1425 """
1426 1426 Term.cout.write('---Return to continue, q to quit--- ')
1427 1427 ans = msvcrt.getch()
1428 1428 if ans in ("q", "Q"):
1429 1429 result = False
1430 1430 else:
1431 1431 result = True
1432 1432 Term.cout.write("\b"*37 + " "*37 + "\b"*37)
1433 1433 return result
1434 1434 else:
1435 1435 def page_more():
1436 1436 ans = raw_input('---Return to continue, q to quit--- ')
1437 1437 if ans.lower().startswith('q'):
1438 1438 return False
1439 1439 else:
1440 1440 return True
1441 1441
1442 1442 esc_re = re.compile(r"(\x1b[^m]+m)")
1443 1443
1444 1444 def page_dumb(strng,start=0,screen_lines=25):
1445 1445 """Very dumb 'pager' in Python, for when nothing else works.
1446 1446
1447 1447 Only moves forward, same interface as page(), except for pager_cmd and
1448 1448 mode."""
1449 1449
1450 1450 out_ln = strng.splitlines()[start:]
1451 1451 screens = chop(out_ln,screen_lines-1)
1452 1452 if len(screens) == 1:
1453 1453 print >>Term.cout, os.linesep.join(screens[0])
1454 1454 else:
1455 1455 last_escape = ""
1456 1456 for scr in screens[0:-1]:
1457 1457 hunk = os.linesep.join(scr)
1458 1458 print >>Term.cout, last_escape + hunk
1459 1459 if not page_more():
1460 1460 return
1461 1461 esc_list = esc_re.findall(hunk)
1462 1462 if len(esc_list) > 0:
1463 1463 last_escape = esc_list[-1]
1464 1464 print >>Term.cout, last_escape + os.linesep.join(screens[-1])
1465 1465
1466 1466 #----------------------------------------------------------------------------
1467 1467 def page(strng,start=0,screen_lines=0,pager_cmd = None):
1468 1468 """Print a string, piping through a pager after a certain length.
1469 1469
1470 1470 The screen_lines parameter specifies the number of *usable* lines of your
1471 1471 terminal screen (total lines minus lines you need to reserve to show other
1472 1472 information).
1473 1473
1474 1474 If you set screen_lines to a number <=0, page() will try to auto-determine
1475 1475 your screen size and will only use up to (screen_size+screen_lines) for
1476 1476 printing, paging after that. That is, if you want auto-detection but need
1477 1477 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
1478 1478 auto-detection without any lines reserved simply use screen_lines = 0.
1479 1479
1480 1480 If a string won't fit in the allowed lines, it is sent through the
1481 1481 specified pager command. If none given, look for PAGER in the environment,
1482 1482 and ultimately default to less.
1483 1483
1484 1484 If no system pager works, the string is sent through a 'dumb pager'
1485 1485 written in python, very simplistic.
1486 1486 """
1487 1487
1488 1488 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
1489 1489 TERM = os.environ.get('TERM','dumb')
1490 1490 if TERM in ['dumb','emacs'] and os.name != 'nt':
1491 1491 print strng
1492 1492 return
1493 1493 # chop off the topmost part of the string we don't want to see
1494 1494 str_lines = strng.split(os.linesep)[start:]
1495 1495 str_toprint = os.linesep.join(str_lines)
1496 1496 num_newlines = len(str_lines)
1497 1497 len_str = len(str_toprint)
1498 1498
1499 1499 # Dumb heuristics to guesstimate number of on-screen lines the string
1500 1500 # takes. Very basic, but good enough for docstrings in reasonable
1501 1501 # terminals. If someone later feels like refining it, it's not hard.
1502 1502 numlines = max(num_newlines,int(len_str/80)+1)
1503 1503
1504 1504 if os.name == "nt":
1505 1505 screen_lines_def = get_console_size(defaulty=25)[1]
1506 1506 else:
1507 1507 screen_lines_def = 25 # default value if we can't auto-determine
1508 1508
1509 1509 # auto-determine screen size
1510 1510 if screen_lines <= 0:
1511 1511 if TERM=='xterm':
1512 1512 try:
1513 1513 import curses
1514 1514 if hasattr(curses,'initscr'):
1515 1515 use_curses = 1
1516 1516 else:
1517 1517 use_curses = 0
1518 1518 except ImportError:
1519 1519 use_curses = 0
1520 1520 else:
1521 1521 # curses causes problems on many terminals other than xterm.
1522 1522 use_curses = 0
1523 1523 if use_curses:
1524 1524 scr = curses.initscr()
1525 1525 screen_lines_real,screen_cols = scr.getmaxyx()
1526 1526 curses.endwin()
1527 1527 screen_lines += screen_lines_real
1528 1528 #print '***Screen size:',screen_lines_real,'lines x',\
1529 1529 #screen_cols,'columns.' # dbg
1530 1530 else:
1531 1531 screen_lines += screen_lines_def
1532 1532
1533 1533 #print 'numlines',numlines,'screenlines',screen_lines # dbg
1534 1534 if numlines <= screen_lines :
1535 1535 #print '*** normal print' # dbg
1536 1536 print >>Term.cout, str_toprint
1537 1537 else:
1538 1538 # Try to open pager and default to internal one if that fails.
1539 1539 # All failure modes are tagged as 'retval=1', to match the return
1540 1540 # value of a failed system command. If any intermediate attempt
1541 1541 # sets retval to 1, at the end we resort to our own page_dumb() pager.
1542 1542 pager_cmd = get_pager_cmd(pager_cmd)
1543 1543 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1544 1544 if os.name == 'nt':
1545 1545 if pager_cmd.startswith('type'):
1546 1546 # The default WinXP 'type' command is failing on complex strings.
1547 1547 retval = 1
1548 1548 else:
1549 1549 tmpname = tempfile.mktemp('.txt')
1550 1550 tmpfile = file(tmpname,'wt')
1551 1551 tmpfile.write(strng)
1552 1552 tmpfile.close()
1553 1553 cmd = "%s < %s" % (pager_cmd,tmpname)
1554 1554 if os.system(cmd):
1555 1555 retval = 1
1556 1556 else:
1557 1557 retval = None
1558 1558 os.remove(tmpname)
1559 1559 else:
1560 1560 try:
1561 1561 retval = None
1562 1562 # if I use popen4, things hang. No idea why.
1563 1563 #pager,shell_out = os.popen4(pager_cmd)
1564 1564 pager = os.popen(pager_cmd,'w')
1565 1565 pager.write(strng)
1566 1566 pager.close()
1567 1567 retval = pager.close() # success returns None
1568 1568 except IOError,msg: # broken pipe when user quits
1569 1569 if msg.args == (32,'Broken pipe'):
1570 1570 retval = None
1571 1571 else:
1572 1572 retval = 1
1573 1573 except OSError:
1574 1574 # Other strange problems, sometimes seen in Win2k/cygwin
1575 1575 retval = 1
1576 1576 if retval is not None:
1577 1577 page_dumb(strng,screen_lines=screen_lines)
1578 1578
1579 1579 #----------------------------------------------------------------------------
1580 1580 def page_file(fname,start = 0, pager_cmd = None):
1581 1581 """Page a file, using an optional pager command and starting line.
1582 1582 """
1583 1583
1584 1584 pager_cmd = get_pager_cmd(pager_cmd)
1585 1585 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1586 1586
1587 1587 try:
1588 1588 if os.environ['TERM'] in ['emacs','dumb']:
1589 1589 raise EnvironmentError
1590 1590 xsys(pager_cmd + ' ' + fname)
1591 1591 except:
1592 1592 try:
1593 1593 if start > 0:
1594 1594 start -= 1
1595 1595 page(open(fname).read(),start)
1596 1596 except:
1597 1597 print 'Unable to show file',`fname`
1598 1598
1599 1599 #----------------------------------------------------------------------------
1600 1600 def snip_print(str,width = 75,print_full = 0,header = ''):
1601 1601 """Print a string snipping the midsection to fit in width.
1602 1602
1603 1603 print_full: mode control:
1604 1604 - 0: only snip long strings
1605 1605 - 1: send to page() directly.
1606 1606 - 2: snip long strings and ask for full length viewing with page()
1607 1607 Return 1 if snipping was necessary, 0 otherwise."""
1608 1608
1609 1609 if print_full == 1:
1610 1610 page(header+str)
1611 1611 return 0
1612 1612
1613 1613 print header,
1614 1614 if len(str) < width:
1615 1615 print str
1616 1616 snip = 0
1617 1617 else:
1618 1618 whalf = int((width -5)/2)
1619 1619 print str[:whalf] + ' <...> ' + str[-whalf:]
1620 1620 snip = 1
1621 1621 if snip and print_full == 2:
1622 1622 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
1623 1623 page(str)
1624 1624 return snip
1625 1625
1626 1626 #****************************************************************************
1627 1627 # lists, dicts and structures
1628 1628
1629 1629 def belong(candidates,checklist):
1630 1630 """Check whether a list of items appear in a given list of options.
1631 1631
1632 1632 Returns a list of 1 and 0, one for each candidate given."""
1633 1633
1634 1634 return [x in checklist for x in candidates]
1635 1635
1636 1636 #----------------------------------------------------------------------------
1637 1637 def uniq_stable(elems):
1638 1638 """uniq_stable(elems) -> list
1639 1639
1640 1640 Return from an iterable, a list of all the unique elements in the input,
1641 1641 but maintaining the order in which they first appear.
1642 1642
1643 1643 A naive solution to this problem which just makes a dictionary with the
1644 1644 elements as keys fails to respect the stability condition, since
1645 1645 dictionaries are unsorted by nature.
1646 1646
1647 1647 Note: All elements in the input must be valid dictionary keys for this
1648 1648 routine to work, as it internally uses a dictionary for efficiency
1649 1649 reasons."""
1650 1650
1651 1651 unique = []
1652 1652 unique_dict = {}
1653 1653 for nn in elems:
1654 1654 if nn not in unique_dict:
1655 1655 unique.append(nn)
1656 1656 unique_dict[nn] = None
1657 1657 return unique
1658 1658
1659 1659 #----------------------------------------------------------------------------
1660 1660 class NLprinter:
1661 1661 """Print an arbitrarily nested list, indicating index numbers.
1662 1662
1663 1663 An instance of this class called nlprint is available and callable as a
1664 1664 function.
1665 1665
1666 1666 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1667 1667 and using 'sep' to separate the index from the value. """
1668 1668
1669 1669 def __init__(self):
1670 1670 self.depth = 0
1671 1671
1672 1672 def __call__(self,lst,pos='',**kw):
1673 1673 """Prints the nested list numbering levels."""
1674 1674 kw.setdefault('indent',' ')
1675 1675 kw.setdefault('sep',': ')
1676 1676 kw.setdefault('start',0)
1677 1677 kw.setdefault('stop',len(lst))
1678 1678 # we need to remove start and stop from kw so they don't propagate
1679 1679 # into a recursive call for a nested list.
1680 1680 start = kw['start']; del kw['start']
1681 1681 stop = kw['stop']; del kw['stop']
1682 1682 if self.depth == 0 and 'header' in kw.keys():
1683 1683 print kw['header']
1684 1684
1685 1685 for idx in range(start,stop):
1686 1686 elem = lst[idx]
1687 1687 if type(elem)==type([]):
1688 1688 self.depth += 1
1689 1689 self.__call__(elem,itpl('$pos$idx,'),**kw)
1690 1690 self.depth -= 1
1691 1691 else:
1692 1692 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1693 1693
1694 1694 nlprint = NLprinter()
1695 1695 #----------------------------------------------------------------------------
1696 1696 def all_belong(candidates,checklist):
1697 1697 """Check whether a list of items ALL appear in a given list of options.
1698 1698
1699 1699 Returns a single 1 or 0 value."""
1700 1700
1701 1701 return 1-(0 in [x in checklist for x in candidates])
1702 1702
1703 1703 #----------------------------------------------------------------------------
1704 1704 def sort_compare(lst1,lst2,inplace = 1):
1705 1705 """Sort and compare two lists.
1706 1706
1707 1707 By default it does it in place, thus modifying the lists. Use inplace = 0
1708 1708 to avoid that (at the cost of temporary copy creation)."""
1709 1709 if not inplace:
1710 1710 lst1 = lst1[:]
1711 1711 lst2 = lst2[:]
1712 1712 lst1.sort(); lst2.sort()
1713 1713 return lst1 == lst2
1714 1714
1715 1715 #----------------------------------------------------------------------------
1716 1716 def mkdict(**kwargs):
1717 1717 """Return a dict from a keyword list.
1718 1718
1719 1719 It's just syntactic sugar for making ditcionary creation more convenient:
1720 1720 # the standard way
1721 1721 >>>data = { 'red' : 1, 'green' : 2, 'blue' : 3 }
1722 1722 # a cleaner way
1723 1723 >>>data = dict(red=1, green=2, blue=3)
1724 1724
1725 1725 If you need more than this, look at the Struct() class."""
1726 1726
1727 1727 return kwargs
1728 1728
1729 1729 #----------------------------------------------------------------------------
1730 1730 def list2dict(lst):
1731 1731 """Takes a list of (key,value) pairs and turns it into a dict."""
1732 1732
1733 1733 dic = {}
1734 1734 for k,v in lst: dic[k] = v
1735 1735 return dic
1736 1736
1737 1737 #----------------------------------------------------------------------------
1738 1738 def list2dict2(lst,default=''):
1739 1739 """Takes a list and turns it into a dict.
1740 1740 Much slower than list2dict, but more versatile. This version can take
1741 1741 lists with sublists of arbitrary length (including sclars)."""
1742 1742
1743 1743 dic = {}
1744 1744 for elem in lst:
1745 1745 if type(elem) in (types.ListType,types.TupleType):
1746 1746 size = len(elem)
1747 1747 if size == 0:
1748 1748 pass
1749 1749 elif size == 1:
1750 1750 dic[elem] = default
1751 1751 else:
1752 1752 k,v = elem[0], elem[1:]
1753 1753 if len(v) == 1: v = v[0]
1754 1754 dic[k] = v
1755 1755 else:
1756 1756 dic[elem] = default
1757 1757 return dic
1758 1758
1759 1759 #----------------------------------------------------------------------------
1760 1760 def flatten(seq):
1761 1761 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1762 1762
1763 1763 return [x for subseq in seq for x in subseq]
1764 1764
1765 1765 #----------------------------------------------------------------------------
1766 1766 def get_slice(seq,start=0,stop=None,step=1):
1767 1767 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1768 1768 if stop == None:
1769 1769 stop = len(seq)
1770 1770 item = lambda i: seq[i]
1771 1771 return map(item,xrange(start,stop,step))
1772 1772
1773 1773 #----------------------------------------------------------------------------
1774 1774 def chop(seq,size):
1775 1775 """Chop a sequence into chunks of the given size."""
1776 1776 chunk = lambda i: seq[i:i+size]
1777 1777 return map(chunk,xrange(0,len(seq),size))
1778 1778
1779 1779 #----------------------------------------------------------------------------
1780 1780 # with is a keyword as of python 2.5, so this function is renamed to withobj
1781 1781 # from its old 'with' name.
1782 1782 def with_obj(object, **args):
1783 1783 """Set multiple attributes for an object, similar to Pascal's with.
1784 1784
1785 1785 Example:
1786 1786 with_obj(jim,
1787 1787 born = 1960,
1788 1788 haircolour = 'Brown',
1789 1789 eyecolour = 'Green')
1790 1790
1791 1791 Credit: Greg Ewing, in
1792 1792 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1793 1793
1794 1794 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1795 1795 has become a keyword for Python 2.5, so we had to rename it."""
1796 1796
1797 1797 object.__dict__.update(args)
1798 1798
1799 1799 #----------------------------------------------------------------------------
1800 1800 def setattr_list(obj,alist,nspace = None):
1801 1801 """Set a list of attributes for an object taken from a namespace.
1802 1802
1803 1803 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1804 1804 alist with their values taken from nspace, which must be a dict (something
1805 1805 like locals() will often do) If nspace isn't given, locals() of the
1806 1806 *caller* is used, so in most cases you can omit it.
1807 1807
1808 1808 Note that alist can be given as a string, which will be automatically
1809 1809 split into a list on whitespace. If given as a list, it must be a list of
1810 1810 *strings* (the variable names themselves), not of variables."""
1811 1811
1812 1812 # this grabs the local variables from the *previous* call frame -- that is
1813 1813 # the locals from the function that called setattr_list().
1814 1814 # - snipped from weave.inline()
1815 1815 if nspace is None:
1816 1816 call_frame = sys._getframe().f_back
1817 1817 nspace = call_frame.f_locals
1818 1818
1819 1819 if type(alist) in StringTypes:
1820 1820 alist = alist.split()
1821 1821 for attr in alist:
1822 1822 val = eval(attr,nspace)
1823 1823 setattr(obj,attr,val)
1824 1824
1825 1825 #----------------------------------------------------------------------------
1826 1826 def getattr_list(obj,alist,*args):
1827 1827 """getattr_list(obj,alist[, default]) -> attribute list.
1828 1828
1829 1829 Get a list of named attributes for an object. When a default argument is
1830 1830 given, it is returned when the attribute doesn't exist; without it, an
1831 1831 exception is raised in that case.
1832 1832
1833 1833 Note that alist can be given as a string, which will be automatically
1834 1834 split into a list on whitespace. If given as a list, it must be a list of
1835 1835 *strings* (the variable names themselves), not of variables."""
1836 1836
1837 1837 if type(alist) in StringTypes:
1838 1838 alist = alist.split()
1839 1839 if args:
1840 1840 if len(args)==1:
1841 1841 default = args[0]
1842 1842 return map(lambda attr: getattr(obj,attr,default),alist)
1843 1843 else:
1844 1844 raise ValueError,'getattr_list() takes only one optional argument'
1845 1845 else:
1846 1846 return map(lambda attr: getattr(obj,attr),alist)
1847 1847
1848 1848 #----------------------------------------------------------------------------
1849 1849 def map_method(method,object_list,*argseq,**kw):
1850 1850 """map_method(method,object_list,*args,**kw) -> list
1851 1851
1852 1852 Return a list of the results of applying the methods to the items of the
1853 1853 argument sequence(s). If more than one sequence is given, the method is
1854 1854 called with an argument list consisting of the corresponding item of each
1855 1855 sequence. All sequences must be of the same length.
1856 1856
1857 1857 Keyword arguments are passed verbatim to all objects called.
1858 1858
1859 1859 This is Python code, so it's not nearly as fast as the builtin map()."""
1860 1860
1861 1861 out_list = []
1862 1862 idx = 0
1863 1863 for object in object_list:
1864 1864 try:
1865 1865 handler = getattr(object, method)
1866 1866 except AttributeError:
1867 1867 out_list.append(None)
1868 1868 else:
1869 1869 if argseq:
1870 1870 args = map(lambda lst:lst[idx],argseq)
1871 1871 #print 'ob',object,'hand',handler,'ar',args # dbg
1872 1872 out_list.append(handler(args,**kw))
1873 1873 else:
1874 1874 out_list.append(handler(**kw))
1875 1875 idx += 1
1876 1876 return out_list
1877 1877
1878 1878 #----------------------------------------------------------------------------
1879 1879 def get_class_members(cls):
1880 1880 ret = dir(cls)
1881 1881 if hasattr(cls,'__bases__'):
1882 1882 for base in cls.__bases__:
1883 1883 ret.extend(get_class_members(base))
1884 1884 return ret
1885 1885
1886 1886 #----------------------------------------------------------------------------
1887 1887 def dir2(obj):
1888 1888 """dir2(obj) -> list of strings
1889 1889
1890 1890 Extended version of the Python builtin dir(), which does a few extra
1891 1891 checks, and supports common objects with unusual internals that confuse
1892 1892 dir(), such as Traits and PyCrust.
1893 1893
1894 1894 This version is guaranteed to return only a list of true strings, whereas
1895 1895 dir() returns anything that objects inject into themselves, even if they
1896 1896 are later not really valid for attribute access (many extension libraries
1897 1897 have such bugs).
1898 1898 """
1899 1899
1900 1900 # Start building the attribute list via dir(), and then complete it
1901 1901 # with a few extra special-purpose calls.
1902 1902 words = dir(obj)
1903 1903
1904 1904 if hasattr(obj,'__class__'):
1905 1905 words.append('__class__')
1906 1906 words.extend(get_class_members(obj.__class__))
1907 1907 #if '__base__' in words: 1/0
1908 1908
1909 1909 # Some libraries (such as traits) may introduce duplicates, we want to
1910 1910 # track and clean this up if it happens
1911 1911 may_have_dupes = False
1912 1912
1913 1913 # this is the 'dir' function for objects with Enthought's traits
1914 1914 if hasattr(obj, 'trait_names'):
1915 1915 try:
1916 1916 words.extend(obj.trait_names())
1917 1917 may_have_dupes = True
1918 1918 except TypeError:
1919 1919 # This will happen if `obj` is a class and not an instance.
1920 1920 pass
1921 1921
1922 1922 # Support for PyCrust-style _getAttributeNames magic method.
1923 1923 if hasattr(obj, '_getAttributeNames'):
1924 1924 try:
1925 1925 words.extend(obj._getAttributeNames())
1926 1926 may_have_dupes = True
1927 1927 except TypeError:
1928 1928 # `obj` is a class and not an instance. Ignore
1929 1929 # this error.
1930 1930 pass
1931 1931
1932 1932 if may_have_dupes:
1933 1933 # eliminate possible duplicates, as some traits may also
1934 1934 # appear as normal attributes in the dir() call.
1935 1935 words = list(set(words))
1936 1936 words.sort()
1937 1937
1938 1938 # filter out non-string attributes which may be stuffed by dir() calls
1939 1939 # and poor coding in third-party modules
1940 1940 return [w for w in words if isinstance(w, basestring)]
1941 1941
1942 1942 #----------------------------------------------------------------------------
1943 1943 def import_fail_info(mod_name,fns=None):
1944 1944 """Inform load failure for a module."""
1945 1945
1946 1946 if fns == None:
1947 1947 warn("Loading of %s failed.\n" % (mod_name,))
1948 1948 else:
1949 1949 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
1950 1950
1951 1951 #----------------------------------------------------------------------------
1952 1952 # Proposed popitem() extension, written as a method
1953 1953
1954 1954
1955 1955 class NotGiven: pass
1956 1956
1957 1957 def popkey(dct,key,default=NotGiven):
1958 1958 """Return dct[key] and delete dct[key].
1959 1959
1960 1960 If default is given, return it if dct[key] doesn't exist, otherwise raise
1961 1961 KeyError. """
1962 1962
1963 1963 try:
1964 1964 val = dct[key]
1965 1965 except KeyError:
1966 1966 if default is NotGiven:
1967 1967 raise
1968 1968 else:
1969 1969 return default
1970 1970 else:
1971 1971 del dct[key]
1972 1972 return val
1973 1973
1974 1974 def wrap_deprecated(func, suggest = '<nothing>'):
1975 1975 def newFunc(*args, **kwargs):
1976 1976 warnings.warn("Call to deprecated function %s, use %s instead" %
1977 1977 ( func.__name__, suggest),
1978 1978 category=DeprecationWarning,
1979 1979 stacklevel = 2)
1980 1980 return func(*args, **kwargs)
1981 1981 return newFunc
1982 1982
1983 1983 #*************************** end of file <genutils.py> **********************
1984 1984
@@ -1,763 +1,763 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 IPython -- An enhanced Interactive Python
4 4
5 5 Requires Python 2.1 or better.
6 6
7 7 This file contains the main make_IPython() starter function.
8 8
9 $Id: ipmaker.py 2723 2007-09-07 07:44:16Z fperez $"""
9 $Id: ipmaker.py 2872 2007-11-25 17:58:05Z fperez $"""
10 10
11 11 #*****************************************************************************
12 12 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
13 13 #
14 14 # Distributed under the terms of the BSD License. The full license is in
15 15 # the file COPYING, distributed as part of this software.
16 16 #*****************************************************************************
17 17
18 18 from IPython import Release
19 19 __author__ = '%s <%s>' % Release.authors['Fernando']
20 20 __license__ = Release.license
21 21 __version__ = Release.version
22 22
23 23 try:
24 24 credits._Printer__data = """
25 25 Python: %s
26 26
27 27 IPython: Fernando Perez, Janko Hauser, Nathan Gray, and many users.
28 28 See http://ipython.scipy.org for more information.""" \
29 29 % credits._Printer__data
30 30
31 31 copyright._Printer__data += """
32 32
33 33 Copyright (c) 2001-2004 Fernando Perez, Janko Hauser, Nathan Gray.
34 34 All Rights Reserved."""
35 35 except NameError:
36 36 # Can happen if ipython was started with 'python -S', so that site.py is
37 37 # not loaded
38 38 pass
39 39
40 40 #****************************************************************************
41 41 # Required modules
42 42
43 43 # From the standard library
44 44 import __main__
45 45 import __builtin__
46 46 import os
47 47 import re
48 48 import sys
49 49 import types
50 50 from pprint import pprint,pformat
51 51
52 52 # Our own
53 53 from IPython import DPyGetOpt
54 54 from IPython.ipstruct import Struct
55 55 from IPython.OutputTrap import OutputTrap
56 56 from IPython.ConfigLoader import ConfigLoader
57 57 from IPython.iplib import InteractiveShell
58 58 from IPython.usage import cmd_line_usage,interactive_usage
59 59 from IPython.genutils import *
60 60
61 61 #-----------------------------------------------------------------------------
62 62 def make_IPython(argv=None,user_ns=None,user_global_ns=None,debug=1,
63 63 rc_override=None,shell_class=InteractiveShell,
64 64 embedded=False,**kw):
65 65 """This is a dump of IPython into a single function.
66 66
67 67 Later it will have to be broken up in a sensible manner.
68 68
69 69 Arguments:
70 70
71 71 - argv: a list similar to sys.argv[1:]. It should NOT contain the desired
72 72 script name, b/c DPyGetOpt strips the first argument only for the real
73 73 sys.argv.
74 74
75 75 - user_ns: a dict to be used as the user's namespace."""
76 76
77 77 #----------------------------------------------------------------------
78 78 # Defaults and initialization
79 79
80 80 # For developer debugging, deactivates crash handler and uses pdb.
81 81 DEVDEBUG = False
82 82
83 83 if argv is None:
84 84 argv = sys.argv
85 85
86 86 # __IP is the main global that lives throughout and represents the whole
87 87 # application. If the user redefines it, all bets are off as to what
88 88 # happens.
89 89
90 90 # __IP is the name of he global which the caller will have accessible as
91 91 # __IP.name. We set its name via the first parameter passed to
92 92 # InteractiveShell:
93 93
94 94 IP = shell_class('__IP',user_ns=user_ns,user_global_ns=user_global_ns,
95 95 embedded=embedded,**kw)
96 96
97 97 # Put 'help' in the user namespace
98 98 from site import _Helper
99 99 IP.user_config_ns = {}
100 100 IP.user_ns['help'] = _Helper()
101 101
102 102
103 103 if DEVDEBUG:
104 104 # For developer debugging only (global flag)
105 105 from IPython import ultraTB
106 106 sys.excepthook = ultraTB.VerboseTB(call_pdb=1)
107 107
108 108 IP.BANNER_PARTS = ['Python %s\n'
109 109 'Type "copyright", "credits" or "license" '
110 110 'for more information.\n'
111 111 % (sys.version.split('\n')[0],),
112 112 "IPython %s -- An enhanced Interactive Python."
113 113 % (__version__,),
114 114 """\
115 115 ? -> Introduction and overview of IPython's features.
116 116 %quickref -> Quick reference.
117 117 help -> Python's own help system.
118 118 object? -> Details about 'object'. ?object also works, ?? prints more.
119 119 """ ]
120 120
121 121 IP.usage = interactive_usage
122 122
123 123 # Platform-dependent suffix and directory names. We use _ipython instead
124 124 # of .ipython under win32 b/c there's software that breaks with .named
125 125 # directories on that platform.
126 126 if os.name == 'posix':
127 127 rc_suffix = ''
128 128 ipdir_def = '.ipython'
129 129 else:
130 130 rc_suffix = '.ini'
131 131 ipdir_def = '_ipython'
132 132
133 133 # default directory for configuration
134 134 ipythondir_def = os.path.abspath(os.environ.get('IPYTHONDIR',
135 135 os.path.join(IP.home_dir,ipdir_def)))
136 136
137 137 sys.path.insert(0, '') # add . to sys.path. Fix from Prabhu Ramachandran
138 138
139 139 # we need the directory where IPython itself is installed
140 140 import IPython
141 141 IPython_dir = os.path.dirname(IPython.__file__)
142 142 del IPython
143 143
144 144 #-------------------------------------------------------------------------
145 145 # Command line handling
146 146
147 147 # Valid command line options (uses DPyGetOpt syntax, like Perl's
148 148 # GetOpt::Long)
149 149
150 150 # Any key not listed here gets deleted even if in the file (like session
151 151 # or profile). That's deliberate, to maintain the rc namespace clean.
152 152
153 153 # Each set of options appears twice: under _conv only the names are
154 154 # listed, indicating which type they must be converted to when reading the
155 155 # ipythonrc file. And under DPyGetOpt they are listed with the regular
156 156 # DPyGetOpt syntax (=s,=i,:f,etc).
157 157
158 158 # Make sure there's a space before each end of line (they get auto-joined!)
159 159 cmdline_opts = ('autocall=i autoindent! automagic! banner! cache_size|cs=i '
160 160 'c=s classic|cl color_info! colors=s confirm_exit! '
161 161 'debug! deep_reload! editor=s log|l messages! nosep '
162 162 'object_info_string_level=i pdb! '
163 163 'pprint! prompt_in1|pi1=s prompt_in2|pi2=s prompt_out|po=s '
164 164 'pylab_import_all! '
165 165 'quick screen_length|sl=i prompts_pad_left=i '
166 166 'logfile|lf=s logplay|lp=s profile|p=s '
167 167 'readline! readline_merge_completions! '
168 168 'readline_omit__names! '
169 169 'rcfile=s separate_in|si=s separate_out|so=s '
170 170 'separate_out2|so2=s xmode=s wildcards_case_sensitive! '
171 171 'magic_docstrings system_verbose! '
172 172 'multi_line_specials! '
173 173 'term_title! wxversion=s '
174 174 'autoedit_syntax!')
175 175
176 176 # Options that can *only* appear at the cmd line (not in rcfiles).
177 177
178 178 # The "ignore" option is a kludge so that Emacs buffers don't crash, since
179 179 # the 'C-c !' command in emacs automatically appends a -i option at the end.
180 180 cmdline_only = ('help interact|i ipythondir=s Version upgrade '
181 181 'gthread! qthread! q4thread! wthread! pylab! tk!')
182 182
183 183 # Build the actual name list to be used by DPyGetOpt
184 184 opts_names = qw(cmdline_opts) + qw(cmdline_only)
185 185
186 186 # Set sensible command line defaults.
187 187 # This should have everything from cmdline_opts and cmdline_only
188 188 opts_def = Struct(autocall = 1,
189 189 autoedit_syntax = 0,
190 190 autoindent = 0,
191 191 automagic = 1,
192 192 banner = 1,
193 193 cache_size = 1000,
194 194 c = '',
195 195 classic = 0,
196 196 colors = 'NoColor',
197 197 color_info = 0,
198 198 confirm_exit = 1,
199 199 debug = 0,
200 200 deep_reload = 0,
201 201 editor = '0',
202 202 help = 0,
203 203 interact = 0,
204 204 ipythondir = ipythondir_def,
205 205 log = 0,
206 206 logfile = '',
207 207 logplay = '',
208 208 multi_line_specials = 1,
209 209 messages = 1,
210 210 object_info_string_level = 0,
211 211 nosep = 0,
212 212 pdb = 0,
213 213 pprint = 0,
214 214 profile = '',
215 215 prompt_in1 = 'In [\\#]: ',
216 216 prompt_in2 = ' .\\D.: ',
217 217 prompt_out = 'Out[\\#]: ',
218 218 prompts_pad_left = 1,
219 219 pylab_import_all = 1,
220 220 quiet = 0,
221 221 quick = 0,
222 222 readline = 1,
223 223 readline_merge_completions = 1,
224 224 readline_omit__names = 0,
225 225 rcfile = 'ipythonrc' + rc_suffix,
226 226 screen_length = 0,
227 227 separate_in = '\n',
228 228 separate_out = '\n',
229 229 separate_out2 = '',
230 230 system_header = 'IPython system call: ',
231 231 system_verbose = 0,
232 232 gthread = 0,
233 233 qthread = 0,
234 234 q4thread = 0,
235 235 wthread = 0,
236 236 pylab = 0,
237 237 term_title = 1,
238 238 tk = 0,
239 239 upgrade = 0,
240 240 Version = 0,
241 241 xmode = 'Verbose',
242 242 wildcards_case_sensitive = 1,
243 243 wxversion = '0',
244 244 magic_docstrings = 0, # undocumented, for doc generation
245 245 )
246 246
247 247 # Things that will *only* appear in rcfiles (not at the command line).
248 248 # Make sure there's a space before each end of line (they get auto-joined!)
249 249 rcfile_opts = { qwflat: 'include import_mod import_all execfile ',
250 250 qw_lol: 'import_some ',
251 251 # for things with embedded whitespace:
252 252 list_strings:'execute alias readline_parse_and_bind ',
253 253 # Regular strings need no conversion:
254 254 None:'readline_remove_delims ',
255 255 }
256 256 # Default values for these
257 257 rc_def = Struct(include = [],
258 258 import_mod = [],
259 259 import_all = [],
260 260 import_some = [[]],
261 261 execute = [],
262 262 execfile = [],
263 263 alias = [],
264 264 readline_parse_and_bind = [],
265 265 readline_remove_delims = '',
266 266 )
267 267
268 268 # Build the type conversion dictionary from the above tables:
269 269 typeconv = rcfile_opts.copy()
270 270 typeconv.update(optstr2types(cmdline_opts))
271 271
272 272 # FIXME: the None key appears in both, put that back together by hand. Ugly!
273 273 typeconv[None] += ' ' + rcfile_opts[None]
274 274
275 275 # Remove quotes at ends of all strings (used to protect spaces)
276 276 typeconv[unquote_ends] = typeconv[None]
277 277 del typeconv[None]
278 278
279 279 # Build the list we'll use to make all config decisions with defaults:
280 280 opts_all = opts_def.copy()
281 281 opts_all.update(rc_def)
282 282
283 283 # Build conflict resolver for recursive loading of config files:
284 284 # - preserve means the outermost file maintains the value, it is not
285 285 # overwritten if an included file has the same key.
286 286 # - add_flip applies + to the two values, so it better make sense to add
287 287 # those types of keys. But it flips them first so that things loaded
288 288 # deeper in the inclusion chain have lower precedence.
289 289 conflict = {'preserve': ' '.join([ typeconv[int],
290 290 typeconv[unquote_ends] ]),
291 291 'add_flip': ' '.join([ typeconv[qwflat],
292 292 typeconv[qw_lol],
293 293 typeconv[list_strings] ])
294 294 }
295 295
296 296 # Now actually process the command line
297 297 getopt = DPyGetOpt.DPyGetOpt()
298 298 getopt.setIgnoreCase(0)
299 299
300 300 getopt.parseConfiguration(opts_names)
301 301
302 302 try:
303 303 getopt.processArguments(argv)
304 except:
304 except DPyGetOpt.ArgumentError, exc:
305 305 print cmd_line_usage
306 warn('\nError in Arguments: ' + `sys.exc_value`)
306 warn('\nError in Arguments: "%s"' % exc)
307 307 sys.exit(1)
308 308
309 309 # convert the options dict to a struct for much lighter syntax later
310 310 opts = Struct(getopt.optionValues)
311 311 args = getopt.freeValues
312 312
313 313 # this is the struct (which has default values at this point) with which
314 314 # we make all decisions:
315 315 opts_all.update(opts)
316 316
317 317 # Options that force an immediate exit
318 318 if opts_all.help:
319 319 page(cmd_line_usage)
320 320 sys.exit()
321 321
322 322 if opts_all.Version:
323 323 print __version__
324 324 sys.exit()
325 325
326 326 if opts_all.magic_docstrings:
327 327 IP.magic_magic('-latex')
328 328 sys.exit()
329 329
330 330 # add personal ipythondir to sys.path so that users can put things in
331 331 # there for customization
332 332 sys.path.append(os.path.abspath(opts_all.ipythondir))
333 333
334 334 # Create user config directory if it doesn't exist. This must be done
335 335 # *after* getting the cmd line options.
336 336 if not os.path.isdir(opts_all.ipythondir):
337 337 IP.user_setup(opts_all.ipythondir,rc_suffix,'install')
338 338
339 339 # upgrade user config files while preserving a copy of the originals
340 340 if opts_all.upgrade:
341 341 IP.user_setup(opts_all.ipythondir,rc_suffix,'upgrade')
342 342
343 343 # check mutually exclusive options in the *original* command line
344 344 mutex_opts(opts,[qw('log logfile'),qw('rcfile profile'),
345 345 qw('classic profile'),qw('classic rcfile')])
346 346
347 347 #---------------------------------------------------------------------------
348 348 # Log replay
349 349
350 350 # if -logplay, we need to 'become' the other session. That basically means
351 351 # replacing the current command line environment with that of the old
352 352 # session and moving on.
353 353
354 354 # this is needed so that later we know we're in session reload mode, as
355 355 # opts_all will get overwritten:
356 356 load_logplay = 0
357 357
358 358 if opts_all.logplay:
359 359 load_logplay = opts_all.logplay
360 360 opts_debug_save = opts_all.debug
361 361 try:
362 362 logplay = open(opts_all.logplay)
363 363 except IOError:
364 364 if opts_all.debug: IP.InteractiveTB()
365 365 warn('Could not open logplay file '+`opts_all.logplay`)
366 366 # restore state as if nothing had happened and move on, but make
367 367 # sure that later we don't try to actually load the session file
368 368 logplay = None
369 369 load_logplay = 0
370 370 del opts_all.logplay
371 371 else:
372 372 try:
373 373 logplay.readline()
374 374 logplay.readline();
375 375 # this reloads that session's command line
376 376 cmd = logplay.readline()[6:]
377 377 exec cmd
378 378 # restore the true debug flag given so that the process of
379 379 # session loading itself can be monitored.
380 380 opts.debug = opts_debug_save
381 381 # save the logplay flag so later we don't overwrite the log
382 382 opts.logplay = load_logplay
383 383 # now we must update our own structure with defaults
384 384 opts_all.update(opts)
385 385 # now load args
386 386 cmd = logplay.readline()[6:]
387 387 exec cmd
388 388 logplay.close()
389 389 except:
390 390 logplay.close()
391 391 if opts_all.debug: IP.InteractiveTB()
392 392 warn("Logplay file lacking full configuration information.\n"
393 393 "I'll try to read it, but some things may not work.")
394 394
395 395 #-------------------------------------------------------------------------
396 396 # set up output traps: catch all output from files, being run, modules
397 397 # loaded, etc. Then give it to the user in a clean form at the end.
398 398
399 399 msg_out = 'Output messages. '
400 400 msg_err = 'Error messages. '
401 401 msg_sep = '\n'
402 402 msg = Struct(config = OutputTrap('Configuration Loader',msg_out,
403 403 msg_err,msg_sep,debug,
404 404 quiet_out=1),
405 405 user_exec = OutputTrap('User File Execution',msg_out,
406 406 msg_err,msg_sep,debug),
407 407 logplay = OutputTrap('Log Loader',msg_out,
408 408 msg_err,msg_sep,debug),
409 409 summary = ''
410 410 )
411 411
412 412 #-------------------------------------------------------------------------
413 413 # Process user ipythonrc-type configuration files
414 414
415 415 # turn on output trapping and log to msg.config
416 416 # remember that with debug on, trapping is actually disabled
417 417 msg.config.trap_all()
418 418
419 419 # look for rcfile in current or default directory
420 420 try:
421 421 opts_all.rcfile = filefind(opts_all.rcfile,opts_all.ipythondir)
422 422 except IOError:
423 423 if opts_all.debug: IP.InteractiveTB()
424 424 warn('Configuration file %s not found. Ignoring request.'
425 425 % (opts_all.rcfile) )
426 426
427 427 # 'profiles' are a shorthand notation for config filenames
428 428 profile_handled_by_legacy = False
429 429 if opts_all.profile:
430 430
431 431 try:
432 432 opts_all.rcfile = filefind('ipythonrc-' + opts_all.profile
433 433 + rc_suffix,
434 434 opts_all.ipythondir)
435 435 profile_handled_by_legacy = True
436 436 except IOError:
437 437 if opts_all.debug: IP.InteractiveTB()
438 438 opts.profile = '' # remove profile from options if invalid
439 439 # We won't warn anymore, primary method is ipy_profile_PROFNAME
440 440 # which does trigger a warning.
441 441
442 442 # load the config file
443 443 rcfiledata = None
444 444 if opts_all.quick:
445 445 print 'Launching IPython in quick mode. No config file read.'
446 446 elif opts_all.rcfile:
447 447 try:
448 448 cfg_loader = ConfigLoader(conflict)
449 449 rcfiledata = cfg_loader.load(opts_all.rcfile,typeconv,
450 450 'include',opts_all.ipythondir,
451 451 purge = 1,
452 452 unique = conflict['preserve'])
453 453 except:
454 454 IP.InteractiveTB()
455 455 warn('Problems loading configuration file '+
456 456 `opts_all.rcfile`+
457 457 '\nStarting with default -bare bones- configuration.')
458 458 else:
459 459 warn('No valid configuration file found in either currrent directory\n'+
460 460 'or in the IPython config. directory: '+`opts_all.ipythondir`+
461 461 '\nProceeding with internal defaults.')
462 462
463 463 #------------------------------------------------------------------------
464 464 # Set exception handlers in mode requested by user.
465 465 otrap = OutputTrap(trap_out=1) # trap messages from magic_xmode
466 466 IP.magic_xmode(opts_all.xmode)
467 467 otrap.release_out()
468 468
469 469 #------------------------------------------------------------------------
470 470 # Execute user config
471 471
472 472 # Create a valid config structure with the right precedence order:
473 473 # defaults < rcfile < command line. This needs to be in the instance, so
474 474 # that method calls below that rely on it find it.
475 475 IP.rc = rc_def.copy()
476 476
477 477 # Work with a local alias inside this routine to avoid unnecessary
478 478 # attribute lookups.
479 479 IP_rc = IP.rc
480 480
481 481 IP_rc.update(opts_def)
482 482 if rcfiledata:
483 483 # now we can update
484 484 IP_rc.update(rcfiledata)
485 485 IP_rc.update(opts)
486 486 IP_rc.update(rc_override)
487 487
488 488 # Store the original cmd line for reference:
489 489 IP_rc.opts = opts
490 490 IP_rc.args = args
491 491
492 492 # create a *runtime* Struct like rc for holding parameters which may be
493 493 # created and/or modified by runtime user extensions.
494 494 IP.runtime_rc = Struct()
495 495
496 496 # from this point on, all config should be handled through IP_rc,
497 497 # opts* shouldn't be used anymore.
498 498
499 499
500 500 # update IP_rc with some special things that need manual
501 501 # tweaks. Basically options which affect other options. I guess this
502 502 # should just be written so that options are fully orthogonal and we
503 503 # wouldn't worry about this stuff!
504 504
505 505 if IP_rc.classic:
506 506 IP_rc.quick = 1
507 507 IP_rc.cache_size = 0
508 508 IP_rc.pprint = 0
509 509 IP_rc.prompt_in1 = '>>> '
510 510 IP_rc.prompt_in2 = '... '
511 511 IP_rc.prompt_out = ''
512 512 IP_rc.separate_in = IP_rc.separate_out = IP_rc.separate_out2 = '0'
513 513 IP_rc.colors = 'NoColor'
514 514 IP_rc.xmode = 'Plain'
515 515
516 516 IP.pre_config_initialization()
517 517 # configure readline
518 518 # Define the history file for saving commands in between sessions
519 519 if IP_rc.profile:
520 520 histfname = 'history-%s' % IP_rc.profile
521 521 else:
522 522 histfname = 'history'
523 523 IP.histfile = os.path.join(opts_all.ipythondir,histfname)
524 524
525 525 # update exception handlers with rc file status
526 526 otrap.trap_out() # I don't want these messages ever.
527 527 IP.magic_xmode(IP_rc.xmode)
528 528 otrap.release_out()
529 529
530 530 # activate logging if requested and not reloading a log
531 531 if IP_rc.logplay:
532 532 IP.magic_logstart(IP_rc.logplay + ' append')
533 533 elif IP_rc.logfile:
534 534 IP.magic_logstart(IP_rc.logfile)
535 535 elif IP_rc.log:
536 536 IP.magic_logstart()
537 537
538 538 # find user editor so that it we don't have to look it up constantly
539 539 if IP_rc.editor.strip()=='0':
540 540 try:
541 541 ed = os.environ['EDITOR']
542 542 except KeyError:
543 543 if os.name == 'posix':
544 544 ed = 'vi' # the only one guaranteed to be there!
545 545 else:
546 546 ed = 'notepad' # same in Windows!
547 547 IP_rc.editor = ed
548 548
549 549 # Keep track of whether this is an embedded instance or not (useful for
550 550 # post-mortems).
551 551 IP_rc.embedded = IP.embedded
552 552
553 553 # Recursive reload
554 554 try:
555 555 from IPython import deep_reload
556 556 if IP_rc.deep_reload:
557 557 __builtin__.reload = deep_reload.reload
558 558 else:
559 559 __builtin__.dreload = deep_reload.reload
560 560 del deep_reload
561 561 except ImportError:
562 562 pass
563 563
564 564 # Save the current state of our namespace so that the interactive shell
565 565 # can later know which variables have been created by us from config files
566 566 # and loading. This way, loading a file (in any way) is treated just like
567 567 # defining things on the command line, and %who works as expected.
568 568
569 569 # DON'T do anything that affects the namespace beyond this point!
570 570 IP.internal_ns.update(__main__.__dict__)
571 571
572 572 #IP.internal_ns.update(locals()) # so our stuff doesn't show up in %who
573 573
574 574 # Now run through the different sections of the users's config
575 575 if IP_rc.debug:
576 576 print 'Trying to execute the following configuration structure:'
577 577 print '(Things listed first are deeper in the inclusion tree and get'
578 578 print 'loaded first).\n'
579 579 pprint(IP_rc.__dict__)
580 580
581 581 for mod in IP_rc.import_mod:
582 582 try:
583 583 exec 'import '+mod in IP.user_ns
584 584 except :
585 585 IP.InteractiveTB()
586 586 import_fail_info(mod)
587 587
588 588 for mod_fn in IP_rc.import_some:
589 589 if not mod_fn == []:
590 590 mod,fn = mod_fn[0],','.join(mod_fn[1:])
591 591 try:
592 592 exec 'from '+mod+' import '+fn in IP.user_ns
593 593 except :
594 594 IP.InteractiveTB()
595 595 import_fail_info(mod,fn)
596 596
597 597 for mod in IP_rc.import_all:
598 598 try:
599 599 exec 'from '+mod+' import *' in IP.user_ns
600 600 except :
601 601 IP.InteractiveTB()
602 602 import_fail_info(mod)
603 603
604 604 for code in IP_rc.execute:
605 605 try:
606 606 exec code in IP.user_ns
607 607 except:
608 608 IP.InteractiveTB()
609 609 warn('Failure executing code: ' + `code`)
610 610
611 611 # Execute the files the user wants in ipythonrc
612 612 for file in IP_rc.execfile:
613 613 try:
614 614 file = filefind(file,sys.path+[IPython_dir])
615 615 except IOError:
616 616 warn(itpl('File $file not found. Skipping it.'))
617 617 else:
618 618 IP.safe_execfile(os.path.expanduser(file),IP.user_ns)
619 619
620 620 # finally, try importing ipy_*_conf for final configuration
621 621 try:
622 622 import ipy_system_conf
623 623 except ImportError:
624 624 if opts_all.debug: IP.InteractiveTB()
625 625 warn("Could not import 'ipy_system_conf'")
626 626 except:
627 627 IP.InteractiveTB()
628 628 import_fail_info('ipy_system_conf')
629 629
630 630 # only import prof module if ipythonrc-PROF was not found
631 631 if opts_all.profile and not profile_handled_by_legacy:
632 632 profmodname = 'ipy_profile_' + opts_all.profile
633 633 try:
634 634 __import__(profmodname)
635 635 except:
636 636 IP.InteractiveTB()
637 637 print "Error importing",profmodname,"- perhaps you should run %upgrade?"
638 638 import_fail_info(profmodname)
639 639 else:
640 640 import ipy_profile_none
641 641 try:
642 642 import ipy_user_conf
643 643
644 644 except:
645 645 conf = opts_all.ipythondir + "/ipy_user_conf.py"
646 646 IP.InteractiveTB()
647 647 if not os.path.isfile(conf):
648 648 warn(conf + ' does not exist, please run %upgrade!')
649 649
650 650 import_fail_info("ipy_user_conf")
651 651
652 652 # finally, push the argv to options again to ensure highest priority
653 653 IP_rc.update(opts)
654 654
655 655 # release stdout and stderr and save config log into a global summary
656 656 msg.config.release_all()
657 657 if IP_rc.messages:
658 658 msg.summary += msg.config.summary_all()
659 659
660 660 #------------------------------------------------------------------------
661 661 # Setup interactive session
662 662
663 663 # Now we should be fully configured. We can then execute files or load
664 664 # things only needed for interactive use. Then we'll open the shell.
665 665
666 666 # Take a snapshot of the user namespace before opening the shell. That way
667 667 # we'll be able to identify which things were interactively defined and
668 668 # which were defined through config files.
669 669 IP.user_config_ns.update(IP.user_ns)
670 670
671 671 # Force reading a file as if it were a session log. Slower but safer.
672 672 if load_logplay:
673 673 print 'Replaying log...'
674 674 try:
675 675 if IP_rc.debug:
676 676 logplay_quiet = 0
677 677 else:
678 678 logplay_quiet = 1
679 679
680 680 msg.logplay.trap_all()
681 681 IP.safe_execfile(load_logplay,IP.user_ns,
682 682 islog = 1, quiet = logplay_quiet)
683 683 msg.logplay.release_all()
684 684 if IP_rc.messages:
685 685 msg.summary += msg.logplay.summary_all()
686 686 except:
687 687 warn('Problems replaying logfile %s.' % load_logplay)
688 688 IP.InteractiveTB()
689 689
690 690 # Load remaining files in command line
691 691 msg.user_exec.trap_all()
692 692
693 693 # Do NOT execute files named in the command line as scripts to be loaded
694 694 # by embedded instances. Doing so has the potential for an infinite
695 695 # recursion if there are exceptions thrown in the process.
696 696
697 697 # XXX FIXME: the execution of user files should be moved out to after
698 698 # ipython is fully initialized, just as if they were run via %run at the
699 699 # ipython prompt. This would also give them the benefit of ipython's
700 700 # nice tracebacks.
701 701
702 702 if (not embedded and IP_rc.args and
703 703 not IP_rc.args[0].lower().endswith('.ipy')):
704 704 name_save = IP.user_ns['__name__']
705 705 IP.user_ns['__name__'] = '__main__'
706 706 # Set our own excepthook in case the user code tries to call it
707 707 # directly. This prevents triggering the IPython crash handler.
708 708 old_excepthook,sys.excepthook = sys.excepthook, IP.excepthook
709 709
710 710 save_argv = sys.argv[1:] # save it for later restoring
711 711
712 712 sys.argv = args
713 713
714 714 try:
715 715 IP.safe_execfile(args[0], IP.user_ns)
716 716 finally:
717 717 # Reset our crash handler in place
718 718 sys.excepthook = old_excepthook
719 719 sys.argv[:] = save_argv
720 720 IP.user_ns['__name__'] = name_save
721 721
722 722 msg.user_exec.release_all()
723 723
724 724 if IP_rc.messages:
725 725 msg.summary += msg.user_exec.summary_all()
726 726
727 727 # since we can't specify a null string on the cmd line, 0 is the equivalent:
728 728 if IP_rc.nosep:
729 729 IP_rc.separate_in = IP_rc.separate_out = IP_rc.separate_out2 = '0'
730 730 if IP_rc.separate_in == '0': IP_rc.separate_in = ''
731 731 if IP_rc.separate_out == '0': IP_rc.separate_out = ''
732 732 if IP_rc.separate_out2 == '0': IP_rc.separate_out2 = ''
733 733 IP_rc.separate_in = IP_rc.separate_in.replace('\\n','\n')
734 734 IP_rc.separate_out = IP_rc.separate_out.replace('\\n','\n')
735 735 IP_rc.separate_out2 = IP_rc.separate_out2.replace('\\n','\n')
736 736
737 737 # Determine how many lines at the bottom of the screen are needed for
738 738 # showing prompts, so we can know wheter long strings are to be printed or
739 739 # paged:
740 740 num_lines_bot = IP_rc.separate_in.count('\n')+1
741 741 IP_rc.screen_length = IP_rc.screen_length - num_lines_bot
742 742
743 743 # configure startup banner
744 744 if IP_rc.c: # regular python doesn't print the banner with -c
745 745 IP_rc.banner = 0
746 746 if IP_rc.banner:
747 747 BANN_P = IP.BANNER_PARTS
748 748 else:
749 749 BANN_P = []
750 750
751 751 if IP_rc.profile: BANN_P.append('IPython profile: %s\n' % IP_rc.profile)
752 752
753 753 # add message log (possibly empty)
754 754 if msg.summary: BANN_P.append(msg.summary)
755 755 # Final banner is a string
756 756 IP.BANNER = '\n'.join(BANN_P)
757 757
758 758 # Finalize the IPython instance. This assumes the rc structure is fully
759 759 # in place.
760 760 IP.post_config_initialization()
761 761
762 762 return IP
763 763 #************************ end of file <ipmaker.py> **************************
1 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