summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1992-09-02 20:43:20 (GMT)
committerGuido van Rossum <guido@python.org>1992-09-02 20:43:20 (GMT)
commit4e16098ce74c645cf1d69566b6f8bc96031554b7 (patch)
tree919ce6e774608fbf5a2e4745472e9fbc445139e9
parent2179945eec5ab32b4aa88b9f7a9308a898cde8a5 (diff)
downloadcpython-4e16098ce74c645cf1d69566b6f8bc96031554b7.zip
cpython-4e16098ce74c645cf1d69566b6f8bc96031554b7.tar.gz
cpython-4e16098ce74c645cf1d69566b6f8bc96031554b7.tar.bz2
Added a _v21 def to FL.py and added two new input field types
Added runcall(func, *args) interfaces to profile.py, bdb.py, pdb.py, wdb.py Added new module bisect.py and used it in sched.py. Mostly cosmetic changes to profile.py (changed output format).
-rw-r--r--Lib/bdb.py37
-rw-r--r--Lib/bisect.py23
-rwxr-xr-xLib/irix5/FL.py4
-rw-r--r--Lib/lib-stdwin/wdb.py5
-rwxr-xr-xLib/pdb.py3
-rwxr-xr-xLib/plat-irix5/FL.py4
-rwxr-xr-xLib/profile.py233
-rw-r--r--Lib/sched.py13
-rwxr-xr-xLib/stdwin/wdb.py5
9 files changed, 167 insertions, 160 deletions
diff --git a/Lib/bdb.py b/Lib/bdb.py
index 15a8023..8a722fe 100644
--- a/Lib/bdb.py
+++ b/Lib/bdb.py
@@ -68,7 +68,7 @@ class Bdb: # Basic Debugger
return self.trace_dispatch
# Normally derived classes don't override the following
- # functions, but they may if they want to redefine the
+ # methods, but they may if they want to redefine the
# definition of stopping and breakpoints.
def stop_here(self, frame):
@@ -93,28 +93,28 @@ class Bdb: # Basic Debugger
def break_anywhere(self, frame):
return self.breaks.has_key(frame.f_code.co_filename)
- # Derived classes should override the user_* functions
+ # Derived classes should override the user_* methods
# to gain control.
def user_call(self, frame, argument_list):
- # This function is called when there is the remote possibility
+ # This method is called when there is the remote possibility
# that we ever need to stop in this function
pass
def user_line(self, frame):
- # This function is called when we stop or break at this line
+ # This method is called when we stop or break at this line
pass
def user_return(self, frame, return_value):
- # This function is called when a return trap is set here
+ # This method is called when a return trap is set here
pass
def user_exception(self, frame, (exc_type, exc_value, exc_traceback)):
- # This function is called if an exception occurs,
+ # This method is called if an exception occurs,
# but only if we are to stop at or just below this level
pass
- # Derived classes and clients can call the following functions
+ # Derived classes and clients can call the following methods
# to affect the stepping state.
def set_step(self):
@@ -147,8 +147,8 @@ class Bdb: # Basic Debugger
self.quitting = 1
sys.settrace(None)
- # Derived classes and clients can call the following functions
- # to manipulate breakpoints. These functions return an
+ # Derived classes and clients can call the following methods
+ # to manipulate breakpoints. These methods return an
# error message is something went wrong, None if all is well.
# Call self.get_*break*() to see the breakpoints.
@@ -196,7 +196,7 @@ class Bdb: # Basic Debugger
def get_all_breaks(self):
return self.breaks
- # Derived classes and clients can call the following function
+ # Derived classes and clients can call the following method
# to get a data structure representing a stack trace.
def get_stack(self, f, t):
@@ -234,7 +234,7 @@ class Bdb: # Basic Debugger
if line: s = s + ': ' + string.strip(line)
return s
- # The following two functions can be called by clients to use
+ # The following two methods can be called by clients to use
# a debugger to debug a statement, given as a string.
def run(self, cmd):
@@ -253,7 +253,20 @@ class Bdb: # Basic Debugger
finally:
self.quitting = 1
sys.settrace(None)
- # XXX What to do if the command finishes normally?
+
+ # This method is more useful to debug a single function call.
+
+ def runcall(self, func, *args):
+ self.reset()
+ sys.settrace(self.trace_dispatch)
+ try:
+ try:
+ apply(func, args)
+ except BdbQuit:
+ pass
+ finally:
+ self.quitting = 1
+ sys.settrace(None)
# -------------------- testing --------------------
diff --git a/Lib/bisect.py b/Lib/bisect.py
new file mode 100644
index 0000000..688666a
--- /dev/null
+++ b/Lib/bisect.py
@@ -0,0 +1,23 @@
+# Bisection algorithms
+
+
+# Insert item x in list a, and keep it sorted assuming a is sorted
+
+def insort(a, x):
+ lo, hi = 0, len(a)
+ while lo < hi:
+ mid = (lo+hi)/2
+ if x < a[mid]: hi = mid
+ else: lo = mid+1
+ a.insert(lo, x)
+
+
+# Find the index where to insert item x in list a, assuming a is sorted
+
+def bisect(a, x):
+ lo, hi = 0, len(a)
+ while lo < hi:
+ mid = (lo+hi)/2
+ if x < a[mid]: hi = mid
+ else: lo = mid+1
+ return lo
diff --git a/Lib/irix5/FL.py b/Lib/irix5/FL.py
index 3142b1b..65184df 100755
--- a/Lib/irix5/FL.py
+++ b/Lib/irix5/FL.py
@@ -4,6 +4,7 @@
# Alternate use: from FL import *; ... NORMAL_BOX ... etc.
_v20 = 1
+_v21 = 1
##import fl
##try:
## _v20 = (fl.get_rgbmode <> None)
@@ -198,6 +199,9 @@ if _v20:
FLOAT_INPUT = 1
INT_INPUT = 2
HIDDEN_INPUT = 3
+ if _v21:
+ MULTILINE_INPUT = 4
+ SECRET_INPUT = 5
else:
ALWAYS_INPUT = 1
INPUT_BOXTYPE = DOWN_BOX
diff --git a/Lib/lib-stdwin/wdb.py b/Lib/lib-stdwin/wdb.py
index 9914f3f..b3d6b73 100644
--- a/Lib/lib-stdwin/wdb.py
+++ b/Lib/lib-stdwin/wdb.py
@@ -283,6 +283,11 @@ def runctx(statement, globals, locals):
try: x.runctx(statement, globals, locals)
finally: x.close()
+def runcall(*args):
+ x = Wdb().init()
+ try: apply(Pdb().init().runcall, args)
+ finally: x.close()
+
TESTCMD = 'import x; x.main()'
def test():
diff --git a/Lib/pdb.py b/Lib/pdb.py
index 0dd975b..f564f64 100755
--- a/Lib/pdb.py
+++ b/Lib/pdb.py
@@ -254,6 +254,9 @@ def run(statement):
def runctx(statement, globals, locals):
Pdb().init().runctx(statement, globals, locals)
+def runcall(*args):
+ apply(Pdb().init().runcall, args)
+
TESTCMD = 'import x; x.main()'
def test():
diff --git a/Lib/plat-irix5/FL.py b/Lib/plat-irix5/FL.py
index 3142b1b..65184df 100755
--- a/Lib/plat-irix5/FL.py
+++ b/Lib/plat-irix5/FL.py
@@ -4,6 +4,7 @@
# Alternate use: from FL import *; ... NORMAL_BOX ... etc.
_v20 = 1
+_v21 = 1
##import fl
##try:
## _v20 = (fl.get_rgbmode <> None)
@@ -198,6 +199,9 @@ if _v20:
FLOAT_INPUT = 1
INT_INPUT = 2
HIDDEN_INPUT = 3
+ if _v21:
+ MULTILINE_INPUT = 4
+ SECRET_INPUT = 5
else:
ALWAYS_INPUT = 1
INPUT_BOXTYPE = DOWN_BOX
diff --git a/Lib/profile.py b/Lib/profile.py
index 1c7a6e2..046b70b 100755
--- a/Lib/profile.py
+++ b/Lib/profile.py
@@ -1,12 +1,16 @@
#
# Class for profiling python code.
# Author: Sjoerd Mullender
+# Hacked somewhat by: Guido van Rossum
#
# See the accompanying document profile.doc for more information.
import sys
import codehack
-import posix
+import os
+import string
+import fpformat
+import marshal
class Profile():
@@ -30,7 +34,7 @@ class Profile():
if self.profile_func.has_key(funcname):
return
self.profiling = 1
- t = posix.times()
+ t = os.times()
t = t[0] + t[1]
lineno = codehack.getlineno(frame.f_code)
filename = frame.f_code.co_filename
@@ -42,13 +46,16 @@ class Profile():
s0 = 'call: ' + key + ' depth: ' + `self.call_level` + ' time: ' + `t`
if pframe:
pkey = pframe.f_code.co_filename + ':' + \
- `codehack.getlineno(pframe.f_code)` + '(' + \
- codehack.getcodename(pframe.f_code) + ')'
+ `codehack.getlineno(pframe.f_code)` \
+ + '(' + \
+ codehack.getcodename(pframe.f_code) \
+ + ')'
if self.debug:
s1 = 'parent: ' + pkey
if pframe.f_locals.has_key('__start_time'):
st = pframe.f_locals['__start_time']
- nc, tt, ct, callers, callees = self.timings[pkey]
+ nc, tt, ct, callers, callees = \
+ self.timings[pkey]
if self.debug:
s1 = s1+' before: st='+`st`+' nc='+`nc`+' tt='+`tt`+' ct='+`ct`
if callers.has_key(key):
@@ -80,7 +87,8 @@ class Profile():
if self.profile_func:
if not self.profiling:
return
- if self.profile_func.has_key(codehack.getcodename(frame.f_code)):
+ if self.profile_func.has_key( \
+ codehack.getcodename(frame.f_code)):
self.profiling = 0
self.call_level = depth(frame)
self.cur_frame = frame
@@ -106,11 +114,12 @@ class Profile():
self.call_level = call_level
self.cur_frame = frame
return
- print 'profile.Profile.dispatch: unknown debugging event:', `event`
+ print 'profile.Profile.dispatch: unknown debugging event:',
+ print `event`
return
def handle_return(self, pframe, frame, s0):
- t = posix.times()
+ t = os.times()
t = t[0] + t[1]
funcname = codehack.getcodename(frame.f_code)
lineno = codehack.getlineno(frame.f_code)
@@ -128,11 +137,13 @@ class Profile():
if pframe.f_locals.has_key('__start_time') and \
self.timings.has_key(pkey):
st = pframe.f_locals['__start_time']
- nc, tt, ct, callers, callees = self.timings[pkey]
+ nc, tt, ct, callers, callees = \
+ self.timings[pkey]
if self.debug:
s1 = s1+' before: st='+`st`+' nc='+`nc`+' tt='+`tt`+' ct='+`ct`
s1 = s1+' after: st='+`t`+' nc='+`nc`+' tt='+`tt`+' ct='+`ct+(t-st)`
- self.timings[pkey] = nc, tt, ct + (t - st), callers, callees
+ self.timings[pkey] = \
+ nc, tt, ct + (t - st), callers, callees
pframe.f_locals['__start_time'] = t
if self.timings.has_key(key):
nc, tt, ct, callers, callees = self.timings[key]
@@ -147,35 +158,30 @@ class Profile():
s0 = s0+' after: nc='+`nc`+' tt='+`tt+(t-st)`+' ct='+`ct+(t-st)`
print s0
print s1
- self.timings[key] = nc, tt + (t - st), ct + (t - st), callers, callees
+ self.timings[key] = \
+ nc, tt + (t - st), ct + (t - st), callers, callees
def print_stats(self):
- import string
- s = string.rjust('# calls', 8)
- s = s + ' ' + string.rjust('tot time', 8)
- s = s + ' ' + string.rjust('per call', 8)
- s = s + ' ' + string.rjust('cum time', 8)
- s = s + ' ' + string.rjust('per call', 8)
- print s + ' filename(function)'
+ # Print in reverse order by ct
+ print_title()
+ list = []
for key in self.timings.keys():
nc, tt, ct, callers, callees = self.timings[key]
if nc == 0:
continue
- s = string.rjust(`nc`, 8)
- s = s + ' ' + string.rjust(`tt`, 8)
- s = s + ' ' + string.rjust(`tt/nc`, 8)
- s = s + ' ' + string.rjust(`ct`, 8)
- s = s + ' ' + string.rjust(`ct/nc`, 8)
- print s + ' ' + key
+ list.append(ct, tt, nc, key)
+ list.sort()
+ list.reverse()
+ for ct, tt, nc, key in list:
+ print_line(nc, tt, ct, os.path.basename(key))
def dump_stats(self, file):
- import marshal
f = open(file, 'w')
marshal.dump(self.timings, f)
f.close()
- # The following two functions can be called by clients to use
- # a debugger to debug a statement, given as a string.
+ # The following two methods can be called by clients to use
+ # a profiler to profile a statement, given as a string.
def run(self, cmd):
import __main__
@@ -183,17 +189,21 @@ class Profile():
self.runctx(cmd, dict, dict)
def runctx(self, cmd, globals, locals):
-## self.reset()
sys.setprofile(self.trace_dispatch)
try:
-## try:
- exec(cmd + '\n', globals, locals)
-## except ProfQuit:
-## pass
+ exec(cmd + '\n', globals, locals)
finally:
-## self.quitting = 1
sys.setprofile(None)
- # XXX What to do if the command finishes normally?
+
+ # This method is more useful to profile a single function call.
+
+ def runcall(self, func, *args):
+ sys.setprofile(self.trace_dispatch)
+ try:
+ apply(func, args)
+ finally:
+ sys.setprofile(None)
+
def depth(frame):
d = 0
@@ -202,98 +212,8 @@ def depth(frame):
frame = frame.f_back
return d
-def run(statement, *args):
- prof = Profile().init()
- try:
- prof.run(statement)
- except SystemExit:
- pass
- if len(args) == 0:
- prof.print_stats()
- else:
- prof.dump_stats(args[0])
-
-def cv_float(val, width):
- import string
- s = `val`
- try:
- e = string.index(s, 'e')
- exp = s[e+1:]
- s = s[:e]
- width = width - len(exp) - 1
- except string.index_error:
- exp = ''
- try:
- d = string.index(s, '.')
- frac = s[d+1:]
- s = s[:d]
- width = width - len(s) - 1
- except string.index_error:
- if exp <> '':
- return s + 'e' + exp
- else:
- return s
- if width < 0:
- width = 0
- while width < len(frac):
- c = frac[width]
- frac = frac[:width]
- if ord(c) >= ord('5'):
- carry = 1
- for i in range(width-1, -1, -1):
- if frac[i] == '9':
- frac = frac[:i]
- # keep if trailing zeroes are wanted
- # + '0' + frac[i+1:width]
- else:
- frac = frac[:i] + chr(ord(frac[i])+1) + frac[i+1:width]
- carry = 0
- break
- if carry:
- for i in range(len(s)-1, -1, -1):
- if s[i] == '9':
- s = s[:i] + '0' + s[i+1:]
- if i == 0:
- # gets one wider, so
- # should shorten
- # fraction by one
- s = '1' + s
- if width > 0:
- width = width - 1
- else:
- s = s[:i] + chr(ord(s[i])+1) + s[i+1:]
- break
- # delete trailing zeroes
- for i in range(len(frac)-1, -1, -1):
- if frac[i] == '0':
- frac = frac[:i]
- else:
- break
- # build up the number
- if width > 0 and len(frac) > 0:
- s = s + '.' + frac[:width]
- if exp <> '':
- s = s + 'e' + exp
- return s
-
-def print_line(nc, tt, ct, callers, callees, key):
- import string
- s = string.rjust(cv_float(nc,8), 8)
- s = s + ' ' + string.rjust(cv_float(tt,8), 8)
- if nc == 0:
- s = s + ' '*9
- else:
- s = s + ' ' + string.rjust(cv_float(tt/nc,8), 8)
- s = s + ' ' + string.rjust(cv_float(ct,8), 8)
- if nc == 0:
- s = s + ' '*9
- else:
- s = s + ' ' + string.rjust(cv_float(ct/nc,8), 8)
- print s + ' ' + key
-
class Stats():
def init(self, file):
- import marshal
f = open(file, 'r')
self.stats = marshal.load(f)
f.close()
@@ -301,26 +221,22 @@ class Stats():
return self
def print_stats(self):
- import string
- s = string.rjust('# calls', 8)
- s = s + ' ' + string.rjust('tot time', 8)
- s = s + ' ' + string.rjust('per call', 8)
- s = s + ' ' + string.rjust('cum time', 8)
- s = s + ' ' + string.rjust('per call', 8)
- print s + ' filename(function)'
+ print_title()
if self.stats_list:
for i in range(len(self.stats_list)):
- nc, tt, ct, callers, callees, key = self.stats_list[i]
- print_line(nc, tt, ct, callers, callees, key)
+ nc, tt, ct, callers, callees, key = \
+ self.stats_list[i]
+ print_line(nc, tt, ct, key)
else:
for key in self.stats.keys():
nc, tt, ct, callers, callees = self.stats[key]
- print_line(nc, tt, ct, callers, callees, key)
+ print_line(nc, tt, ct, key)
def print_callers(self):
if self.stats_list:
for i in range(len(self.stats_list)):
- nc, tt, ct, callers, callees, key = self.stats_list[i]
+ nc, tt, ct, callers, callees, key = \
+ self.stats_list[i]
print key,
for func in callers.keys():
print func+'('+`callers[func]`+')',
@@ -336,7 +252,8 @@ class Stats():
def print_callees(self):
if self.stats_list:
for i in range(len(self.stats_list)):
- nc, tt, ct, callers, callees, key = self.stats_list[i]
+ nc, tt, ct, callers, callees, key = \
+ self.stats_list[i]
print key,
for func in callees.keys():
print func+'('+`callees[func]`+')',
@@ -375,8 +292,10 @@ class Stats():
nt = nt[:field] + t[0:1] + nt[field:]
self.stats_list.append(nt)
+ def reverse_order(self):
+ self.stats_list.reverse()
+
def strip_dirs(self):
- import os
newstats = {}
for key in self.stats.keys():
nc, tt, ct, callers, callees = self.stats[key]
@@ -391,7 +310,44 @@ class Stats():
self.stats = newstats
self.stats_list = None
-# test command
+def print_title():
+ print string.rjust('ncalls', 8),
+ print string.rjust('tottime', 8),
+ print string.rjust('percall', 8),
+ print string.rjust('cumtime', 8),
+ print string.rjust('percall', 8),
+ print 'filename:lineno(function)'
+
+def print_line(nc, tt, ct, key):
+ print string.rjust(`nc`, 8),
+ print f8(tt),
+ if nc == 0:
+ print ' '*8,
+ else:
+ print f8(tt/nc),
+ print f8(ct),
+ if nc == 0:
+ print ' '*8,
+ else:
+ print f8(ct/nc),
+ print key
+
+def f8(x):
+ return string.rjust(fpformat.fix(x, 3), 8)
+
+# simplified user interface
+def run(statement, *args):
+ prof = Profile().init()
+ try:
+ prof.run(statement)
+ except SystemExit:
+ pass
+ if len(args) == 0:
+ prof.print_stats()
+ else:
+ prof.dump_stats(args[0])
+
+# test command with debugging
def debug():
prof = Profile().init()
prof.debug = 1
@@ -401,5 +357,6 @@ def debug():
pass
prof.print_stats()
+# test command
def test():
run('import x; x.main()')
diff --git a/Lib/sched.py b/Lib/sched.py
index 4a45309..685b2bc 100644
--- a/Lib/sched.py
+++ b/Lib/sched.py
@@ -28,6 +28,8 @@
# XXX instead of having to define a module or class just to hold
# XXX the global state of your particular time and delay functtions.
+import bisect
+
class scheduler:
#
# Initialize a new instance, passing the time and delay functions
@@ -43,16 +45,7 @@ class scheduler:
# to remove it, if necessary.
#
def enterabs(self, event):
- time, priority, action, argument = event
- q = self.queue
- # XXX Could use bisection or linear interpolation?
- for i in range(len(q)):
- qtime, qpri, qact, qarg = q[i]
- if time < qtime: break
- if time == qtime and priority < qpri: break
- else:
- i = len(q)
- q.insert(i, event)
+ bisect.insort(self.queue, event)
return event # The ID
#
# A variant that specifies the time as a relative time.
diff --git a/Lib/stdwin/wdb.py b/Lib/stdwin/wdb.py
index 9914f3f..b3d6b73 100755
--- a/Lib/stdwin/wdb.py
+++ b/Lib/stdwin/wdb.py
@@ -283,6 +283,11 @@ def runctx(statement, globals, locals):
try: x.runctx(statement, globals, locals)
finally: x.close()
+def runcall(*args):
+ x = Wdb().init()
+ try: apply(Pdb().init().runcall, args)
+ finally: x.close()
+
TESTCMD = 'import x; x.main()'
def test():