| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498 |
- import types
- import string
- import re
- import math
- import operator
- def ifAbsentPut(dict, key, newValue):
- """
- If dict has key, return the value, otherwise insert the newValue and return it
- """
- if dict.has_key(key):
- return dict[key]
- else:
- dict[key] = newValue
- return newValue
- def unique(L1, L2):
- """Return a list containing all items in 'L1' that are not in 'L2'"""
- L2 = dict([(k,None) for k in L2])
- return [item for item in L1 if item not in L2]
- def indent(stream, numIndents, str):
- """
- Write str to stream with numIndents in front it it
- """
- # To match emacs, instead of a tab character we will use 4 spaces
- stream.write(' ' * numIndents + str)
- def apropos(obj, *args):
- """
- Obsolete, use pdir
- """
- print 'Use pdir instead'
- def getClassLineage(obj):
- """ getClassLineage(obj): print object inheritance list """
- # Just a dictionary, return dictionary
- if type(obj) == types.DictionaryType:
- return [obj]
- # Instance, make a list with the instance and its class interitance
- elif type(obj) == types.InstanceType:
- return [obj] + getClassLineage(obj.__class__)
- # Class, see what it derives from
- elif type(obj) == types.ClassType:
- lineage = [obj]
- for c in obj.__bases__:
- lineage = lineage + getClassLineage(c)
- return lineage
- # Not what I'm looking for
- else:
- return []
- def pdir(obj, str = None, fOverloaded = 0, width = None,
- fTruncate = 1, lineWidth = 75, wantPrivate = 0):
- # Remove redundant class entries
- uniqueLineage = []
- for l in getClassLineage(obj):
- if type(l) == types.ClassType:
- if l in uniqueLineage:
- break
- uniqueLineage.append(l)
- # Pretty print out directory info
- uniqueLineage.reverse()
- for obj in uniqueLineage:
- _pdir(obj, str, fOverloaded, width, fTruncate, lineWidth, wantPrivate)
- print
- def _pdir(obj, str = None, fOverloaded = 0, width = None,
- fTruncate = 1, lineWidth = 75, wantPrivate = 0):
- """
- Print out a formatted list of members and methods of an instance or class
- """
- def printHeader(name):
- name = ' ' + name + ' '
- length = len(name)
- if length < 70:
- padBefore = int((70 - length)/2.0)
- padAfter = max(0,70 - length - padBefore)
- header = '*' * padBefore + name + '*' * padAfter
- print header
- print
- def printInstanceHeader(i, printHeader = printHeader):
- printHeader(i.__class__.__name__ + ' INSTANCE INFO')
- def printClassHeader(c, printHeader = printHeader):
- printHeader(c.__name__ + ' CLASS INFO')
- def printDictionaryHeader(d, printHeader = printHeader):
- printHeader('DICTIONARY INFO')
- # Print Header
- if type(obj) == types.InstanceType:
- printInstanceHeader(obj)
- elif type(obj) == types.ClassType:
- printClassHeader(obj)
- elif type (obj) == types.DictionaryType:
- printDictionaryHeader(obj)
- # Get dict
- if type(obj) == types.DictionaryType:
- dict = obj
- else:
- dict = obj.__dict__
- # Adjust width
- if width:
- maxWidth = width
- else:
- maxWidth = 10
- keyWidth = 0
- aproposKeys = []
- privateKeys = []
- remainingKeys = []
- for key in dict.keys():
- if not width:
- keyWidth = len(key)
- if str:
- if re.search(str, key, re.I):
- aproposKeys.append(key)
- if (not width) and (keyWidth > maxWidth):
- maxWidth = keyWidth
- else:
- if key[:1] == '_':
- if wantPrivate:
- privateKeys.append(key)
- if (not width) and (keyWidth > maxWidth):
- maxWidth = keyWidth
- else:
- remainingKeys.append(key)
- if (not width) and (keyWidth > maxWidth):
- maxWidth = keyWidth
- # Sort appropriate keys
- if str:
- aproposKeys.sort()
- else:
- privateKeys.sort()
- remainingKeys.sort()
- # Print out results
- if wantPrivate:
- keys = aproposKeys + privateKeys + remainingKeys
- else:
- keys = aproposKeys + remainingKeys
- format = '%-' + `maxWidth` + 's'
- for key in keys:
- value = dict[key]
- if callable(value):
- strvalue = `Signature(value)`
- else:
- strvalue = `value`
- if fTruncate:
- # Cut off line (keeping at least 1 char)
- strvalue = strvalue[:max(1,lineWidth - maxWidth)]
- print (format % key)[:maxWidth] + '\t' + strvalue
- # Magic numbers: These are the bit masks in func_code.co_flags that
- # reveal whether or not the function has a *arg or **kw argument.
- _POS_LIST = 4
- _KEY_DICT = 8
- def _is_variadic(function):
- return function.func_code.co_flags & _POS_LIST
- def _has_keywordargs(function):
- return function.func_code.co_flags & _KEY_DICT
- def _varnames(function):
- return function.func_code.co_varnames
- def _getcode(f):
- """
- _getcode(f)
- This function returns the name and function object of a callable
- object.
- """
- def method_get(f):
- return f.__name__, f.im_func
- def function_get(f):
- return f.__name__, f
- def instance_get(f):
- if hasattr(f, '__call__'):
- method = f.__call__
- if (type(method) == types.MethodType):
- func = method.im_func
- else:
- func = method
- return ("%s%s" % (f.__class__.__name__, '__call__'), func)
- else:
- s = ("Instance %s of class %s does not have a __call__ method" %
- (f, f.__class__.__name__))
- raise TypeError, s
- def class_get(f):
- if hasattr(f, '__init__'):
- return f.__name__, f.__init__.im_func
- else:
- return f.__name__, lambda: None
- codedict = { types.UnboundMethodType: method_get,
- types.MethodType : method_get,
- types.FunctionType : function_get,
- types.InstanceType : instance_get,
- types.ClassType : class_get,
- }
- try:
- return codedict[type(f)](f)
- except KeyError:
- if callable(f): # eg, built-in functions and methods
- # raise ValueError, "type %s not supported yet." % type(f)
- return f.__name__, None
- else:
- raise TypeError, ("object %s of type %s is not callable." %
- (f, type(f)))
- class Signature:
- def __init__(self, func):
- self.type = type(func)
- self.name, self.func = _getcode(func)
- def ordinary_args(self):
- n = self.func.func_code.co_argcount
- return _varnames(self.func)[0:n]
- def special_args(self):
- n = self.func.func_code.co_argcount
- x = {}
- #
- if _is_variadic(self.func):
- x['positional'] = _varnames(self.func)[n]
- if _has_keywordargs(self.func):
- x['keyword'] = _varnames(self.func)[n+1]
- elif _has_keywordargs(self.func):
- x['keyword'] = _varnames(self.func)[n]
- else:
- pass
- return x
- def full_arglist(self):
- base = list(self.ordinary_args())
- x = self.special_args()
- if x.has_key('positional'):
- base.append(x['positional'])
- if x.has_key('keyword'):
- base.append(x['keyword'])
- return base
- def defaults(self):
- defargs = self.func.func_defaults
- args = self.ordinary_args()
- mapping = {}
- if defargs is not None:
- for i in range(-1, -(len(defargs)+1), -1):
- mapping[args[i]] = defargs[i]
- else:
- pass
- return mapping
- def __repr__(self):
- if self.func:
- defaults = self.defaults()
- specials = self.special_args()
- l = []
- for arg in self.ordinary_args():
- if defaults.has_key(arg):
- l.append( arg + '=' + str(defaults[arg]) )
- else:
- l.append( arg )
- if specials.has_key('positional'):
- l.append( '*' + specials['positional'] )
- if specials.has_key('keyword'):
- l.append( '**' + specials['keyword'] )
- return "%s(%s)" % (self.name, string.join(l, ', '))
- else:
- return "%s(?)" % self.name
- def aproposAll(obj):
- """
- Print out a list of all members and methods (including overloaded methods)
- of an instance or class
- """
- apropos(obj, fOverloaded = 1, fTruncate = 0)
- def doc(obj):
- if (isinstance(obj, types.MethodType)) or \
- (isinstance(obj, types.FunctionType)):
- print obj.__doc__
- def adjust(command = None, dim = 1, parent = None, **kw):
- """
- adjust(command = None, parent = None, **kw)
- Popup and entry scale to adjust a parameter
-
- Accepts any Slider keyword argument. Typical arguments include:
- command: The one argument command to execute
- min: The min value of the slider
- max: The max value of the slider
- resolution: The resolution of the slider
- text: The label on the slider
-
- These values can be accessed and/or changed after the fact
- >>> vg = adjust()
- >>> vg['min']
- 0.0
- >>> vg['min'] = 10.0
- >>> vg['min']
- 10.0
- """
- # Make sure we enable Tk
- import Valuator
- # Set command if specified
- if command:
- kw['command'] = lambda x: apply(command, x)
- if parent is None:
- kw['title'] = command.__name__
- kw['dim'] = dim
- # Create toplevel if needed
- if not parent:
- vg = apply(Valuator.ValuatorGroupPanel, (parent,), kw)
- else:
- vg = apply(Valuator.ValuatorGroup,(parent,), kw)
- vg.pack(expand = 1, fill = 'x')
- return vg
- def intersection(a, b):
- """
- intersection(list, list):
- """
- if not a: return []
- if not b: return []
- c = a + b
- d = []
- for i in c:
- if (i in a) and (i in b):
- # make it unique, like a set
- if (i not in d):
- d.append(i)
- return d
- def union(a, b):
- """
- union(list, list):
- """
- # Copy a
- c = a[:]
- for i in b:
- if (i not in c):
- c.append(i)
- return c
- def sameElements(a, b):
- if len(a) != len(b):
- return 0
- for elem in a:
- if elem not in b:
- return 0
- for elem in b:
- if elem not in a:
- return 0
- return 1
- def contains(whole, sub):
- """
- Return 1 if whole contains sub, 0 otherwise
- """
- if (whole == sub):
- return 1
- for elem in sub:
- # The first item you find not in whole, return 0
- if elem not in whole:
- return 0
- # If you got here, whole must contain sub
- return 1
- def replace(list, old, new, all=0):
- """
- replace 'old' with 'new' in 'list'
- if all == 0, replace first occurrence
- otherwise replace all occurrences
- returns the number of items replaced
- """
- if old not in list:
- return 0
- if not all:
- i = list.index(old)
- list[i] = new
- return 1
- else:
- numReplaced = 0
- for i in xrange(len(list)):
- if list[i] == old:
- numReplaced += 1
- list[i] = new
- return numReplaced
- def reduceAngle(deg):
- """
- Reduces an angle (in degrees) to a value in [-180..180)
- """
- return (((deg + 180.) % 360.) - 180.)
-
- def fitSrcAngle2Dest(src, dest):
- """
- given a src and destination angle, returns an equivalent src angle
- that is within [-180..180) of dest
- examples:
- fitSrcAngle2Dest(30,60) == 30
- fitSrcAngle2Dest(60,30) == 60
- fitSrcAngle2Dest(0,180) == 0
- fitSrcAngle2Dest(-1,180) == 359
- fitSrcAngle2Dest(-180,180) == 180
- """
- return dest + reduceAngle(src - dest)
- def fitDestAngle2Src(src, dest):
- """
- given a src and destination angle, returns an equivalent dest angle
- that is within [-180..180) of src
- examples:
- fitDestAngle2Src(30,60) == 60
- fitDestAngle2Src(60,30) == 30
- fitDestAngle2Src(0,180) == -180
- fitDestAngle2Src(1,180) == 180
- """
- return src + (reduceAngle(dest - src))
- def closestDestAngle2(src, dest):
- # The function above didn't seem to do what I wanted. So I hacked
- # this one together. I can't really say I understand it. It's more
- # from impirical observation... GRW
- diff = src - dest
- # if the difference is greater that 180 it's shorter to go the other way
- if diff > 180:
- return dest - 360
- # or perhaps the OTHER other way...
- elif diff < -180:
- return dest + 360
- # otherwise just go to the original destination
- else:
- return dest
- def closestDestAngle(src, dest):
- # The function above didn't seem to do what I wanted. So I hacked
- # this one together. I can't really say I understand it. It's more
- # from impirical observation... GRW
- diff = src - dest
- # if the difference is greater that 180 it's shorter to go the other way
- if diff > 180:
- return src - (diff - 360)
- # or perhaps the OTHER other way...
- elif diff < -180:
- return src - (360 + diff)
- # otherwise just go to the original destination
- else:
- return dest
- def binaryRepr(number, max_length = 32):
- # This will only work reliably for relatively small numbers.
- # Increase the value of max_length if you think you're going
- # to use long integers
- assert number < 2L << max_length
- shifts = map (operator.rshift, max_length * [number], \
- range (max_length - 1, -1, -1))
- digits = map (operator.mod, shifts, max_length * [2])
- if not digits.count (1): return 0
- digits = digits [digits.index (1):]
- return string.join (map (repr, digits), '')
- # constant profile defaults
- PyUtilProfileDefaultFilename = 'profiledata'
- PyUtilProfileDefaultLines = 80
- PyUtilProfileDefaultSorts = ['cumulative', 'time', 'calls']
- # call this from the prompt, and break back out to the prompt
- # to stop profiling
- def startProfile(filename=PyUtilProfileDefaultFilename,
- lines=PyUtilProfileDefaultLines,
- sorts=PyUtilProfileDefaultSorts,
- silent=0):
- import profile
- profile.run('run()', filename)
- if not silent:
- printProfile(filename, lines, sorts)
- # call this to see the results again
- def printProfile(filename=PyUtilProfileDefaultFilename,
- lines=PyUtilProfileDefaultLines,
- sorts=PyUtilProfileDefaultSorts,):
- import pstats
- s = pstats.Stats(filename)
- s.strip_dirs()
- for sort in sorts:
- s.sort_stats(sort)
- s.print_stats(lines)
- class Functor:
- def __init__(self, function, *args, **kargs):
- assert callable(function), "function should be a callable obj"
- self._function = function
- self._args = args
- self._kargs = kargs
-
- def __call__(self, *args, **kargs):
- """call function"""
- _args = list(self._args)
- _args.extend(args)
- _kargs = self._kargs.copy()
- _kargs.update(kargs)
- return apply(self._function,_args,_kargs)
|