Whitespace normalization.

This commit is contained in:
Tim Peters 2001-01-15 01:18:21 +00:00
parent 2344fae6d0
commit 0c9886d589
7 changed files with 488 additions and 488 deletions

View file

@ -28,101 +28,101 @@ from math import log, exp, pi, e, sqrt, acos, cos, sin
# XXX TO DO: make the distribution functions below into methods. # XXX TO DO: make the distribution functions below into methods.
def makeseed(a=None): def makeseed(a=None):
"""Turn a hashable value into three seed values for whrandom.seed(). """Turn a hashable value into three seed values for whrandom.seed().
None or no argument returns (0, 0, 0), to seed from current time. None or no argument returns (0, 0, 0), to seed from current time.
""" """
if a is None: if a is None:
return (0, 0, 0) return (0, 0, 0)
a = hash(a) a = hash(a)
a, x = divmod(a, 256) a, x = divmod(a, 256)
a, y = divmod(a, 256) a, y = divmod(a, 256)
a, z = divmod(a, 256) a, z = divmod(a, 256)
x = (x + a) % 256 or 1 x = (x + a) % 256 or 1
y = (y + a) % 256 or 1 y = (y + a) % 256 or 1
z = (z + a) % 256 or 1 z = (z + a) % 256 or 1
return (x, y, z) return (x, y, z)
def seed(a=None): def seed(a=None):
"""Seed the default generator from any hashable value. """Seed the default generator from any hashable value.
None or no argument seeds from current time. None or no argument seeds from current time.
""" """
x, y, z = makeseed(a) x, y, z = makeseed(a)
whrandom.seed(x, y, z) whrandom.seed(x, y, z)
class generator(whrandom.whrandom): class generator(whrandom.whrandom):
"""Random generator class.""" """Random generator class."""
def __init__(self, a=None): def __init__(self, a=None):
"""Constructor. Seed from current time or hashable value.""" """Constructor. Seed from current time or hashable value."""
self.seed(a) self.seed(a)
def seed(self, a=None): def seed(self, a=None):
"""Seed the generator from current time or hashable value.""" """Seed the generator from current time or hashable value."""
x, y, z = makeseed(a) x, y, z = makeseed(a)
whrandom.whrandom.seed(self, x, y, z) whrandom.whrandom.seed(self, x, y, z)
def new_generator(a=None): def new_generator(a=None):
"""Return a new random generator instance.""" """Return a new random generator instance."""
return generator(a) return generator(a)
# Housekeeping function to verify that magic constants have been # Housekeeping function to verify that magic constants have been
# computed correctly # computed correctly
def verify(name, expected): def verify(name, expected):
computed = eval(name) computed = eval(name)
if abs(computed - expected) > 1e-7: if abs(computed - expected) > 1e-7:
raise ValueError, \ raise ValueError, \
'computed value for %s deviates too much (computed %g, expected %g)' % \ 'computed value for %s deviates too much (computed %g, expected %g)' % \
(name, computed, expected) (name, computed, expected)
# -------------------- normal distribution -------------------- # -------------------- normal distribution --------------------
NV_MAGICCONST = 4*exp(-0.5)/sqrt(2.0) NV_MAGICCONST = 4*exp(-0.5)/sqrt(2.0)
verify('NV_MAGICCONST', 1.71552776992141) verify('NV_MAGICCONST', 1.71552776992141)
def normalvariate(mu, sigma): def normalvariate(mu, sigma):
# mu = mean, sigma = standard deviation # mu = mean, sigma = standard deviation
# Uses Kinderman and Monahan method. Reference: Kinderman, # Uses Kinderman and Monahan method. Reference: Kinderman,
# A.J. and Monahan, J.F., "Computer generation of random # A.J. and Monahan, J.F., "Computer generation of random
# variables using the ratio of uniform deviates", ACM Trans # variables using the ratio of uniform deviates", ACM Trans
# Math Software, 3, (1977), pp257-260. # Math Software, 3, (1977), pp257-260.
while 1: while 1:
u1 = random() u1 = random()
u2 = random() u2 = random()
z = NV_MAGICCONST*(u1-0.5)/u2 z = NV_MAGICCONST*(u1-0.5)/u2
zz = z*z/4.0 zz = z*z/4.0
if zz <= -log(u2): if zz <= -log(u2):
break break
return mu+z*sigma return mu+z*sigma
# -------------------- lognormal distribution -------------------- # -------------------- lognormal distribution --------------------
def lognormvariate(mu, sigma): def lognormvariate(mu, sigma):
return exp(normalvariate(mu, sigma)) return exp(normalvariate(mu, sigma))
# -------------------- circular uniform -------------------- # -------------------- circular uniform --------------------
def cunifvariate(mean, arc): def cunifvariate(mean, arc):
# mean: mean angle (in radians between 0 and pi) # mean: mean angle (in radians between 0 and pi)
# arc: range of distribution (in radians between 0 and pi) # arc: range of distribution (in radians between 0 and pi)
return (mean + arc * (random() - 0.5)) % pi return (mean + arc * (random() - 0.5)) % pi
# -------------------- exponential distribution -------------------- # -------------------- exponential distribution --------------------
def expovariate(lambd): def expovariate(lambd):
# lambd: rate lambd = 1/mean # lambd: rate lambd = 1/mean
# ('lambda' is a Python reserved word) # ('lambda' is a Python reserved word)
u = random() u = random()
while u <= 1e-7: while u <= 1e-7:
u = random() u = random()
return -log(u)/lambd return -log(u)/lambd
# -------------------- von Mises distribution -------------------- # -------------------- von Mises distribution --------------------
@ -130,43 +130,43 @@ TWOPI = 2.0*pi
verify('TWOPI', 6.28318530718) verify('TWOPI', 6.28318530718)
def vonmisesvariate(mu, kappa): def vonmisesvariate(mu, kappa):
# mu: mean angle (in radians between 0 and 2*pi) # mu: mean angle (in radians between 0 and 2*pi)
# kappa: concentration parameter kappa (>= 0) # kappa: concentration parameter kappa (>= 0)
# if kappa = 0 generate uniform random angle # if kappa = 0 generate uniform random angle
# Based upon an algorithm published in: Fisher, N.I., # Based upon an algorithm published in: Fisher, N.I.,
# "Statistical Analysis of Circular Data", Cambridge # "Statistical Analysis of Circular Data", Cambridge
# University Press, 1993. # University Press, 1993.
# Thanks to Magnus Kessler for a correction to the # Thanks to Magnus Kessler for a correction to the
# implementation of step 4. # implementation of step 4.
if kappa <= 1e-6: if kappa <= 1e-6:
return TWOPI * random() return TWOPI * random()
a = 1.0 + sqrt(1.0 + 4.0 * kappa * kappa) a = 1.0 + sqrt(1.0 + 4.0 * kappa * kappa)
b = (a - sqrt(2.0 * a))/(2.0 * kappa) b = (a - sqrt(2.0 * a))/(2.0 * kappa)
r = (1.0 + b * b)/(2.0 * b) r = (1.0 + b * b)/(2.0 * b)
while 1: while 1:
u1 = random() u1 = random()
z = cos(pi * u1) z = cos(pi * u1)
f = (1.0 + r * z)/(r + z) f = (1.0 + r * z)/(r + z)
c = kappa * (r - f) c = kappa * (r - f)
u2 = random() u2 = random()
if not (u2 >= c * (2.0 - c) and u2 > c * exp(1.0 - c)): if not (u2 >= c * (2.0 - c) and u2 > c * exp(1.0 - c)):
break break
u3 = random() u3 = random()
if u3 > 0.5: if u3 > 0.5:
theta = (mu % TWOPI) + acos(f) theta = (mu % TWOPI) + acos(f)
else: else:
theta = (mu % TWOPI) - acos(f) theta = (mu % TWOPI) - acos(f)
return theta return theta
# -------------------- gamma distribution -------------------- # -------------------- gamma distribution --------------------
@ -174,62 +174,62 @@ LOG4 = log(4.0)
verify('LOG4', 1.38629436111989) verify('LOG4', 1.38629436111989)
def gammavariate(alpha, beta): def gammavariate(alpha, beta):
# beta times standard gamma # beta times standard gamma
ainv = sqrt(2.0 * alpha - 1.0) ainv = sqrt(2.0 * alpha - 1.0)
return beta * stdgamma(alpha, ainv, alpha - LOG4, alpha + ainv) return beta * stdgamma(alpha, ainv, alpha - LOG4, alpha + ainv)
SG_MAGICCONST = 1.0 + log(4.5) SG_MAGICCONST = 1.0 + log(4.5)
verify('SG_MAGICCONST', 2.50407739677627) verify('SG_MAGICCONST', 2.50407739677627)
def stdgamma(alpha, ainv, bbb, ccc): def stdgamma(alpha, ainv, bbb, ccc):
# ainv = sqrt(2 * alpha - 1) # ainv = sqrt(2 * alpha - 1)
# bbb = alpha - log(4) # bbb = alpha - log(4)
# ccc = alpha + ainv # ccc = alpha + ainv
if alpha <= 0.0: if alpha <= 0.0:
raise ValueError, 'stdgamma: alpha must be > 0.0' raise ValueError, 'stdgamma: alpha must be > 0.0'
if alpha > 1.0: if alpha > 1.0:
# Uses R.C.H. Cheng, "The generation of Gamma # Uses R.C.H. Cheng, "The generation of Gamma
# variables with non-integral shape parameters", # variables with non-integral shape parameters",
# Applied Statistics, (1977), 26, No. 1, p71-74 # Applied Statistics, (1977), 26, No. 1, p71-74
while 1: while 1:
u1 = random() u1 = random()
u2 = random() u2 = random()
v = log(u1/(1.0-u1))/ainv v = log(u1/(1.0-u1))/ainv
x = alpha*exp(v) x = alpha*exp(v)
z = u1*u1*u2 z = u1*u1*u2
r = bbb+ccc*v-x r = bbb+ccc*v-x
if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= log(z): if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= log(z):
return x return x
elif alpha == 1.0: elif alpha == 1.0:
# expovariate(1) # expovariate(1)
u = random() u = random()
while u <= 1e-7: while u <= 1e-7:
u = random() u = random()
return -log(u) return -log(u)
else: # alpha is between 0 and 1 (exclusive) else: # alpha is between 0 and 1 (exclusive)
# Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
while 1: while 1:
u = random() u = random()
b = (e + alpha)/e b = (e + alpha)/e
p = b*u p = b*u
if p <= 1.0: if p <= 1.0:
x = pow(p, 1.0/alpha) x = pow(p, 1.0/alpha)
else: else:
# p > 1 # p > 1
x = -log((b-p)/alpha) x = -log((b-p)/alpha)
u1 = random() u1 = random()
if not (((p <= 1.0) and (u1 > exp(-x))) or if not (((p <= 1.0) and (u1 > exp(-x))) or
((p > 1) and (u1 > pow(x, alpha - 1.0)))): ((p > 1) and (u1 > pow(x, alpha - 1.0)))):
break break
return x return x
# -------------------- Gauss (faster alternative) -------------------- # -------------------- Gauss (faster alternative) --------------------
@ -237,61 +237,61 @@ def stdgamma(alpha, ainv, bbb, ccc):
gauss_next = None gauss_next = None
def gauss(mu, sigma): def gauss(mu, sigma):
# When x and y are two variables from [0, 1), uniformly # When x and y are two variables from [0, 1), uniformly
# distributed, then # distributed, then
# #
# cos(2*pi*x)*sqrt(-2*log(1-y)) # cos(2*pi*x)*sqrt(-2*log(1-y))
# sin(2*pi*x)*sqrt(-2*log(1-y)) # sin(2*pi*x)*sqrt(-2*log(1-y))
# #
# are two *independent* variables with normal distribution # are two *independent* variables with normal distribution
# (mu = 0, sigma = 1). # (mu = 0, sigma = 1).
# (Lambert Meertens) # (Lambert Meertens)
# (corrected version; bug discovered by Mike Miller, fixed by LM) # (corrected version; bug discovered by Mike Miller, fixed by LM)
# Multithreading note: When two threads call this function # Multithreading note: When two threads call this function
# simultaneously, it is possible that they will receive the # simultaneously, it is possible that they will receive the
# same return value. The window is very small though. To # same return value. The window is very small though. To
# avoid this, you have to use a lock around all calls. (I # avoid this, you have to use a lock around all calls. (I
# didn't want to slow this down in the serial case by using a # didn't want to slow this down in the serial case by using a
# lock here.) # lock here.)
global gauss_next global gauss_next
z = gauss_next z = gauss_next
gauss_next = None gauss_next = None
if z is None: if z is None:
x2pi = random() * TWOPI x2pi = random() * TWOPI
g2rad = sqrt(-2.0 * log(1.0 - random())) g2rad = sqrt(-2.0 * log(1.0 - random()))
z = cos(x2pi) * g2rad z = cos(x2pi) * g2rad
gauss_next = sin(x2pi) * g2rad gauss_next = sin(x2pi) * g2rad
return mu + z*sigma return mu + z*sigma
# -------------------- beta -------------------- # -------------------- beta --------------------
def betavariate(alpha, beta): def betavariate(alpha, beta):
# Discrete Event Simulation in C, pp 87-88. # Discrete Event Simulation in C, pp 87-88.
y = expovariate(alpha) y = expovariate(alpha)
z = expovariate(1.0/beta) z = expovariate(1.0/beta)
return z/(y+z) return z/(y+z)
# -------------------- Pareto -------------------- # -------------------- Pareto --------------------
def paretovariate(alpha): def paretovariate(alpha):
# Jain, pg. 495 # Jain, pg. 495
u = random() u = random()
return 1.0 / pow(u, 1.0/alpha) return 1.0 / pow(u, 1.0/alpha)
# -------------------- Weibull -------------------- # -------------------- Weibull --------------------
def weibullvariate(alpha, beta): def weibullvariate(alpha, beta):
# Jain, pg. 499; bug fix courtesy Bill Arms # Jain, pg. 499; bug fix courtesy Bill Arms
u = random() u = random()
return alpha * pow(-log(u), 1.0/beta) return alpha * pow(-log(u), 1.0/beta)
# -------------------- shuffle -------------------- # -------------------- shuffle --------------------
# Not quite a random distribution, but a standard algorithm. # Not quite a random distribution, but a standard algorithm.
@ -310,55 +310,55 @@ def shuffle(x, random=random, int=int):
""" """
for i in xrange(len(x)-1, 0, -1): for i in xrange(len(x)-1, 0, -1):
# pick an element in x[:i+1] with which to exchange x[i] # pick an element in x[:i+1] with which to exchange x[i]
j = int(random() * (i+1)) j = int(random() * (i+1))
x[i], x[j] = x[j], x[i] x[i], x[j] = x[j], x[i]
# -------------------- test program -------------------- # -------------------- test program --------------------
def test(N = 200): def test(N = 200):
print 'TWOPI =', TWOPI print 'TWOPI =', TWOPI
print 'LOG4 =', LOG4 print 'LOG4 =', LOG4
print 'NV_MAGICCONST =', NV_MAGICCONST print 'NV_MAGICCONST =', NV_MAGICCONST
print 'SG_MAGICCONST =', SG_MAGICCONST print 'SG_MAGICCONST =', SG_MAGICCONST
test_generator(N, 'random()') test_generator(N, 'random()')
test_generator(N, 'normalvariate(0.0, 1.0)') test_generator(N, 'normalvariate(0.0, 1.0)')
test_generator(N, 'lognormvariate(0.0, 1.0)') test_generator(N, 'lognormvariate(0.0, 1.0)')
test_generator(N, 'cunifvariate(0.0, 1.0)') test_generator(N, 'cunifvariate(0.0, 1.0)')
test_generator(N, 'expovariate(1.0)') test_generator(N, 'expovariate(1.0)')
test_generator(N, 'vonmisesvariate(0.0, 1.0)') test_generator(N, 'vonmisesvariate(0.0, 1.0)')
test_generator(N, 'gammavariate(0.5, 1.0)') test_generator(N, 'gammavariate(0.5, 1.0)')
test_generator(N, 'gammavariate(0.9, 1.0)') test_generator(N, 'gammavariate(0.9, 1.0)')
test_generator(N, 'gammavariate(1.0, 1.0)') test_generator(N, 'gammavariate(1.0, 1.0)')
test_generator(N, 'gammavariate(2.0, 1.0)') test_generator(N, 'gammavariate(2.0, 1.0)')
test_generator(N, 'gammavariate(20.0, 1.0)') test_generator(N, 'gammavariate(20.0, 1.0)')
test_generator(N, 'gammavariate(200.0, 1.0)') test_generator(N, 'gammavariate(200.0, 1.0)')
test_generator(N, 'gauss(0.0, 1.0)') test_generator(N, 'gauss(0.0, 1.0)')
test_generator(N, 'betavariate(3.0, 3.0)') test_generator(N, 'betavariate(3.0, 3.0)')
test_generator(N, 'paretovariate(1.0)') test_generator(N, 'paretovariate(1.0)')
test_generator(N, 'weibullvariate(1.0, 1.0)') test_generator(N, 'weibullvariate(1.0, 1.0)')
def test_generator(n, funccall): def test_generator(n, funccall):
import time import time
print n, 'times', funccall print n, 'times', funccall
code = compile(funccall, funccall, 'eval') code = compile(funccall, funccall, 'eval')
sum = 0.0 sum = 0.0
sqsum = 0.0 sqsum = 0.0
smallest = 1e10 smallest = 1e10
largest = -1e10 largest = -1e10
t0 = time.time() t0 = time.time()
for i in range(n): for i in range(n):
x = eval(code) x = eval(code)
sum = sum + x sum = sum + x
sqsum = sqsum + x*x sqsum = sqsum + x*x
smallest = min(x, smallest) smallest = min(x, smallest)
largest = max(x, largest) largest = max(x, largest)
t1 = time.time() t1 = time.time()
print round(t1-t0, 3), 'sec,', print round(t1-t0, 3), 'sec,',
avg = sum/n avg = sum/n
stddev = sqrt(sqsum/n - avg*avg) stddev = sqrt(sqsum/n - avg*avg)
print 'avg %g, stddev %g, min %g, max %g' % \ print 'avg %g, stddev %g, min %g, max %g' % \
(avg, stddev, smallest, largest) (avg, stddev, smallest, largest)
if __name__ == '__main__': if __name__ == '__main__':
test() test()

View file

@ -33,9 +33,9 @@ RE_NEWLINE_OR = 16
# their special meaning regardless of the surrounding context. # their special meaning regardless of the surrounding context.
# 1 means that special characters may act as normal characters in some # 1 means that special characters may act as normal characters in some
# contexts. Specifically, this applies to: # contexts. Specifically, this applies to:
# ^ - only special at the beginning, or after ( or | # ^ - only special at the beginning, or after ( or |
# $ - only special at the end, or before ) or | # $ - only special at the end, or before ) or |
# *, +, ? - only special when not after the beginning, (, or | # *, +, ? - only special when not after the beginning, (, or |
RE_CONTEXT_INDEP_OPS = 32 RE_CONTEXT_INDEP_OPS = 32
# ANSI sequences (\n etc) and \xhh # ANSI sequences (\n etc) and \xhh

View file

@ -12,7 +12,7 @@ splitx(str, pat, maxsplit): split string using pattern as delimiter plus
import warnings import warnings
warnings.warn("the regsub module is deprecated; please use re.sub()", warnings.warn("the regsub module is deprecated; please use re.sub()",
DeprecationWarning) DeprecationWarning)
# Ignore further deprecation warnings about this module # Ignore further deprecation warnings about this module
warnings.filterwarnings("ignore", "", DeprecationWarning, __name__) warnings.filterwarnings("ignore", "", DeprecationWarning, __name__)
@ -27,12 +27,12 @@ import regex
# compiled pattern. # compiled pattern.
def sub(pat, repl, str): def sub(pat, repl, str):
prog = compile(pat) prog = compile(pat)
if prog.search(str) >= 0: if prog.search(str) >= 0:
regs = prog.regs regs = prog.regs
a, b = regs[0] a, b = regs[0]
str = str[:a] + expand(repl, regs, str) + str[b:] str = str[:a] + expand(repl, regs, str) + str[b:]
return str return str
# Replace all (non-overlapping) occurrences of pattern pat in string # Replace all (non-overlapping) occurrences of pattern pat in string
@ -41,23 +41,23 @@ def sub(pat, repl, str):
# a previous match, so e.g. gsub('', '-', 'abc') returns '-a-b-c-'. # a previous match, so e.g. gsub('', '-', 'abc') returns '-a-b-c-'.
def gsub(pat, repl, str): def gsub(pat, repl, str):
prog = compile(pat) prog = compile(pat)
new = '' new = ''
start = 0 start = 0
first = 1 first = 1
while prog.search(str, start) >= 0: while prog.search(str, start) >= 0:
regs = prog.regs regs = prog.regs
a, b = regs[0] a, b = regs[0]
if a == b == start and not first: if a == b == start and not first:
if start >= len(str) or prog.search(str, start+1) < 0: if start >= len(str) or prog.search(str, start+1) < 0:
break break
regs = prog.regs regs = prog.regs
a, b = regs[0] a, b = regs[0]
new = new + str[start:a] + expand(repl, regs, str) new = new + str[start:a] + expand(repl, regs, str)
start = b start = b
first = 0 first = 0
new = new + str[start:] new = new + str[start:]
return new return new
# Split string str in fields separated by delimiters matching pattern # Split string str in fields separated by delimiters matching pattern
@ -66,7 +66,7 @@ def gsub(pat, repl, str):
# The optional 3rd argument sets the number of splits that are performed. # The optional 3rd argument sets the number of splits that are performed.
def split(str, pat, maxsplit = 0): def split(str, pat, maxsplit = 0):
return intsplit(str, pat, maxsplit, 0) return intsplit(str, pat, maxsplit, 0)
# Split string str in fields separated by delimiters matching pattern # Split string str in fields separated by delimiters matching pattern
# pat. Only non-empty matches for the pattern are considered, so e.g. # pat. Only non-empty matches for the pattern are considered, so e.g.
@ -76,42 +76,42 @@ def split(str, pat, maxsplit = 0):
def splitx(str, pat, maxsplit = 0): def splitx(str, pat, maxsplit = 0):
return intsplit(str, pat, maxsplit, 1) return intsplit(str, pat, maxsplit, 1)
# Internal function used to implement split() and splitx(). # Internal function used to implement split() and splitx().
def intsplit(str, pat, maxsplit, retain): def intsplit(str, pat, maxsplit, retain):
prog = compile(pat) prog = compile(pat)
res = [] res = []
start = next = 0 start = next = 0
splitcount = 0 splitcount = 0
while prog.search(str, next) >= 0: while prog.search(str, next) >= 0:
regs = prog.regs regs = prog.regs
a, b = regs[0] a, b = regs[0]
if a == b: if a == b:
next = next + 1 next = next + 1
if next >= len(str): if next >= len(str):
break break
else: else:
res.append(str[start:a]) res.append(str[start:a])
if retain: if retain:
res.append(str[a:b]) res.append(str[a:b])
start = next = b start = next = b
splitcount = splitcount + 1 splitcount = splitcount + 1
if (maxsplit and (splitcount >= maxsplit)): if (maxsplit and (splitcount >= maxsplit)):
break break
res.append(str[start:]) res.append(str[start:])
return res return res
# Capitalize words split using a pattern # Capitalize words split using a pattern
def capwords(str, pat='[^a-zA-Z0-9_]+'): def capwords(str, pat='[^a-zA-Z0-9_]+'):
import string import string
words = splitx(str, pat) words = splitx(str, pat)
for i in range(0, len(words), 2): for i in range(0, len(words), 2):
words[i] = string.capitalize(words[i]) words[i] = string.capitalize(words[i])
return string.joinfields(words, "") return string.joinfields(words, "")
# Internal subroutines: # Internal subroutines:
@ -131,19 +131,19 @@ def capwords(str, pat='[^a-zA-Z0-9_]+'):
cache = {} cache = {}
def compile(pat): def compile(pat):
if type(pat) != type(''): if type(pat) != type(''):
return pat # Assume it is a compiled regex return pat # Assume it is a compiled regex
key = (pat, regex.get_syntax()) key = (pat, regex.get_syntax())
if cache.has_key(key): if cache.has_key(key):
prog = cache[key] # Get it from the cache prog = cache[key] # Get it from the cache
else: else:
prog = cache[key] = regex.compile(pat) prog = cache[key] = regex.compile(pat)
return prog return prog
def clear_cache(): def clear_cache():
global cache global cache
cache = {} cache = {}
# Expand \digit in the replacement. # Expand \digit in the replacement.
@ -153,46 +153,46 @@ def clear_cache():
# the \ and the following character are both copied). # the \ and the following character are both copied).
def expand(repl, regs, str): def expand(repl, regs, str):
if '\\' not in repl: if '\\' not in repl:
return repl return repl
new = '' new = ''
i = 0 i = 0
ord0 = ord('0') ord0 = ord('0')
while i < len(repl): while i < len(repl):
c = repl[i]; i = i+1 c = repl[i]; i = i+1
if c != '\\' or i >= len(repl): if c != '\\' or i >= len(repl):
new = new + c new = new + c
else: else:
c = repl[i]; i = i+1 c = repl[i]; i = i+1
if '0' <= c <= '9': if '0' <= c <= '9':
a, b = regs[ord(c)-ord0] a, b = regs[ord(c)-ord0]
new = new + str[a:b] new = new + str[a:b]
elif c == '\\': elif c == '\\':
new = new + c new = new + c
else: else:
new = new + '\\' + c new = new + '\\' + c
return new return new
# Test program, reads sequences "pat repl str" from stdin. # Test program, reads sequences "pat repl str" from stdin.
# Optional argument specifies pattern used to split lines. # Optional argument specifies pattern used to split lines.
def test(): def test():
import sys import sys
if sys.argv[1:]: if sys.argv[1:]:
delpat = sys.argv[1] delpat = sys.argv[1]
else: else:
delpat = '[ \t\n]+' delpat = '[ \t\n]+'
while 1: while 1:
if sys.stdin.isatty(): sys.stderr.write('--> ') if sys.stdin.isatty(): sys.stderr.write('--> ')
line = sys.stdin.readline() line = sys.stdin.readline()
if not line: break if not line: break
if line[-1] == '\n': line = line[:-1] if line[-1] == '\n': line = line[:-1]
fields = split(line, delpat) fields = split(line, delpat)
if len(fields) != 3: if len(fields) != 3:
print 'Sorry, not three fields' print 'Sorry, not three fields'
print 'split:', `fields` print 'split:', `fields`
continue continue
[pat, repl, str] = split(line, delpat) [pat, repl, str] = split(line, delpat)
print 'sub :', `sub(pat, repl, str)` print 'sub :', `sub(pat, repl, str)`
print 'gsub:', `gsub(pat, repl, str)` print 'gsub:', `gsub(pat, repl, str)`

View file

@ -3,93 +3,93 @@
import string import string
class Repr: class Repr:
def __init__(self): def __init__(self):
self.maxlevel = 6 self.maxlevel = 6
self.maxtuple = 6 self.maxtuple = 6
self.maxlist = 6 self.maxlist = 6
self.maxdict = 4 self.maxdict = 4
self.maxstring = 30 self.maxstring = 30
self.maxlong = 40 self.maxlong = 40
self.maxother = 20 self.maxother = 20
def repr(self, x): def repr(self, x):
return self.repr1(x, self.maxlevel) return self.repr1(x, self.maxlevel)
def repr1(self, x, level): def repr1(self, x, level):
typename = `type(x)`[7:-2] # "<type '......'>" typename = `type(x)`[7:-2] # "<type '......'>"
if ' ' in typename: if ' ' in typename:
parts = string.split(typename) parts = string.split(typename)
typename = string.joinfields(parts, '_') typename = string.joinfields(parts, '_')
if hasattr(self, 'repr_' + typename): if hasattr(self, 'repr_' + typename):
return getattr(self, 'repr_' + typename)(x, level) return getattr(self, 'repr_' + typename)(x, level)
else: else:
s = `x` s = `x`
if len(s) > self.maxother: if len(s) > self.maxother:
i = max(0, (self.maxother-3)/2) i = max(0, (self.maxother-3)/2)
j = max(0, self.maxother-3-i) j = max(0, self.maxother-3-i)
s = s[:i] + '...' + s[len(s)-j:] s = s[:i] + '...' + s[len(s)-j:]
return s return s
def repr_tuple(self, x, level): def repr_tuple(self, x, level):
n = len(x) n = len(x)
if n == 0: return '()' if n == 0: return '()'
if level <= 0: return '(...)' if level <= 0: return '(...)'
s = '' s = ''
for i in range(min(n, self.maxtuple)): for i in range(min(n, self.maxtuple)):
if s: s = s + ', ' if s: s = s + ', '
s = s + self.repr1(x[i], level-1) s = s + self.repr1(x[i], level-1)
if n > self.maxtuple: s = s + ', ...' if n > self.maxtuple: s = s + ', ...'
elif n == 1: s = s + ',' elif n == 1: s = s + ','
return '(' + s + ')' return '(' + s + ')'
def repr_list(self, x, level): def repr_list(self, x, level):
n = len(x) n = len(x)
if n == 0: return '[]' if n == 0: return '[]'
if level <= 0: return '[...]' if level <= 0: return '[...]'
s = '' s = ''
for i in range(min(n, self.maxlist)): for i in range(min(n, self.maxlist)):
if s: s = s + ', ' if s: s = s + ', '
s = s + self.repr1(x[i], level-1) s = s + self.repr1(x[i], level-1)
if n > self.maxlist: s = s + ', ...' if n > self.maxlist: s = s + ', ...'
return '[' + s + ']' return '[' + s + ']'
def repr_dictionary(self, x, level): def repr_dictionary(self, x, level):
n = len(x) n = len(x)
if n == 0: return '{}' if n == 0: return '{}'
if level <= 0: return '{...}' if level <= 0: return '{...}'
s = '' s = ''
keys = x.keys() keys = x.keys()
keys.sort() keys.sort()
for i in range(min(n, self.maxdict)): for i in range(min(n, self.maxdict)):
if s: s = s + ', ' if s: s = s + ', '
key = keys[i] key = keys[i]
s = s + self.repr1(key, level-1) s = s + self.repr1(key, level-1)
s = s + ': ' + self.repr1(x[key], level-1) s = s + ': ' + self.repr1(x[key], level-1)
if n > self.maxdict: s = s + ', ...' if n > self.maxdict: s = s + ', ...'
return '{' + s + '}' return '{' + s + '}'
def repr_string(self, x, level): def repr_string(self, x, level):
s = `x[:self.maxstring]` s = `x[:self.maxstring]`
if len(s) > self.maxstring: if len(s) > self.maxstring:
i = max(0, (self.maxstring-3)/2) i = max(0, (self.maxstring-3)/2)
j = max(0, self.maxstring-3-i) j = max(0, self.maxstring-3-i)
s = `x[:i] + x[len(x)-j:]` s = `x[:i] + x[len(x)-j:]`
s = s[:i] + '...' + s[len(s)-j:] s = s[:i] + '...' + s[len(s)-j:]
return s return s
def repr_long_int(self, x, level): def repr_long_int(self, x, level):
s = `x` # XXX Hope this isn't too slow... s = `x` # XXX Hope this isn't too slow...
if len(s) > self.maxlong: if len(s) > self.maxlong:
i = max(0, (self.maxlong-3)/2) i = max(0, (self.maxlong-3)/2)
j = max(0, self.maxlong-3-i) j = max(0, self.maxlong-3-i)
s = s[:i] + '...' + s[len(s)-j:] s = s[:i] + '...' + s[len(s)-j:]
return s return s
def repr_instance(self, x, level): def repr_instance(self, x, level):
try: try:
s = `x` s = `x`
# Bugs in x.__repr__() can cause arbitrary # Bugs in x.__repr__() can cause arbitrary
# exceptions -- then make up something # exceptions -- then make up something
except: except:
return '<' + x.__class__.__name__ + ' instance at ' + \ return '<' + x.__class__.__name__ + ' instance at ' + \
hex(id(x))[2:] + '>' hex(id(x))[2:] + '>'
if len(s) > self.maxstring: if len(s) > self.maxstring:
i = max(0, (self.maxstring-3)/2) i = max(0, (self.maxstring-3)/2)
j = max(0, self.maxstring-3-i) j = max(0, self.maxstring-3-i)
s = s[:i] + '...' + s[len(s)-j:] s = s[:i] + '...' + s[len(s)-j:]
return s return s
aRepr = Repr() aRepr = Repr()
repr = aRepr.repr repr = aRepr.repr