mirror of
https://github.com/darlinghq/darling-python.git
synced 2024-11-23 04:09:40 +00:00
Upload Generated Source Of python-136.120.2
This commit is contained in:
parent
bdf4dc67bf
commit
9fe8ec4d50
61
2.7/Python-2.7.16/Demo/README
Normal file
61
2.7/Python-2.7.16/Demo/README
Normal file
@ -0,0 +1,61 @@
|
||||
This directory contains various demonstrations of what you can do with
|
||||
Python. They were all written by me except where explicitly stated
|
||||
otherwise -- in general, demos contributed by others ends up in the
|
||||
../Contrib directory, unless I think they're of utmost general
|
||||
importance (like Matt Conway's Tk demos).
|
||||
|
||||
A fair number of utilities that are useful when while developing
|
||||
Python code can be found in the ../Tools directory -- some of these
|
||||
can also be considered good examples of how to write Python code.
|
||||
|
||||
Finally, in order to save disk space and net bandwidth, not all
|
||||
subdirectories listed here are distributed. They are listed just
|
||||
in case I change my mind about them.
|
||||
|
||||
|
||||
cgi CGI examples (see also ../Tools/faqwiz/.)
|
||||
|
||||
classes Some examples of how to use classes.
|
||||
|
||||
comparisons A set of responses to a really old language-comparison
|
||||
challenge.
|
||||
|
||||
curses A set of curses demos.
|
||||
|
||||
embed An example of embedding Python in another application
|
||||
(see also pysvr).
|
||||
|
||||
imputil Demonstration subclasses of imputil.Importer.
|
||||
|
||||
md5test Test program for the optional md5 module.
|
||||
|
||||
metaclasses The code from the 1.5 metaclasses paper on the web.
|
||||
|
||||
parser Example using the parser module.
|
||||
|
||||
pdist Old, unfinished code messing with CVS, RCS and remote
|
||||
files.
|
||||
|
||||
pysvr An example of embedding Python in a threaded
|
||||
application.
|
||||
|
||||
rpc A set of classes for building clients and servers for
|
||||
Sun RPC.
|
||||
|
||||
scripts Some useful Python scripts that I put in my bin
|
||||
directory. No optional built-in modules needed.
|
||||
|
||||
sockets Examples for the new built-in module 'socket'.
|
||||
|
||||
threads Demos that use the 'thread' module. (Currently these
|
||||
only run on SGIs, but this may change in the future.)
|
||||
|
||||
tix Demos using the Tix widget set addition to Tkinter.
|
||||
|
||||
tkinter Demos using the Tk interface (including Matt Conway's
|
||||
excellent set of demos).
|
||||
|
||||
xml Some XML demos.
|
||||
|
||||
zlib Some demos for the zlib module (see also the standard
|
||||
library module gzip.py).
|
11
2.7/Python-2.7.16/Demo/cgi/README
Normal file
11
2.7/Python-2.7.16/Demo/cgi/README
Normal file
@ -0,0 +1,11 @@
|
||||
CGI Examples
|
||||
------------
|
||||
|
||||
Here are some example CGI programs. For a larger example, see
|
||||
../../Tools/faqwiz/.
|
||||
|
||||
cgi0.sh -- A shell script to test your server is configured for CGI
|
||||
cgi1.py -- A Python script to test your server is configured for CGI
|
||||
cgi2.py -- A Python script showing how to parse a form
|
||||
cgi3.py -- A Python script for driving an arbitrary CGI application
|
||||
wiki.py -- Sample CGI application: a minimal Wiki implementation
|
8
2.7/Python-2.7.16/Demo/cgi/cgi0.sh
Normal file
8
2.7/Python-2.7.16/Demo/cgi/cgi0.sh
Normal file
@ -0,0 +1,8 @@
|
||||
#! /bin/sh
|
||||
|
||||
# If you can't get this to work, your web server isn't set up right
|
||||
|
||||
echo Content-type: text/plain
|
||||
echo
|
||||
echo Hello world
|
||||
echo This is cgi0.sh
|
14
2.7/Python-2.7.16/Demo/cgi/cgi1.py
Normal file
14
2.7/Python-2.7.16/Demo/cgi/cgi1.py
Normal file
@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""CGI test 1 - check server setup."""
|
||||
|
||||
# Until you get this to work, your web server isn't set up right or
|
||||
# your Python isn't set up right.
|
||||
|
||||
# If cgi0.sh works but cgi1.py doesn't, check the #! line and the file
|
||||
# permissions. The docs for the cgi.py module have debugging tips.
|
||||
|
||||
print "Content-type: text/html"
|
||||
print
|
||||
print "<h1>Hello world</h1>"
|
||||
print "<p>This is cgi1.py"
|
22
2.7/Python-2.7.16/Demo/cgi/cgi2.py
Normal file
22
2.7/Python-2.7.16/Demo/cgi/cgi2.py
Normal file
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""CGI test 2 - basic use of cgi module."""
|
||||
|
||||
import cgitb; cgitb.enable()
|
||||
|
||||
import cgi
|
||||
|
||||
def main():
|
||||
form = cgi.FieldStorage()
|
||||
print "Content-type: text/html"
|
||||
print
|
||||
if not form:
|
||||
print "<h1>No Form Keys</h1>"
|
||||
else:
|
||||
print "<h1>Form Keys</h1>"
|
||||
for key in form.keys():
|
||||
value = form[key].value
|
||||
print "<p>", cgi.escape(key), ":", cgi.escape(value)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
10
2.7/Python-2.7.16/Demo/cgi/cgi3.py
Normal file
10
2.7/Python-2.7.16/Demo/cgi/cgi3.py
Normal file
@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""CGI test 3 (persistent data)."""
|
||||
|
||||
import cgitb; cgitb.enable()
|
||||
|
||||
from wiki import main
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
123
2.7/Python-2.7.16/Demo/cgi/wiki.py
Normal file
123
2.7/Python-2.7.16/Demo/cgi/wiki.py
Normal file
@ -0,0 +1,123 @@
|
||||
"""Wiki main program. Imported and run by cgi3.py."""
|
||||
|
||||
import os, re, cgi, sys, tempfile
|
||||
escape = cgi.escape
|
||||
|
||||
def main():
|
||||
form = cgi.FieldStorage()
|
||||
print "Content-type: text/html"
|
||||
print
|
||||
cmd = form.getvalue("cmd", "view")
|
||||
page = form.getvalue("page", "FrontPage")
|
||||
wiki = WikiPage(page)
|
||||
method = getattr(wiki, 'cmd_' + cmd, None) or wiki.cmd_view
|
||||
method(form)
|
||||
|
||||
class WikiPage:
|
||||
|
||||
homedir = tempfile.gettempdir()
|
||||
scripturl = os.path.basename(sys.argv[0])
|
||||
|
||||
def __init__(self, name):
|
||||
if not self.iswikiword(name):
|
||||
raise ValueError, "page name is not a wiki word"
|
||||
self.name = name
|
||||
self.load()
|
||||
|
||||
def cmd_view(self, form):
|
||||
print "<h1>", escape(self.splitwikiword(self.name)), "</h1>"
|
||||
print "<p>"
|
||||
for line in self.data.splitlines():
|
||||
line = line.rstrip()
|
||||
if not line:
|
||||
print "<p>"
|
||||
else:
|
||||
print self.formatline(line)
|
||||
print "<hr>"
|
||||
print "<p>", self.mklink("edit", self.name, "Edit this page") + ";"
|
||||
print self.mklink("view", "FrontPage", "go to front page") + "."
|
||||
|
||||
def formatline(self, line):
|
||||
words = []
|
||||
for word in re.split('(\W+)', line):
|
||||
if self.iswikiword(word):
|
||||
if os.path.isfile(self.mkfile(word)):
|
||||
word = self.mklink("view", word, word)
|
||||
else:
|
||||
word = self.mklink("new", word, word + "*")
|
||||
else:
|
||||
word = escape(word)
|
||||
words.append(word)
|
||||
return "".join(words)
|
||||
|
||||
def cmd_edit(self, form, label="Change"):
|
||||
print "<h1>", label, self.name, "</h1>"
|
||||
print '<form method="POST" action="%s">' % self.scripturl
|
||||
s = '<textarea cols="70" rows="20" name="text">%s</textarea>'
|
||||
print s % self.data
|
||||
print '<input type="hidden" name="cmd" value="create">'
|
||||
print '<input type="hidden" name="page" value="%s">' % self.name
|
||||
print '<br>'
|
||||
print '<input type="submit" value="%s Page">' % label
|
||||
print "</form>"
|
||||
|
||||
def cmd_create(self, form):
|
||||
self.data = form.getvalue("text", "").strip()
|
||||
error = self.store()
|
||||
if error:
|
||||
print "<h1>I'm sorry. That didn't work</h1>"
|
||||
print "<p>An error occurred while attempting to write the file:"
|
||||
print "<p>", escape(error)
|
||||
else:
|
||||
# Use a redirect directive, to avoid "reload page" problems
|
||||
print "<head>"
|
||||
s = '<meta http-equiv="refresh" content="1; URL=%s">'
|
||||
print s % (self.scripturl + "?cmd=view&page=" + self.name)
|
||||
print "<head>"
|
||||
print "<h1>OK</h1>"
|
||||
print "<p>If nothing happens, please click here:",
|
||||
print self.mklink("view", self.name, self.name)
|
||||
|
||||
def cmd_new(self, form):
|
||||
self.cmd_edit(form, label="Create")
|
||||
|
||||
def iswikiword(self, word):
|
||||
return re.match("[A-Z][a-z]+([A-Z][a-z]*)+", word)
|
||||
|
||||
def splitwikiword(self, word):
|
||||
chars = []
|
||||
for c in word:
|
||||
if chars and c.isupper():
|
||||
chars.append(' ')
|
||||
chars.append(c)
|
||||
return "".join(chars)
|
||||
|
||||
def mkfile(self, name=None):
|
||||
if name is None:
|
||||
name = self.name
|
||||
return os.path.join(self.homedir, name + ".txt")
|
||||
|
||||
def mklink(self, cmd, page, text):
|
||||
link = self.scripturl + "?cmd=" + cmd + "&page=" + page
|
||||
return '<a href="%s">%s</a>' % (link, text)
|
||||
|
||||
def load(self):
|
||||
try:
|
||||
f = open(self.mkfile())
|
||||
data = f.read().strip()
|
||||
f.close()
|
||||
except IOError:
|
||||
data = ""
|
||||
self.data = data
|
||||
|
||||
def store(self):
|
||||
data = self.data
|
||||
try:
|
||||
f = open(self.mkfile(), "w")
|
||||
f.write(data)
|
||||
if data and not data.endswith('\n'):
|
||||
f.write('\n')
|
||||
f.close()
|
||||
return ""
|
||||
except IOError, err:
|
||||
return "IOError: %s" % str(err)
|
320
2.7/Python-2.7.16/Demo/classes/Complex.py
Normal file
320
2.7/Python-2.7.16/Demo/classes/Complex.py
Normal file
@ -0,0 +1,320 @@
|
||||
# Complex numbers
|
||||
# ---------------
|
||||
|
||||
# [Now that Python has a complex data type built-in, this is not very
|
||||
# useful, but it's still a nice example class]
|
||||
|
||||
# This module represents complex numbers as instances of the class Complex.
|
||||
# A Complex instance z has two data attribues, z.re (the real part) and z.im
|
||||
# (the imaginary part). In fact, z.re and z.im can have any value -- all
|
||||
# arithmetic operators work regardless of the type of z.re and z.im (as long
|
||||
# as they support numerical operations).
|
||||
#
|
||||
# The following functions exist (Complex is actually a class):
|
||||
# Complex([re [,im]) -> creates a complex number from a real and an imaginary part
|
||||
# IsComplex(z) -> true iff z is a complex number (== has .re and .im attributes)
|
||||
# ToComplex(z) -> a complex number equal to z; z itself if IsComplex(z) is true
|
||||
# if z is a tuple(re, im) it will also be converted
|
||||
# PolarToComplex([r [,phi [,fullcircle]]]) ->
|
||||
# the complex number z for which r == z.radius() and phi == z.angle(fullcircle)
|
||||
# (r and phi default to 0)
|
||||
# exp(z) -> returns the complex exponential of z. Equivalent to pow(math.e,z).
|
||||
#
|
||||
# Complex numbers have the following methods:
|
||||
# z.abs() -> absolute value of z
|
||||
# z.radius() == z.abs()
|
||||
# z.angle([fullcircle]) -> angle from positive X axis; fullcircle gives units
|
||||
# z.phi([fullcircle]) == z.angle(fullcircle)
|
||||
#
|
||||
# These standard functions and unary operators accept complex arguments:
|
||||
# abs(z)
|
||||
# -z
|
||||
# +z
|
||||
# not z
|
||||
# repr(z) == `z`
|
||||
# str(z)
|
||||
# hash(z) -> a combination of hash(z.re) and hash(z.im) such that if z.im is zero
|
||||
# the result equals hash(z.re)
|
||||
# Note that hex(z) and oct(z) are not defined.
|
||||
#
|
||||
# These conversions accept complex arguments only if their imaginary part is zero:
|
||||
# int(z)
|
||||
# long(z)
|
||||
# float(z)
|
||||
#
|
||||
# The following operators accept two complex numbers, or one complex number
|
||||
# and one real number (int, long or float):
|
||||
# z1 + z2
|
||||
# z1 - z2
|
||||
# z1 * z2
|
||||
# z1 / z2
|
||||
# pow(z1, z2)
|
||||
# cmp(z1, z2)
|
||||
# Note that z1 % z2 and divmod(z1, z2) are not defined,
|
||||
# nor are shift and mask operations.
|
||||
#
|
||||
# The standard module math does not support complex numbers.
|
||||
# The cmath modules should be used instead.
|
||||
#
|
||||
# Idea:
|
||||
# add a class Polar(r, phi) and mixed-mode arithmetic which
|
||||
# chooses the most appropriate type for the result:
|
||||
# Complex for +,-,cmp
|
||||
# Polar for *,/,pow
|
||||
|
||||
import math
|
||||
import sys
|
||||
|
||||
twopi = math.pi*2.0
|
||||
halfpi = math.pi/2.0
|
||||
|
||||
def IsComplex(obj):
|
||||
return hasattr(obj, 're') and hasattr(obj, 'im')
|
||||
|
||||
def ToComplex(obj):
|
||||
if IsComplex(obj):
|
||||
return obj
|
||||
elif isinstance(obj, tuple):
|
||||
return Complex(*obj)
|
||||
else:
|
||||
return Complex(obj)
|
||||
|
||||
def PolarToComplex(r = 0, phi = 0, fullcircle = twopi):
|
||||
phi = phi * (twopi / fullcircle)
|
||||
return Complex(math.cos(phi)*r, math.sin(phi)*r)
|
||||
|
||||
def Re(obj):
|
||||
if IsComplex(obj):
|
||||
return obj.re
|
||||
return obj
|
||||
|
||||
def Im(obj):
|
||||
if IsComplex(obj):
|
||||
return obj.im
|
||||
return 0
|
||||
|
||||
class Complex:
|
||||
|
||||
def __init__(self, re=0, im=0):
|
||||
_re = 0
|
||||
_im = 0
|
||||
if IsComplex(re):
|
||||
_re = re.re
|
||||
_im = re.im
|
||||
else:
|
||||
_re = re
|
||||
if IsComplex(im):
|
||||
_re = _re - im.im
|
||||
_im = _im + im.re
|
||||
else:
|
||||
_im = _im + im
|
||||
# this class is immutable, so setting self.re directly is
|
||||
# not possible.
|
||||
self.__dict__['re'] = _re
|
||||
self.__dict__['im'] = _im
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
raise TypeError, 'Complex numbers are immutable'
|
||||
|
||||
def __hash__(self):
|
||||
if not self.im:
|
||||
return hash(self.re)
|
||||
return hash((self.re, self.im))
|
||||
|
||||
def __repr__(self):
|
||||
if not self.im:
|
||||
return 'Complex(%r)' % (self.re,)
|
||||
else:
|
||||
return 'Complex(%r, %r)' % (self.re, self.im)
|
||||
|
||||
def __str__(self):
|
||||
if not self.im:
|
||||
return repr(self.re)
|
||||
else:
|
||||
return 'Complex(%r, %r)' % (self.re, self.im)
|
||||
|
||||
def __neg__(self):
|
||||
return Complex(-self.re, -self.im)
|
||||
|
||||
def __pos__(self):
|
||||
return self
|
||||
|
||||
def __abs__(self):
|
||||
return math.hypot(self.re, self.im)
|
||||
|
||||
def __int__(self):
|
||||
if self.im:
|
||||
raise ValueError, "can't convert Complex with nonzero im to int"
|
||||
return int(self.re)
|
||||
|
||||
def __long__(self):
|
||||
if self.im:
|
||||
raise ValueError, "can't convert Complex with nonzero im to long"
|
||||
return long(self.re)
|
||||
|
||||
def __float__(self):
|
||||
if self.im:
|
||||
raise ValueError, "can't convert Complex with nonzero im to float"
|
||||
return float(self.re)
|
||||
|
||||
def __cmp__(self, other):
|
||||
other = ToComplex(other)
|
||||
return cmp((self.re, self.im), (other.re, other.im))
|
||||
|
||||
def __rcmp__(self, other):
|
||||
other = ToComplex(other)
|
||||
return cmp(other, self)
|
||||
|
||||
def __nonzero__(self):
|
||||
return not (self.re == self.im == 0)
|
||||
|
||||
abs = radius = __abs__
|
||||
|
||||
def angle(self, fullcircle = twopi):
|
||||
return (fullcircle/twopi) * ((halfpi - math.atan2(self.re, self.im)) % twopi)
|
||||
|
||||
phi = angle
|
||||
|
||||
def __add__(self, other):
|
||||
other = ToComplex(other)
|
||||
return Complex(self.re + other.re, self.im + other.im)
|
||||
|
||||
__radd__ = __add__
|
||||
|
||||
def __sub__(self, other):
|
||||
other = ToComplex(other)
|
||||
return Complex(self.re - other.re, self.im - other.im)
|
||||
|
||||
def __rsub__(self, other):
|
||||
other = ToComplex(other)
|
||||
return other - self
|
||||
|
||||
def __mul__(self, other):
|
||||
other = ToComplex(other)
|
||||
return Complex(self.re*other.re - self.im*other.im,
|
||||
self.re*other.im + self.im*other.re)
|
||||
|
||||
__rmul__ = __mul__
|
||||
|
||||
def __div__(self, other):
|
||||
other = ToComplex(other)
|
||||
d = float(other.re*other.re + other.im*other.im)
|
||||
if not d: raise ZeroDivisionError, 'Complex division'
|
||||
return Complex((self.re*other.re + self.im*other.im) / d,
|
||||
(self.im*other.re - self.re*other.im) / d)
|
||||
|
||||
def __rdiv__(self, other):
|
||||
other = ToComplex(other)
|
||||
return other / self
|
||||
|
||||
def __pow__(self, n, z=None):
|
||||
if z is not None:
|
||||
raise TypeError, 'Complex does not support ternary pow()'
|
||||
if IsComplex(n):
|
||||
if n.im:
|
||||
if self.im: raise TypeError, 'Complex to the Complex power'
|
||||
else: return exp(math.log(self.re)*n)
|
||||
n = n.re
|
||||
r = pow(self.abs(), n)
|
||||
phi = n*self.angle()
|
||||
return Complex(math.cos(phi)*r, math.sin(phi)*r)
|
||||
|
||||
def __rpow__(self, base):
|
||||
base = ToComplex(base)
|
||||
return pow(base, self)
|
||||
|
||||
def exp(z):
|
||||
r = math.exp(z.re)
|
||||
return Complex(math.cos(z.im)*r,math.sin(z.im)*r)
|
||||
|
||||
|
||||
def checkop(expr, a, b, value, fuzz = 1e-6):
|
||||
print ' ', a, 'and', b,
|
||||
try:
|
||||
result = eval(expr)
|
||||
except:
|
||||
result = sys.exc_type
|
||||
print '->', result
|
||||
if isinstance(result, str) or isinstance(value, str):
|
||||
ok = (result == value)
|
||||
else:
|
||||
ok = abs(result - value) <= fuzz
|
||||
if not ok:
|
||||
print '!!\t!!\t!! should be', value, 'diff', abs(result - value)
|
||||
|
||||
def test():
|
||||
print 'test constructors'
|
||||
constructor_test = (
|
||||
# "expect" is an array [re,im] "got" the Complex.
|
||||
( (0,0), Complex() ),
|
||||
( (0,0), Complex() ),
|
||||
( (1,0), Complex(1) ),
|
||||
( (0,1), Complex(0,1) ),
|
||||
( (1,2), Complex(Complex(1,2)) ),
|
||||
( (1,3), Complex(Complex(1,2),1) ),
|
||||
( (0,0), Complex(0,Complex(0,0)) ),
|
||||
( (3,4), Complex(3,Complex(4)) ),
|
||||
( (-1,3), Complex(1,Complex(3,2)) ),
|
||||
( (-7,6), Complex(Complex(1,2),Complex(4,8)) ) )
|
||||
cnt = [0,0]
|
||||
for t in constructor_test:
|
||||
cnt[0] += 1
|
||||
if ((t[0][0]!=t[1].re)or(t[0][1]!=t[1].im)):
|
||||
print " expected", t[0], "got", t[1]
|
||||
cnt[1] += 1
|
||||
print " ", cnt[1], "of", cnt[0], "tests failed"
|
||||
# test operators
|
||||
testsuite = {
|
||||
'a+b': [
|
||||
(1, 10, 11),
|
||||
(1, Complex(0,10), Complex(1,10)),
|
||||
(Complex(0,10), 1, Complex(1,10)),
|
||||
(Complex(0,10), Complex(1), Complex(1,10)),
|
||||
(Complex(1), Complex(0,10), Complex(1,10)),
|
||||
],
|
||||
'a-b': [
|
||||
(1, 10, -9),
|
||||
(1, Complex(0,10), Complex(1,-10)),
|
||||
(Complex(0,10), 1, Complex(-1,10)),
|
||||
(Complex(0,10), Complex(1), Complex(-1,10)),
|
||||
(Complex(1), Complex(0,10), Complex(1,-10)),
|
||||
],
|
||||
'a*b': [
|
||||
(1, 10, 10),
|
||||
(1, Complex(0,10), Complex(0, 10)),
|
||||
(Complex(0,10), 1, Complex(0,10)),
|
||||
(Complex(0,10), Complex(1), Complex(0,10)),
|
||||
(Complex(1), Complex(0,10), Complex(0,10)),
|
||||
],
|
||||
'a/b': [
|
||||
(1., 10, 0.1),
|
||||
(1, Complex(0,10), Complex(0, -0.1)),
|
||||
(Complex(0, 10), 1, Complex(0, 10)),
|
||||
(Complex(0, 10), Complex(1), Complex(0, 10)),
|
||||
(Complex(1), Complex(0,10), Complex(0, -0.1)),
|
||||
],
|
||||
'pow(a,b)': [
|
||||
(1, 10, 1),
|
||||
(1, Complex(0,10), 1),
|
||||
(Complex(0,10), 1, Complex(0,10)),
|
||||
(Complex(0,10), Complex(1), Complex(0,10)),
|
||||
(Complex(1), Complex(0,10), 1),
|
||||
(2, Complex(4,0), 16),
|
||||
],
|
||||
'cmp(a,b)': [
|
||||
(1, 10, -1),
|
||||
(1, Complex(0,10), 1),
|
||||
(Complex(0,10), 1, -1),
|
||||
(Complex(0,10), Complex(1), -1),
|
||||
(Complex(1), Complex(0,10), 1),
|
||||
],
|
||||
}
|
||||
for expr in sorted(testsuite):
|
||||
print expr + ':'
|
||||
t = (expr,)
|
||||
for item in testsuite[expr]:
|
||||
checkop(*(t+item))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
227
2.7/Python-2.7.16/Demo/classes/Dates.py
Normal file
227
2.7/Python-2.7.16/Demo/classes/Dates.py
Normal file
@ -0,0 +1,227 @@
|
||||
# Class Date supplies date objects that support date arithmetic.
|
||||
#
|
||||
# Date(month,day,year) returns a Date object. An instance prints as,
|
||||
# e.g., 'Mon 16 Aug 1993'.
|
||||
#
|
||||
# Addition, subtraction, comparison operators, min, max, and sorting
|
||||
# all work as expected for date objects: int+date or date+int returns
|
||||
# the date `int' days from `date'; date+date raises an exception;
|
||||
# date-int returns the date `int' days before `date'; date2-date1 returns
|
||||
# an integer, the number of days from date1 to date2; int-date raises an
|
||||
# exception; date1 < date2 is true iff date1 occurs before date2 (&
|
||||
# similarly for other comparisons); min(date1,date2) is the earlier of
|
||||
# the two dates and max(date1,date2) the later; and date objects can be
|
||||
# used as dictionary keys.
|
||||
#
|
||||
# Date objects support one visible method, date.weekday(). This returns
|
||||
# the day of the week the date falls on, as a string.
|
||||
#
|
||||
# Date objects also have 4 read-only data attributes:
|
||||
# .month in 1..12
|
||||
# .day in 1..31
|
||||
# .year int or long int
|
||||
# .ord the ordinal of the date relative to an arbitrary staring point
|
||||
#
|
||||
# The Dates module also supplies function today(), which returns the
|
||||
# current date as a date object.
|
||||
#
|
||||
# Those entranced by calendar trivia will be disappointed, as no attempt
|
||||
# has been made to accommodate the Julian (etc) system. On the other
|
||||
# hand, at least this package knows that 2000 is a leap year but 2100
|
||||
# isn't, and works fine for years with a hundred decimal digits <wink>.
|
||||
|
||||
# Tim Peters tim@ksr.com
|
||||
# not speaking for Kendall Square Research Corp
|
||||
|
||||
# Adapted to Python 1.1 (where some hacks to overcome coercion are unnecessary)
|
||||
# by Guido van Rossum
|
||||
|
||||
# Note that as of Python 2.3, a datetime module is included in the stardard
|
||||
# library.
|
||||
|
||||
# vi:set tabsize=8:
|
||||
|
||||
_MONTH_NAMES = [ 'January', 'February', 'March', 'April', 'May',
|
||||
'June', 'July', 'August', 'September', 'October',
|
||||
'November', 'December' ]
|
||||
|
||||
_DAY_NAMES = [ 'Friday', 'Saturday', 'Sunday', 'Monday',
|
||||
'Tuesday', 'Wednesday', 'Thursday' ]
|
||||
|
||||
_DAYS_IN_MONTH = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]
|
||||
|
||||
_DAYS_BEFORE_MONTH = []
|
||||
dbm = 0
|
||||
for dim in _DAYS_IN_MONTH:
|
||||
_DAYS_BEFORE_MONTH.append(dbm)
|
||||
dbm = dbm + dim
|
||||
del dbm, dim
|
||||
|
||||
_INT_TYPES = type(1), type(1L)
|
||||
|
||||
def _is_leap(year): # 1 if leap year, else 0
|
||||
if year % 4 != 0: return 0
|
||||
if year % 400 == 0: return 1
|
||||
return year % 100 != 0
|
||||
|
||||
def _days_in_year(year): # number of days in year
|
||||
return 365 + _is_leap(year)
|
||||
|
||||
def _days_before_year(year): # number of days before year
|
||||
return year*365L + (year+3)//4 - (year+99)//100 + (year+399)//400
|
||||
|
||||
def _days_in_month(month, year): # number of days in month of year
|
||||
if month == 2 and _is_leap(year): return 29
|
||||
return _DAYS_IN_MONTH[month-1]
|
||||
|
||||
def _days_before_month(month, year): # number of days in year before month
|
||||
return _DAYS_BEFORE_MONTH[month-1] + (month > 2 and _is_leap(year))
|
||||
|
||||
def _date2num(date): # compute ordinal of date.month,day,year
|
||||
return _days_before_year(date.year) + \
|
||||
_days_before_month(date.month, date.year) + \
|
||||
date.day
|
||||
|
||||
_DI400Y = _days_before_year(400) # number of days in 400 years
|
||||
|
||||
def _num2date(n): # return date with ordinal n
|
||||
if type(n) not in _INT_TYPES:
|
||||
raise TypeError, 'argument must be integer: %r' % type(n)
|
||||
|
||||
ans = Date(1,1,1) # arguments irrelevant; just getting a Date obj
|
||||
del ans.ord, ans.month, ans.day, ans.year # un-initialize it
|
||||
ans.ord = n
|
||||
|
||||
n400 = (n-1)//_DI400Y # # of 400-year blocks preceding
|
||||
year, n = 400 * n400, n - _DI400Y * n400
|
||||
more = n // 365
|
||||
dby = _days_before_year(more)
|
||||
if dby >= n:
|
||||
more = more - 1
|
||||
dby = dby - _days_in_year(more)
|
||||
year, n = year + more, int(n - dby)
|
||||
|
||||
try: year = int(year) # chop to int, if it fits
|
||||
except (ValueError, OverflowError): pass
|
||||
|
||||
month = min(n//29 + 1, 12)
|
||||
dbm = _days_before_month(month, year)
|
||||
if dbm >= n:
|
||||
month = month - 1
|
||||
dbm = dbm - _days_in_month(month, year)
|
||||
|
||||
ans.month, ans.day, ans.year = month, n-dbm, year
|
||||
return ans
|
||||
|
||||
def _num2day(n): # return weekday name of day with ordinal n
|
||||
return _DAY_NAMES[ int(n % 7) ]
|
||||
|
||||
|
||||
class Date:
|
||||
def __init__(self, month, day, year):
|
||||
if not 1 <= month <= 12:
|
||||
raise ValueError, 'month must be in 1..12: %r' % (month,)
|
||||
dim = _days_in_month(month, year)
|
||||
if not 1 <= day <= dim:
|
||||
raise ValueError, 'day must be in 1..%r: %r' % (dim, day)
|
||||
self.month, self.day, self.year = month, day, year
|
||||
self.ord = _date2num(self)
|
||||
|
||||
# don't allow setting existing attributes
|
||||
def __setattr__(self, name, value):
|
||||
if self.__dict__.has_key(name):
|
||||
raise AttributeError, 'read-only attribute ' + name
|
||||
self.__dict__[name] = value
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.ord, other.ord)
|
||||
|
||||
# define a hash function so dates can be used as dictionary keys
|
||||
def __hash__(self):
|
||||
return hash(self.ord)
|
||||
|
||||
# print as, e.g., Mon 16 Aug 1993
|
||||
def __repr__(self):
|
||||
return '%.3s %2d %.3s %r' % (
|
||||
self.weekday(),
|
||||
self.day,
|
||||
_MONTH_NAMES[self.month-1],
|
||||
self.year)
|
||||
|
||||
# Python 1.1 coerces neither int+date nor date+int
|
||||
def __add__(self, n):
|
||||
if type(n) not in _INT_TYPES:
|
||||
raise TypeError, 'can\'t add %r to date' % type(n)
|
||||
return _num2date(self.ord + n)
|
||||
__radd__ = __add__ # handle int+date
|
||||
|
||||
# Python 1.1 coerces neither date-int nor date-date
|
||||
def __sub__(self, other):
|
||||
if type(other) in _INT_TYPES: # date-int
|
||||
return _num2date(self.ord - other)
|
||||
else:
|
||||
return self.ord - other.ord # date-date
|
||||
|
||||
# complain about int-date
|
||||
def __rsub__(self, other):
|
||||
raise TypeError, 'Can\'t subtract date from integer'
|
||||
|
||||
def weekday(self):
|
||||
return _num2day(self.ord)
|
||||
|
||||
def today():
|
||||
import time
|
||||
local = time.localtime(time.time())
|
||||
return Date(local[1], local[2], local[0])
|
||||
|
||||
class DateTestError(Exception):
|
||||
pass
|
||||
|
||||
def test(firstyear, lastyear):
|
||||
a = Date(9,30,1913)
|
||||
b = Date(9,30,1914)
|
||||
if repr(a) != 'Tue 30 Sep 1913':
|
||||
raise DateTestError, '__repr__ failure'
|
||||
if (not a < b) or a == b or a > b or b != b:
|
||||
raise DateTestError, '__cmp__ failure'
|
||||
if a+365 != b or 365+a != b:
|
||||
raise DateTestError, '__add__ failure'
|
||||
if b-a != 365 or b-365 != a:
|
||||
raise DateTestError, '__sub__ failure'
|
||||
try:
|
||||
x = 1 - a
|
||||
raise DateTestError, 'int-date should have failed'
|
||||
except TypeError:
|
||||
pass
|
||||
try:
|
||||
x = a + b
|
||||
raise DateTestError, 'date+date should have failed'
|
||||
except TypeError:
|
||||
pass
|
||||
if a.weekday() != 'Tuesday':
|
||||
raise DateTestError, 'weekday() failure'
|
||||
if max(a,b) is not b or min(a,b) is not a:
|
||||
raise DateTestError, 'min/max failure'
|
||||
d = {a-1:b, b:a+1}
|
||||
if d[b-366] != b or d[a+(b-a)] != Date(10,1,1913):
|
||||
raise DateTestError, 'dictionary failure'
|
||||
|
||||
# verify date<->number conversions for first and last days for
|
||||
# all years in firstyear .. lastyear
|
||||
|
||||
lord = _days_before_year(firstyear)
|
||||
y = firstyear
|
||||
while y <= lastyear:
|
||||
ford = lord + 1
|
||||
lord = ford + _days_in_year(y) - 1
|
||||
fd, ld = Date(1,1,y), Date(12,31,y)
|
||||
if (fd.ord,ld.ord) != (ford,lord):
|
||||
raise DateTestError, ('date->num failed', y)
|
||||
fd, ld = _num2date(ford), _num2date(lord)
|
||||
if (1,1,y,12,31,y) != \
|
||||
(fd.month,fd.day,fd.year,ld.month,ld.day,ld.year):
|
||||
raise DateTestError, ('num->date failed', y)
|
||||
y = y + 1
|
||||
|
||||
if __name__ == '__main__':
|
||||
test(1850, 2150)
|
66
2.7/Python-2.7.16/Demo/classes/Dbm.py
Normal file
66
2.7/Python-2.7.16/Demo/classes/Dbm.py
Normal file
@ -0,0 +1,66 @@
|
||||
# A wrapper around the (optional) built-in class dbm, supporting keys
|
||||
# and values of almost any type instead of just string.
|
||||
# (Actually, this works only for keys and values that can be read back
|
||||
# correctly after being converted to a string.)
|
||||
|
||||
|
||||
class Dbm:
|
||||
|
||||
def __init__(self, filename, mode, perm):
|
||||
import dbm
|
||||
self.db = dbm.open(filename, mode, perm)
|
||||
|
||||
def __repr__(self):
|
||||
s = ''
|
||||
for key in self.keys():
|
||||
t = repr(key) + ': ' + repr(self[key])
|
||||
if s: t = ', ' + t
|
||||
s = s + t
|
||||
return '{' + s + '}'
|
||||
|
||||
def __len__(self):
|
||||
return len(self.db)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return eval(self.db[repr(key)])
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self.db[repr(key)] = repr(value)
|
||||
|
||||
def __delitem__(self, key):
|
||||
del self.db[repr(key)]
|
||||
|
||||
def keys(self):
|
||||
res = []
|
||||
for key in self.db.keys():
|
||||
res.append(eval(key))
|
||||
return res
|
||||
|
||||
def has_key(self, key):
|
||||
return self.db.has_key(repr(key))
|
||||
|
||||
|
||||
def test():
|
||||
d = Dbm('@dbm', 'rw', 0600)
|
||||
print d
|
||||
while 1:
|
||||
try:
|
||||
key = input('key: ')
|
||||
if d.has_key(key):
|
||||
value = d[key]
|
||||
print 'currently:', value
|
||||
value = input('value: ')
|
||||
if value is None:
|
||||
del d[key]
|
||||
else:
|
||||
d[key] = value
|
||||
except KeyboardInterrupt:
|
||||
print ''
|
||||
print d
|
||||
except EOFError:
|
||||
print '[eof]'
|
||||
break
|
||||
print d
|
||||
|
||||
|
||||
test()
|
12
2.7/Python-2.7.16/Demo/classes/README
Normal file
12
2.7/Python-2.7.16/Demo/classes/README
Normal file
@ -0,0 +1,12 @@
|
||||
Examples of classes that implement special operators (see reference manual):
|
||||
|
||||
Complex.py Complex numbers
|
||||
Dates.py Date manipulation package by Tim Peters
|
||||
Dbm.py Wrapper around built-in dbm, supporting arbitrary values
|
||||
Range.py Example of a generator: re-implement built-in range()
|
||||
Rev.py Yield the reverse of a sequence
|
||||
Vec.py A simple vector class
|
||||
bitvec.py A bit-vector class by Jan-Hein B\"uhrman
|
||||
|
||||
(For straightforward examples of basic class features, such as use of
|
||||
methods and inheritance, see the library code.)
|
93
2.7/Python-2.7.16/Demo/classes/Range.py
Normal file
93
2.7/Python-2.7.16/Demo/classes/Range.py
Normal file
@ -0,0 +1,93 @@
|
||||
"""Example of a generator: re-implement the built-in range function
|
||||
without actually constructing the list of values.
|
||||
|
||||
OldStyleRange is coded in the way required to work in a 'for' loop before
|
||||
iterators were introduced into the language; using __getitem__ and __len__ .
|
||||
|
||||
"""
|
||||
def handleargs(arglist):
|
||||
"""Take list of arguments and extract/create proper start, stop, and step
|
||||
values and return in a tuple"""
|
||||
try:
|
||||
if len(arglist) == 1:
|
||||
return 0, int(arglist[0]), 1
|
||||
elif len(arglist) == 2:
|
||||
return int(arglist[0]), int(arglist[1]), 1
|
||||
elif len(arglist) == 3:
|
||||
if arglist[2] == 0:
|
||||
raise ValueError("step argument must not be zero")
|
||||
return tuple(int(x) for x in arglist)
|
||||
else:
|
||||
raise TypeError("range() accepts 1-3 arguments, given", len(arglist))
|
||||
except TypeError:
|
||||
raise TypeError("range() arguments must be numbers or strings "
|
||||
"representing numbers")
|
||||
|
||||
def genrange(*a):
|
||||
"""Function to implement 'range' as a generator"""
|
||||
start, stop, step = handleargs(a)
|
||||
value = start
|
||||
while value < stop:
|
||||
yield value
|
||||
value += step
|
||||
|
||||
class oldrange:
|
||||
"""Class implementing a range object.
|
||||
To the user the instances feel like immutable sequences
|
||||
(and you can't concatenate or slice them)
|
||||
|
||||
Done using the old way (pre-iterators; __len__ and __getitem__) to have an
|
||||
object be used by a 'for' loop.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, *a):
|
||||
""" Initialize start, stop, and step values along with calculating the
|
||||
nubmer of values (what __len__ will return) in the range"""
|
||||
self.start, self.stop, self.step = handleargs(a)
|
||||
self.len = max(0, (self.stop - self.start) // self.step)
|
||||
|
||||
def __repr__(self):
|
||||
"""implement repr(x) which is also used by print"""
|
||||
return 'range(%r, %r, %r)' % (self.start, self.stop, self.step)
|
||||
|
||||
def __len__(self):
|
||||
"""implement len(x)"""
|
||||
return self.len
|
||||
|
||||
def __getitem__(self, i):
|
||||
"""implement x[i]"""
|
||||
if 0 <= i <= self.len:
|
||||
return self.start + self.step * i
|
||||
else:
|
||||
raise IndexError, 'range[i] index out of range'
|
||||
|
||||
|
||||
def test():
|
||||
import time, __builtin__
|
||||
#Just a quick sanity check
|
||||
correct_result = __builtin__.range(5, 100, 3)
|
||||
oldrange_result = list(oldrange(5, 100, 3))
|
||||
genrange_result = list(genrange(5, 100, 3))
|
||||
if genrange_result != correct_result or oldrange_result != correct_result:
|
||||
raise Exception("error in implementation:\ncorrect = %s"
|
||||
"\nold-style = %s\ngenerator = %s" %
|
||||
(correct_result, oldrange_result, genrange_result))
|
||||
print "Timings for range(1000):"
|
||||
t1 = time.time()
|
||||
for i in oldrange(1000):
|
||||
pass
|
||||
t2 = time.time()
|
||||
for i in genrange(1000):
|
||||
pass
|
||||
t3 = time.time()
|
||||
for i in __builtin__.range(1000):
|
||||
pass
|
||||
t4 = time.time()
|
||||
print t2-t1, 'sec (old-style class)'
|
||||
print t3-t2, 'sec (generator)'
|
||||
print t4-t3, 'sec (built-in)'
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
95
2.7/Python-2.7.16/Demo/classes/Rev.py
Normal file
95
2.7/Python-2.7.16/Demo/classes/Rev.py
Normal file
@ -0,0 +1,95 @@
|
||||
'''
|
||||
A class which presents the reverse of a sequence without duplicating it.
|
||||
From: "Steven D. Majewski" <sdm7g@elvis.med.virginia.edu>
|
||||
|
||||
It works on mutable or inmutable sequences.
|
||||
|
||||
>>> chars = list(Rev('Hello World!'))
|
||||
>>> print ''.join(chars)
|
||||
!dlroW olleH
|
||||
|
||||
The .forw is so you can use anonymous sequences in __init__, and still
|
||||
keep a reference the forward sequence. )
|
||||
If you give it a non-anonymous mutable sequence, the reverse sequence
|
||||
will track the updated values. ( but not reassignment! - another
|
||||
good reason to use anonymous values in creating the sequence to avoid
|
||||
confusion. Maybe it should be change to copy input sequence to break
|
||||
the connection completely ? )
|
||||
|
||||
>>> nnn = range(3)
|
||||
>>> rnn = Rev(nnn)
|
||||
>>> for n in rnn: print n
|
||||
...
|
||||
2
|
||||
1
|
||||
0
|
||||
>>> for n in range(4, 6): nnn.append(n) # update nnn
|
||||
...
|
||||
>>> for n in rnn: print n # prints reversed updated values
|
||||
...
|
||||
5
|
||||
4
|
||||
2
|
||||
1
|
||||
0
|
||||
>>> nnn = nnn[1:-1]
|
||||
>>> nnn
|
||||
[1, 2, 4]
|
||||
>>> for n in rnn: print n # prints reversed values of old nnn
|
||||
...
|
||||
5
|
||||
4
|
||||
2
|
||||
1
|
||||
0
|
||||
|
||||
#
|
||||
>>> WH = Rev('Hello World!')
|
||||
>>> print WH.forw, WH.back
|
||||
Hello World! !dlroW olleH
|
||||
>>> nnn = Rev(range(1, 10))
|
||||
>>> print nnn.forw
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
>>> print nnn.back
|
||||
[9, 8, 7, 6, 5, 4, 3, 2, 1]
|
||||
|
||||
>>> rrr = Rev(nnn)
|
||||
>>> rrr
|
||||
<1, 2, 3, 4, 5, 6, 7, 8, 9>
|
||||
|
||||
'''
|
||||
|
||||
class Rev:
|
||||
def __init__(self, seq):
|
||||
self.forw = seq
|
||||
self.back = self
|
||||
|
||||
def __len__(self):
|
||||
return len(self.forw)
|
||||
|
||||
def __getitem__(self, j):
|
||||
return self.forw[-(j + 1)]
|
||||
|
||||
def __repr__(self):
|
||||
seq = self.forw
|
||||
if isinstance(seq, list):
|
||||
wrap = '[]'
|
||||
sep = ', '
|
||||
elif isinstance(seq, tuple):
|
||||
wrap = '()'
|
||||
sep = ', '
|
||||
elif isinstance(seq, str):
|
||||
wrap = ''
|
||||
sep = ''
|
||||
else:
|
||||
wrap = '<>'
|
||||
sep = ', '
|
||||
outstrs = [str(item) for item in self.back]
|
||||
return wrap[:1] + sep.join(outstrs) + wrap[-1:]
|
||||
|
||||
def _test():
|
||||
import doctest, Rev
|
||||
return doctest.testmod(Rev)
|
||||
|
||||
if __name__ == "__main__":
|
||||
_test()
|
68
2.7/Python-2.7.16/Demo/classes/Vec.py
Normal file
68
2.7/Python-2.7.16/Demo/classes/Vec.py
Normal file
@ -0,0 +1,68 @@
|
||||
class Vec:
|
||||
""" A simple vector class
|
||||
|
||||
Instances of the Vec class can be constructed from numbers
|
||||
|
||||
>>> a = Vec(1, 2, 3)
|
||||
>>> b = Vec(3, 2, 1)
|
||||
|
||||
added
|
||||
>>> a + b
|
||||
Vec(4, 4, 4)
|
||||
|
||||
subtracted
|
||||
>>> a - b
|
||||
Vec(-2, 0, 2)
|
||||
|
||||
and multiplied by a scalar on the left
|
||||
>>> 3.0 * a
|
||||
Vec(3.0, 6.0, 9.0)
|
||||
|
||||
or on the right
|
||||
>>> a * 3.0
|
||||
Vec(3.0, 6.0, 9.0)
|
||||
"""
|
||||
def __init__(self, *v):
|
||||
self.v = list(v)
|
||||
|
||||
@classmethod
|
||||
def fromlist(cls, v):
|
||||
if not isinstance(v, list):
|
||||
raise TypeError
|
||||
inst = cls()
|
||||
inst.v = v
|
||||
return inst
|
||||
|
||||
def __repr__(self):
|
||||
args = ', '.join(repr(x) for x in self.v)
|
||||
return 'Vec({0})'.format(args)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.v)
|
||||
|
||||
def __getitem__(self, i):
|
||||
return self.v[i]
|
||||
|
||||
def __add__(self, other):
|
||||
# Element-wise addition
|
||||
v = [x + y for x, y in zip(self.v, other.v)]
|
||||
return Vec.fromlist(v)
|
||||
|
||||
def __sub__(self, other):
|
||||
# Element-wise subtraction
|
||||
v = [x - y for x, y in zip(self.v, other.v)]
|
||||
return Vec.fromlist(v)
|
||||
|
||||
def __mul__(self, scalar):
|
||||
# Multiply by scalar
|
||||
v = [x * scalar for x in self.v]
|
||||
return Vec.fromlist(v)
|
||||
|
||||
__rmul__ = __mul__
|
||||
|
||||
|
||||
def test():
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
||||
test()
|
333
2.7/Python-2.7.16/Demo/classes/bitvec.py
Normal file
333
2.7/Python-2.7.16/Demo/classes/bitvec.py
Normal file
@ -0,0 +1,333 @@
|
||||
#
|
||||
# this is a rather strict implementation of a bit vector class
|
||||
# it is accessed the same way as an array of python-ints, except
|
||||
# the value must be 0 or 1
|
||||
#
|
||||
|
||||
import sys; rprt = sys.stderr.write #for debugging
|
||||
|
||||
class error(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def _check_value(value):
|
||||
if type(value) != type(0) or not 0 <= value < 2:
|
||||
raise error, 'bitvec() items must have int value 0 or 1'
|
||||
|
||||
|
||||
import math
|
||||
|
||||
def _compute_len(param):
|
||||
mant, l = math.frexp(float(param))
|
||||
bitmask = 1L << l
|
||||
if bitmask <= param:
|
||||
raise RuntimeError('(param, l) = %r' % ((param, l),))
|
||||
while l:
|
||||
bitmask = bitmask >> 1
|
||||
if param & bitmask:
|
||||
break
|
||||
l = l - 1
|
||||
return l
|
||||
|
||||
|
||||
def _check_key(len, key):
|
||||
if type(key) != type(0):
|
||||
raise TypeError, 'sequence subscript not int'
|
||||
if key < 0:
|
||||
key = key + len
|
||||
if not 0 <= key < len:
|
||||
raise IndexError, 'list index out of range'
|
||||
return key
|
||||
|
||||
def _check_slice(len, i, j):
|
||||
#the type is ok, Python already checked that
|
||||
i, j = max(i, 0), min(len, j)
|
||||
if i > j:
|
||||
i = j
|
||||
return i, j
|
||||
|
||||
|
||||
class BitVec:
|
||||
|
||||
def __init__(self, *params):
|
||||
self._data = 0L
|
||||
self._len = 0
|
||||
if not len(params):
|
||||
pass
|
||||
elif len(params) == 1:
|
||||
param, = params
|
||||
if type(param) == type([]):
|
||||
value = 0L
|
||||
bit_mask = 1L
|
||||
for item in param:
|
||||
# strict check
|
||||
#_check_value(item)
|
||||
if item:
|
||||
value = value | bit_mask
|
||||
bit_mask = bit_mask << 1
|
||||
self._data = value
|
||||
self._len = len(param)
|
||||
elif type(param) == type(0L):
|
||||
if param < 0:
|
||||
raise error, 'bitvec() can\'t handle negative longs'
|
||||
self._data = param
|
||||
self._len = _compute_len(param)
|
||||
else:
|
||||
raise error, 'bitvec() requires array or long parameter'
|
||||
elif len(params) == 2:
|
||||
param, length = params
|
||||
if type(param) == type(0L):
|
||||
if param < 0:
|
||||
raise error, \
|
||||
'can\'t handle negative longs'
|
||||
self._data = param
|
||||
if type(length) != type(0):
|
||||
raise error, 'bitvec()\'s 2nd parameter must be int'
|
||||
computed_length = _compute_len(param)
|
||||
if computed_length > length:
|
||||
print 'warning: bitvec() value is longer than the length indicates, truncating value'
|
||||
self._data = self._data & \
|
||||
((1L << length) - 1)
|
||||
self._len = length
|
||||
else:
|
||||
raise error, 'bitvec() requires array or long parameter'
|
||||
else:
|
||||
raise error, 'bitvec() requires 0 -- 2 parameter(s)'
|
||||
|
||||
|
||||
def append(self, item):
|
||||
#_check_value(item)
|
||||
#self[self._len:self._len] = [item]
|
||||
self[self._len:self._len] = \
|
||||
BitVec(long(not not item), 1)
|
||||
|
||||
|
||||
def count(self, value):
|
||||
#_check_value(value)
|
||||
if value:
|
||||
data = self._data
|
||||
else:
|
||||
data = (~self)._data
|
||||
count = 0
|
||||
while data:
|
||||
data, count = data >> 1, count + (data & 1 != 0)
|
||||
return count
|
||||
|
||||
|
||||
def index(self, value):
|
||||
#_check_value(value):
|
||||
if value:
|
||||
data = self._data
|
||||
else:
|
||||
data = (~self)._data
|
||||
index = 0
|
||||
if not data:
|
||||
raise ValueError, 'list.index(x): x not in list'
|
||||
while not (data & 1):
|
||||
data, index = data >> 1, index + 1
|
||||
return index
|
||||
|
||||
|
||||
def insert(self, index, item):
|
||||
#_check_value(item)
|
||||
#self[index:index] = [item]
|
||||
self[index:index] = BitVec(long(not not item), 1)
|
||||
|
||||
|
||||
def remove(self, value):
|
||||
del self[self.index(value)]
|
||||
|
||||
|
||||
def reverse(self):
|
||||
#ouch, this one is expensive!
|
||||
#for i in self._len>>1: self[i], self[l-i] = self[l-i], self[i]
|
||||
data, result = self._data, 0L
|
||||
for i in range(self._len):
|
||||
if not data:
|
||||
result = result << (self._len - i)
|
||||
break
|
||||
result, data = (result << 1) | (data & 1), data >> 1
|
||||
self._data = result
|
||||
|
||||
|
||||
def sort(self):
|
||||
c = self.count(1)
|
||||
self._data = ((1L << c) - 1) << (self._len - c)
|
||||
|
||||
|
||||
def copy(self):
|
||||
return BitVec(self._data, self._len)
|
||||
|
||||
|
||||
def seq(self):
|
||||
result = []
|
||||
for i in self:
|
||||
result.append(i)
|
||||
return result
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
##rprt('<bitvec class instance object>.' + '__repr__()\n')
|
||||
return 'bitvec(%r, %r)' % (self._data, self._len)
|
||||
|
||||
def __cmp__(self, other, *rest):
|
||||
#rprt('%r.__cmp__%r\n' % (self, (other,) + rest))
|
||||
if type(other) != type(self):
|
||||
other = apply(bitvec, (other, ) + rest)
|
||||
#expensive solution... recursive binary, with slicing
|
||||
length = self._len
|
||||
if length == 0 or other._len == 0:
|
||||
return cmp(length, other._len)
|
||||
if length != other._len:
|
||||
min_length = min(length, other._len)
|
||||
return cmp(self[:min_length], other[:min_length]) or \
|
||||
cmp(self[min_length:], other[min_length:])
|
||||
#the lengths are the same now...
|
||||
if self._data == other._data:
|
||||
return 0
|
||||
if length == 1:
|
||||
return cmp(self[0], other[0])
|
||||
else:
|
||||
length = length >> 1
|
||||
return cmp(self[:length], other[:length]) or \
|
||||
cmp(self[length:], other[length:])
|
||||
|
||||
|
||||
def __len__(self):
|
||||
#rprt('%r.__len__()\n' % (self,))
|
||||
return self._len
|
||||
|
||||
def __getitem__(self, key):
|
||||
#rprt('%r.__getitem__(%r)\n' % (self, key))
|
||||
key = _check_key(self._len, key)
|
||||
return self._data & (1L << key) != 0
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
#rprt('%r.__setitem__(%r, %r)\n' % (self, key, value))
|
||||
key = _check_key(self._len, key)
|
||||
#_check_value(value)
|
||||
if value:
|
||||
self._data = self._data | (1L << key)
|
||||
else:
|
||||
self._data = self._data & ~(1L << key)
|
||||
|
||||
def __delitem__(self, key):
|
||||
#rprt('%r.__delitem__(%r)\n' % (self, key))
|
||||
key = _check_key(self._len, key)
|
||||
#el cheapo solution...
|
||||
self._data = self[:key]._data | self[key+1:]._data >> key
|
||||
self._len = self._len - 1
|
||||
|
||||
def __getslice__(self, i, j):
|
||||
#rprt('%r.__getslice__(%r, %r)\n' % (self, i, j))
|
||||
i, j = _check_slice(self._len, i, j)
|
||||
if i >= j:
|
||||
return BitVec(0L, 0)
|
||||
if i:
|
||||
ndata = self._data >> i
|
||||
else:
|
||||
ndata = self._data
|
||||
nlength = j - i
|
||||
if j != self._len:
|
||||
#we'll have to invent faster variants here
|
||||
#e.g. mod_2exp
|
||||
ndata = ndata & ((1L << nlength) - 1)
|
||||
return BitVec(ndata, nlength)
|
||||
|
||||
def __setslice__(self, i, j, sequence, *rest):
|
||||
#rprt('%s.__setslice__%r\n' % (self, (i, j, sequence) + rest))
|
||||
i, j = _check_slice(self._len, i, j)
|
||||
if type(sequence) != type(self):
|
||||
sequence = apply(bitvec, (sequence, ) + rest)
|
||||
#sequence is now of our own type
|
||||
ls_part = self[:i]
|
||||
ms_part = self[j:]
|
||||
self._data = ls_part._data | \
|
||||
((sequence._data | \
|
||||
(ms_part._data << sequence._len)) << ls_part._len)
|
||||
self._len = self._len - j + i + sequence._len
|
||||
|
||||
def __delslice__(self, i, j):
|
||||
#rprt('%r.__delslice__(%r, %r)\n' % (self, i, j))
|
||||
i, j = _check_slice(self._len, i, j)
|
||||
if i == 0 and j == self._len:
|
||||
self._data, self._len = 0L, 0
|
||||
elif i < j:
|
||||
self._data = self[:i]._data | (self[j:]._data >> i)
|
||||
self._len = self._len - j + i
|
||||
|
||||
def __add__(self, other):
|
||||
#rprt('%r.__add__(%r)\n' % (self, other))
|
||||
retval = self.copy()
|
||||
retval[self._len:self._len] = other
|
||||
return retval
|
||||
|
||||
def __mul__(self, multiplier):
|
||||
#rprt('%r.__mul__(%r)\n' % (self, multiplier))
|
||||
if type(multiplier) != type(0):
|
||||
raise TypeError, 'sequence subscript not int'
|
||||
if multiplier <= 0:
|
||||
return BitVec(0L, 0)
|
||||
elif multiplier == 1:
|
||||
return self.copy()
|
||||
#handle special cases all 0 or all 1...
|
||||
if self._data == 0L:
|
||||
return BitVec(0L, self._len * multiplier)
|
||||
elif (~self)._data == 0L:
|
||||
return ~BitVec(0L, self._len * multiplier)
|
||||
#otherwise el cheapo again...
|
||||
retval = BitVec(0L, 0)
|
||||
while multiplier:
|
||||
retval, multiplier = retval + self, multiplier - 1
|
||||
return retval
|
||||
|
||||
def __and__(self, otherseq, *rest):
|
||||
#rprt('%r.__and__%r\n' % (self, (otherseq,) + rest))
|
||||
if type(otherseq) != type(self):
|
||||
otherseq = apply(bitvec, (otherseq, ) + rest)
|
||||
#sequence is now of our own type
|
||||
return BitVec(self._data & otherseq._data, \
|
||||
min(self._len, otherseq._len))
|
||||
|
||||
|
||||
def __xor__(self, otherseq, *rest):
|
||||
#rprt('%r.__xor__%r\n' % (self, (otherseq,) + rest))
|
||||
if type(otherseq) != type(self):
|
||||
otherseq = apply(bitvec, (otherseq, ) + rest)
|
||||
#sequence is now of our own type
|
||||
return BitVec(self._data ^ otherseq._data, \
|
||||
max(self._len, otherseq._len))
|
||||
|
||||
|
||||
def __or__(self, otherseq, *rest):
|
||||
#rprt('%r.__or__%r\n' % (self, (otherseq,) + rest))
|
||||
if type(otherseq) != type(self):
|
||||
otherseq = apply(bitvec, (otherseq, ) + rest)
|
||||
#sequence is now of our own type
|
||||
return BitVec(self._data | otherseq._data, \
|
||||
max(self._len, otherseq._len))
|
||||
|
||||
|
||||
def __invert__(self):
|
||||
#rprt('%r.__invert__()\n' % (self,))
|
||||
return BitVec(~self._data & ((1L << self._len) - 1), \
|
||||
self._len)
|
||||
|
||||
def __coerce__(self, otherseq, *rest):
|
||||
#needed for *some* of the arithmetic operations
|
||||
#rprt('%r.__coerce__%r\n' % (self, (otherseq,) + rest))
|
||||
if type(otherseq) != type(self):
|
||||
otherseq = apply(bitvec, (otherseq, ) + rest)
|
||||
return self, otherseq
|
||||
|
||||
def __int__(self):
|
||||
return int(self._data)
|
||||
|
||||
def __long__(self):
|
||||
return long(self._data)
|
||||
|
||||
def __float__(self):
|
||||
return float(self._data)
|
||||
|
||||
|
||||
bitvec = BitVec
|
60
2.7/Python-2.7.16/Demo/comparisons/README
Normal file
60
2.7/Python-2.7.16/Demo/comparisons/README
Normal file
@ -0,0 +1,60 @@
|
||||
Subject: Re: What language would you use?
|
||||
From: Tom Christiansen <tchrist@mox.perl.com>
|
||||
Date: 6 Nov 1994 15:14:51 GMT
|
||||
Newsgroups: comp.lang.python,comp.lang.tcl,comp.lang.scheme,comp.lang.misc,comp.lang.perl
|
||||
Message-Id: <39irtb$3t4@csnews.cs.Colorado.EDU>
|
||||
References: <39b7ha$j9v@zeno.nscf.org> <39hhjp$lgn@csnews.cs.Colorado.EDU> <39hvsu$dus@mathserv.mps.ohio-state.edu>
|
||||
|
||||
[...]
|
||||
If you're really into benchmarks, I'd love it if someone were to code up
|
||||
the following problems in tcl, python, and scheme (and whatever else you'd
|
||||
like). Separate versions (one optimized for speed, one for beauty :-) are
|
||||
ok. Post your code so we can time it on our own systems.
|
||||
|
||||
0) Factorial Test (numerics and function calls)
|
||||
|
||||
(we did this already)
|
||||
|
||||
1) Regular Expressions Test
|
||||
|
||||
Read a file of (extended per egrep) regular expressions (one per line),
|
||||
and apply those to all files whose names are listed on the command line.
|
||||
Basically, an 'egrep -f' simulator. Test it with 20 "vt100" patterns
|
||||
against a five /etc/termcap files. Tests using more elaborate patters
|
||||
would also be interesting. Your code should not break if given hundreds
|
||||
of regular expressions or binary files to scan.
|
||||
|
||||
2) Sorting Test
|
||||
|
||||
Sort an input file that consists of lines like this
|
||||
|
||||
var1=23 other=14 ditto=23 fred=2
|
||||
|
||||
such that each output line is sorted WRT to the number. Order
|
||||
of output lines does not change. Resolve collisions using the
|
||||
variable name. e.g.
|
||||
|
||||
fred=2 other=14 ditto=23 var1=23
|
||||
|
||||
Lines may be up to several kilobytes in length and contain
|
||||
zillions of variables.
|
||||
|
||||
3) System Test
|
||||
|
||||
Given a list of directories, report any bogus symbolic links contained
|
||||
anywhere in those subtrees. A bogus symbolic link is one that cannot
|
||||
be resolved because it points to a nonexistent or otherwise
|
||||
unresolvable file. Do *not* use an external find executable.
|
||||
Directories may be very very deep. Print a warning immediately if the
|
||||
system you're running on doesn't support symbolic links.
|
||||
|
||||
|
||||
I'll post perl solutions if people post the others.
|
||||
|
||||
|
||||
--tom
|
||||
--
|
||||
Tom Christiansen Perl Consultant, Gamer, Hiker tchrist@mox.perl.com
|
||||
|
||||
"But Billy! A *small* allowance prepares you for a lifetime of small
|
||||
salaries and for your Social Security payments." --Family Circus
|
4
2.7/Python-2.7.16/Demo/comparisons/patterns
Normal file
4
2.7/Python-2.7.16/Demo/comparisons/patterns
Normal file
@ -0,0 +1,4 @@
|
||||
^def
|
||||
^class
|
||||
^import
|
||||
^from
|
47
2.7/Python-2.7.16/Demo/comparisons/regextest.py
Normal file
47
2.7/Python-2.7.16/Demo/comparisons/regextest.py
Normal file
@ -0,0 +1,47 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# 1) Regular Expressions Test
|
||||
#
|
||||
# Read a file of (extended per egrep) regular expressions (one per line),
|
||||
# and apply those to all files whose names are listed on the command line.
|
||||
# Basically, an 'egrep -f' simulator. Test it with 20 "vt100" patterns
|
||||
# against a five /etc/termcap files. Tests using more elaborate patters
|
||||
# would also be interesting. Your code should not break if given hundreds
|
||||
# of regular expressions or binary files to scan.
|
||||
|
||||
# This implementation:
|
||||
# - combines all patterns into a single one using ( ... | ... | ... )
|
||||
# - reads patterns from stdin, scans files given as command line arguments
|
||||
# - produces output in the format <file>:<lineno>:<line>
|
||||
# - is only about 2.5 times as slow as egrep (though I couldn't run
|
||||
# Tom's test -- this system, a vanilla SGI, only has /etc/terminfo)
|
||||
|
||||
import string
|
||||
import sys
|
||||
import re
|
||||
|
||||
def main():
|
||||
pats = map(chomp, sys.stdin.readlines())
|
||||
bigpat = '(' + '|'.join(pats) + ')'
|
||||
prog = re.compile(bigpat)
|
||||
|
||||
for file in sys.argv[1:]:
|
||||
try:
|
||||
fp = open(file, 'r')
|
||||
except IOError, msg:
|
||||
print "%s: %s" % (file, msg)
|
||||
continue
|
||||
lineno = 0
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
break
|
||||
lineno = lineno + 1
|
||||
if prog.search(line):
|
||||
print "%s:%s:%s" % (file, lineno, line),
|
||||
|
||||
def chomp(s):
|
||||
return s.rstrip('\n')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
45
2.7/Python-2.7.16/Demo/comparisons/sortingtest.py
Normal file
45
2.7/Python-2.7.16/Demo/comparisons/sortingtest.py
Normal file
@ -0,0 +1,45 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# 2) Sorting Test
|
||||
#
|
||||
# Sort an input file that consists of lines like this
|
||||
#
|
||||
# var1=23 other=14 ditto=23 fred=2
|
||||
#
|
||||
# such that each output line is sorted WRT to the number. Order
|
||||
# of output lines does not change. Resolve collisions using the
|
||||
# variable name. e.g.
|
||||
#
|
||||
# fred=2 other=14 ditto=23 var1=23
|
||||
#
|
||||
# Lines may be up to several kilobytes in length and contain
|
||||
# zillions of variables.
|
||||
|
||||
# This implementation:
|
||||
# - Reads stdin, writes stdout
|
||||
# - Uses any amount of whitespace to separate fields
|
||||
# - Allows signed numbers
|
||||
# - Treats illegally formatted fields as field=0
|
||||
# - Outputs the sorted fields with exactly one space between them
|
||||
# - Handles blank input lines correctly
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
def main():
|
||||
prog = re.compile('^(.*)=([-+]?[0-9]+)')
|
||||
def makekey(item, prog=prog):
|
||||
match = prog.match(item)
|
||||
if match:
|
||||
var, num = match.groups()
|
||||
return int(num), var
|
||||
else:
|
||||
# Bad input -- pretend it's a var with value 0
|
||||
return 0, item
|
||||
for line in sys.stdin:
|
||||
items = sorted(makekey(item) for item in line.split())
|
||||
for num, var in items:
|
||||
print "%s=%s" % (var, num),
|
||||
print
|
||||
|
||||
main()
|
74
2.7/Python-2.7.16/Demo/comparisons/systemtest.py
Normal file
74
2.7/Python-2.7.16/Demo/comparisons/systemtest.py
Normal file
@ -0,0 +1,74 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# 3) System Test
|
||||
#
|
||||
# Given a list of directories, report any bogus symbolic links contained
|
||||
# anywhere in those subtrees. A bogus symbolic link is one that cannot
|
||||
# be resolved because it points to a nonexistent or otherwise
|
||||
# unresolvable file. Do *not* use an external find executable.
|
||||
# Directories may be very very deep. Print a warning immediately if the
|
||||
# system you're running on doesn't support symbolic links.
|
||||
|
||||
# This implementation:
|
||||
# - takes one optional argument, using the current directory as default
|
||||
# - uses chdir to increase performance
|
||||
# - sorts the names per directory
|
||||
# - prints output lines of the form "path1 -> path2" as it goes
|
||||
# - prints error messages about directories it can't list or chdir into
|
||||
|
||||
import os
|
||||
import sys
|
||||
from stat import *
|
||||
|
||||
def main():
|
||||
try:
|
||||
# Note: can't test for presence of lstat -- it's always there
|
||||
dummy = os.readlink
|
||||
except AttributeError:
|
||||
print "This system doesn't have symbolic links"
|
||||
sys.exit(0)
|
||||
if sys.argv[1:]:
|
||||
prefix = sys.argv[1]
|
||||
else:
|
||||
prefix = ''
|
||||
if prefix:
|
||||
os.chdir(prefix)
|
||||
if prefix[-1:] != '/': prefix = prefix + '/'
|
||||
reportboguslinks(prefix)
|
||||
else:
|
||||
reportboguslinks('')
|
||||
|
||||
def reportboguslinks(prefix):
|
||||
try:
|
||||
names = os.listdir('.')
|
||||
except os.error, msg:
|
||||
print "%s%s: can't list: %s" % (prefix, '.', msg)
|
||||
return
|
||||
names.sort()
|
||||
for name in names:
|
||||
if name == os.curdir or name == os.pardir:
|
||||
continue
|
||||
try:
|
||||
mode = os.lstat(name)[ST_MODE]
|
||||
except os.error:
|
||||
print "%s%s: can't stat: %s" % (prefix, name, msg)
|
||||
continue
|
||||
if S_ISLNK(mode):
|
||||
try:
|
||||
os.stat(name)
|
||||
except os.error:
|
||||
print "%s%s -> %s" % \
|
||||
(prefix, name, os.readlink(name))
|
||||
elif S_ISDIR(mode):
|
||||
try:
|
||||
os.chdir(name)
|
||||
except os.error, msg:
|
||||
print "%s%s: can't chdir: %s" % \
|
||||
(prefix, name, msg)
|
||||
continue
|
||||
try:
|
||||
reportboguslinks(prefix + name + '/')
|
||||
finally:
|
||||
os.chdir('..')
|
||||
|
||||
main()
|
25
2.7/Python-2.7.16/Demo/curses/README
Normal file
25
2.7/Python-2.7.16/Demo/curses/README
Normal file
@ -0,0 +1,25 @@
|
||||
This is a collection of demos and tests for the curses module.
|
||||
|
||||
ncurses demos
|
||||
=============
|
||||
|
||||
These demos are converted from the C versions in the ncurses
|
||||
distribution, and were contributed by Thomas Gellekum <tg@FreeBSD.org>
|
||||
I didn't strive for a `pythonic' style, but bluntly copied the
|
||||
originals. I won't attempt to `beautify' the program anytime soon, but
|
||||
I wouldn't mind someone else making an effort in that direction, of
|
||||
course.
|
||||
|
||||
ncurses.py -- currently only a panels demo
|
||||
rain.py -- raindrops keep falling on my desktop
|
||||
tclock.py -- ASCII clock, by Howard Jones
|
||||
xmas.py -- I'm dreaming of an ASCII christmas
|
||||
|
||||
Please submit bugfixes and new contributions to the Python bug tracker.
|
||||
|
||||
|
||||
Other demos
|
||||
===========
|
||||
|
||||
life.py -- Simple game of Life
|
||||
repeat.py -- Repeatedly execute a shell command (like watch(1))
|
216
2.7/Python-2.7.16/Demo/curses/life.py
Normal file
216
2.7/Python-2.7.16/Demo/curses/life.py
Normal file
@ -0,0 +1,216 @@
|
||||
#!/usr/bin/env python
|
||||
# life.py -- A curses-based version of Conway's Game of Life.
|
||||
# Contributed by AMK
|
||||
#
|
||||
# An empty board will be displayed, and the following commands are available:
|
||||
# E : Erase the board
|
||||
# R : Fill the board randomly
|
||||
# S : Step for a single generation
|
||||
# C : Update continuously until a key is struck
|
||||
# Q : Quit
|
||||
# Cursor keys : Move the cursor around the board
|
||||
# Space or Enter : Toggle the contents of the cursor's position
|
||||
#
|
||||
# TODO :
|
||||
# Support the mouse
|
||||
# Use colour if available
|
||||
# Make board updates faster
|
||||
#
|
||||
|
||||
import random, string, traceback
|
||||
import curses
|
||||
|
||||
class LifeBoard:
|
||||
"""Encapsulates a Life board
|
||||
|
||||
Attributes:
|
||||
X,Y : horizontal and vertical size of the board
|
||||
state : dictionary mapping (x,y) to 0 or 1
|
||||
|
||||
Methods:
|
||||
display(update_board) -- If update_board is true, compute the
|
||||
next generation. Then display the state
|
||||
of the board and refresh the screen.
|
||||
erase() -- clear the entire board
|
||||
makeRandom() -- fill the board randomly
|
||||
set(y,x) -- set the given cell to Live; doesn't refresh the screen
|
||||
toggle(y,x) -- change the given cell from live to dead, or vice
|
||||
versa, and refresh the screen display
|
||||
|
||||
"""
|
||||
def __init__(self, scr, char=ord('*')):
|
||||
"""Create a new LifeBoard instance.
|
||||
|
||||
scr -- curses screen object to use for display
|
||||
char -- character used to render live cells (default: '*')
|
||||
"""
|
||||
self.state = {}
|
||||
self.scr = scr
|
||||
Y, X = self.scr.getmaxyx()
|
||||
self.X, self.Y = X-2, Y-2-1
|
||||
self.char = char
|
||||
self.scr.clear()
|
||||
|
||||
# Draw a border around the board
|
||||
border_line = '+'+(self.X*'-')+'+'
|
||||
self.scr.addstr(0, 0, border_line)
|
||||
self.scr.addstr(self.Y+1,0, border_line)
|
||||
for y in range(0, self.Y):
|
||||
self.scr.addstr(1+y, 0, '|')
|
||||
self.scr.addstr(1+y, self.X+1, '|')
|
||||
self.scr.refresh()
|
||||
|
||||
def set(self, y, x):
|
||||
"""Set a cell to the live state"""
|
||||
if x<0 or self.X<=x or y<0 or self.Y<=y:
|
||||
raise ValueError, "Coordinates out of range %i,%i"% (y,x)
|
||||
self.state[x,y] = 1
|
||||
|
||||
def toggle(self, y, x):
|
||||
"""Toggle a cell's state between live and dead"""
|
||||
if x<0 or self.X<=x or y<0 or self.Y<=y:
|
||||
raise ValueError, "Coordinates out of range %i,%i"% (y,x)
|
||||
if self.state.has_key( (x,y) ):
|
||||
del self.state[x,y]
|
||||
self.scr.addch(y+1, x+1, ' ')
|
||||
else:
|
||||
self.state[x,y] = 1
|
||||
self.scr.addch(y+1, x+1, self.char)
|
||||
self.scr.refresh()
|
||||
|
||||
def erase(self):
|
||||
"""Clear the entire board and update the board display"""
|
||||
self.state = {}
|
||||
self.display(update_board=False)
|
||||
|
||||
def display(self, update_board=True):
|
||||
"""Display the whole board, optionally computing one generation"""
|
||||
M,N = self.X, self.Y
|
||||
if not update_board:
|
||||
for i in range(0, M):
|
||||
for j in range(0, N):
|
||||
if self.state.has_key( (i,j) ):
|
||||
self.scr.addch(j+1, i+1, self.char)
|
||||
else:
|
||||
self.scr.addch(j+1, i+1, ' ')
|
||||
self.scr.refresh()
|
||||
return
|
||||
|
||||
d = {}
|
||||
self.boring = 1
|
||||
for i in range(0, M):
|
||||
L = range( max(0, i-1), min(M, i+2) )
|
||||
for j in range(0, N):
|
||||
s = 0
|
||||
live = self.state.has_key( (i,j) )
|
||||
for k in range( max(0, j-1), min(N, j+2) ):
|
||||
for l in L:
|
||||
if self.state.has_key( (l,k) ):
|
||||
s += 1
|
||||
s -= live
|
||||
if s == 3:
|
||||
# Birth
|
||||
d[i,j] = 1
|
||||
self.scr.addch(j+1, i+1, self.char)
|
||||
if not live: self.boring = 0
|
||||
elif s == 2 and live: d[i,j] = 1 # Survival
|
||||
elif live:
|
||||
# Death
|
||||
self.scr.addch(j+1, i+1, ' ')
|
||||
self.boring = 0
|
||||
self.state = d
|
||||
self.scr.refresh()
|
||||
|
||||
def makeRandom(self):
|
||||
"Fill the board with a random pattern"
|
||||
self.state = {}
|
||||
for i in range(0, self.X):
|
||||
for j in range(0, self.Y):
|
||||
if random.random() > 0.5:
|
||||
self.set(j,i)
|
||||
|
||||
|
||||
def erase_menu(stdscr, menu_y):
|
||||
"Clear the space where the menu resides"
|
||||
stdscr.move(menu_y, 0)
|
||||
stdscr.clrtoeol()
|
||||
stdscr.move(menu_y+1, 0)
|
||||
stdscr.clrtoeol()
|
||||
|
||||
def display_menu(stdscr, menu_y):
|
||||
"Display the menu of possible keystroke commands"
|
||||
erase_menu(stdscr, menu_y)
|
||||
stdscr.addstr(menu_y, 4,
|
||||
'Use the cursor keys to move, and space or Enter to toggle a cell.')
|
||||
stdscr.addstr(menu_y+1, 4,
|
||||
'E)rase the board, R)andom fill, S)tep once or C)ontinuously, Q)uit')
|
||||
|
||||
def keyloop(stdscr):
|
||||
# Clear the screen and display the menu of keys
|
||||
stdscr.clear()
|
||||
stdscr_y, stdscr_x = stdscr.getmaxyx()
|
||||
menu_y = (stdscr_y-3)-1
|
||||
display_menu(stdscr, menu_y)
|
||||
|
||||
# Allocate a subwindow for the Life board and create the board object
|
||||
subwin = stdscr.subwin(stdscr_y-3, stdscr_x, 0, 0)
|
||||
board = LifeBoard(subwin, char=ord('*'))
|
||||
board.display(update_board=False)
|
||||
|
||||
# xpos, ypos are the cursor's position
|
||||
xpos, ypos = board.X//2, board.Y//2
|
||||
|
||||
# Main loop:
|
||||
while (1):
|
||||
stdscr.move(1+ypos, 1+xpos) # Move the cursor
|
||||
c = stdscr.getch() # Get a keystroke
|
||||
if 0<c<256:
|
||||
c = chr(c)
|
||||
if c in ' \n':
|
||||
board.toggle(ypos, xpos)
|
||||
elif c in 'Cc':
|
||||
erase_menu(stdscr, menu_y)
|
||||
stdscr.addstr(menu_y, 6, ' Hit any key to stop continuously '
|
||||
'updating the screen.')
|
||||
stdscr.refresh()
|
||||
# Activate nodelay mode; getch() will return -1
|
||||
# if no keystroke is available, instead of waiting.
|
||||
stdscr.nodelay(1)
|
||||
while (1):
|
||||
c = stdscr.getch()
|
||||
if c != -1:
|
||||
break
|
||||
stdscr.addstr(0,0, '/')
|
||||
stdscr.refresh()
|
||||
board.display()
|
||||
stdscr.addstr(0,0, '+')
|
||||
stdscr.refresh()
|
||||
|
||||
stdscr.nodelay(0) # Disable nodelay mode
|
||||
display_menu(stdscr, menu_y)
|
||||
|
||||
elif c in 'Ee':
|
||||
board.erase()
|
||||
elif c in 'Qq':
|
||||
break
|
||||
elif c in 'Rr':
|
||||
board.makeRandom()
|
||||
board.display(update_board=False)
|
||||
elif c in 'Ss':
|
||||
board.display()
|
||||
else: pass # Ignore incorrect keys
|
||||
elif c == curses.KEY_UP and ypos>0: ypos -= 1
|
||||
elif c == curses.KEY_DOWN and ypos<board.Y-1: ypos += 1
|
||||
elif c == curses.KEY_LEFT and xpos>0: xpos -= 1
|
||||
elif c == curses.KEY_RIGHT and xpos<board.X-1: xpos += 1
|
||||
else:
|
||||
# Ignore incorrect keys
|
||||
pass
|
||||
|
||||
|
||||
def main(stdscr):
|
||||
keyloop(stdscr) # Enter the main loop
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
curses.wrapper(main)
|
273
2.7/Python-2.7.16/Demo/curses/ncurses.py
Normal file
273
2.7/Python-2.7.16/Demo/curses/ncurses.py
Normal file
@ -0,0 +1,273 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# (n)curses exerciser in Python, an interactive test for the curses
|
||||
# module. Currently, only the panel demos are ported.
|
||||
|
||||
import curses
|
||||
from curses import panel
|
||||
|
||||
def wGetchar(win = None):
|
||||
if win is None: win = stdscr
|
||||
return win.getch()
|
||||
|
||||
def Getchar():
|
||||
wGetchar()
|
||||
|
||||
#
|
||||
# Panels tester
|
||||
#
|
||||
def wait_a_while():
|
||||
if nap_msec == 1:
|
||||
Getchar()
|
||||
else:
|
||||
curses.napms(nap_msec)
|
||||
|
||||
def saywhat(text):
|
||||
stdscr.move(curses.LINES - 1, 0)
|
||||
stdscr.clrtoeol()
|
||||
stdscr.addstr(text)
|
||||
|
||||
def mkpanel(color, rows, cols, tly, tlx):
|
||||
win = curses.newwin(rows, cols, tly, tlx)
|
||||
pan = panel.new_panel(win)
|
||||
if curses.has_colors():
|
||||
if color == curses.COLOR_BLUE:
|
||||
fg = curses.COLOR_WHITE
|
||||
else:
|
||||
fg = curses.COLOR_BLACK
|
||||
bg = color
|
||||
curses.init_pair(color, fg, bg)
|
||||
win.bkgdset(ord(' '), curses.color_pair(color))
|
||||
else:
|
||||
win.bkgdset(ord(' '), curses.A_BOLD)
|
||||
|
||||
return pan
|
||||
|
||||
def pflush():
|
||||
panel.update_panels()
|
||||
curses.doupdate()
|
||||
|
||||
def fill_panel(pan):
|
||||
win = pan.window()
|
||||
num = pan.userptr()[1]
|
||||
|
||||
win.move(1, 1)
|
||||
win.addstr("-pan%c-" % num)
|
||||
win.clrtoeol()
|
||||
win.box()
|
||||
|
||||
maxy, maxx = win.getmaxyx()
|
||||
for y in range(2, maxy - 1):
|
||||
for x in range(1, maxx - 1):
|
||||
win.move(y, x)
|
||||
win.addch(num)
|
||||
|
||||
def demo_panels(win):
|
||||
global stdscr, nap_msec, mod
|
||||
stdscr = win
|
||||
nap_msec = 1
|
||||
mod = ["test", "TEST", "(**)", "*()*", "<-->", "LAST"]
|
||||
|
||||
stdscr.refresh()
|
||||
|
||||
for y in range(0, curses.LINES - 1):
|
||||
for x in range(0, curses.COLS):
|
||||
stdscr.addstr("%d" % ((y + x) % 10))
|
||||
for y in range(0, 1):
|
||||
p1 = mkpanel(curses.COLOR_RED,
|
||||
curses.LINES // 2 - 2,
|
||||
curses.COLS // 8 + 1,
|
||||
0,
|
||||
0)
|
||||
p1.set_userptr("p1")
|
||||
|
||||
p2 = mkpanel(curses.COLOR_GREEN,
|
||||
curses.LINES // 2 + 1,
|
||||
curses.COLS // 7,
|
||||
curses.LINES // 4,
|
||||
curses.COLS // 10)
|
||||
p2.set_userptr("p2")
|
||||
|
||||
p3 = mkpanel(curses.COLOR_YELLOW,
|
||||
curses.LINES // 4,
|
||||
curses.COLS // 10,
|
||||
curses.LINES // 2,
|
||||
curses.COLS // 9)
|
||||
p3.set_userptr("p3")
|
||||
|
||||
p4 = mkpanel(curses.COLOR_BLUE,
|
||||
curses.LINES // 2 - 2,
|
||||
curses.COLS // 8,
|
||||
curses.LINES // 2 - 2,
|
||||
curses.COLS // 3)
|
||||
p4.set_userptr("p4")
|
||||
|
||||
p5 = mkpanel(curses.COLOR_MAGENTA,
|
||||
curses.LINES // 2 - 2,
|
||||
curses.COLS // 8,
|
||||
curses.LINES // 2,
|
||||
curses.COLS // 2 - 2)
|
||||
p5.set_userptr("p5")
|
||||
|
||||
fill_panel(p1)
|
||||
fill_panel(p2)
|
||||
fill_panel(p3)
|
||||
fill_panel(p4)
|
||||
fill_panel(p5)
|
||||
p4.hide()
|
||||
p5.hide()
|
||||
pflush()
|
||||
saywhat("press any key to continue")
|
||||
wait_a_while()
|
||||
|
||||
saywhat("h3 s1 s2 s4 s5;press any key to continue")
|
||||
p1.move(0, 0)
|
||||
p3.hide()
|
||||
p1.show()
|
||||
p2.show()
|
||||
p4.show()
|
||||
p5.show()
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("s1; press any key to continue")
|
||||
p1.show()
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("s2; press any key to continue")
|
||||
p2.show()
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("m2; press any key to continue")
|
||||
p2.move(curses.LINES // 3 + 1, curses.COLS // 8)
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("s3; press any key to continue")
|
||||
p3.show()
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("m3; press any key to continue")
|
||||
p3.move(curses.LINES // 4 + 1, curses.COLS // 15)
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("b3; press any key to continue")
|
||||
p3.bottom()
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("s4; press any key to continue")
|
||||
p4.show()
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("s5; press any key to continue")
|
||||
p5.show()
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("t3; press any key to continue")
|
||||
p3.top()
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("t1; press any key to continue")
|
||||
p1.show()
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("t2; press any key to continue")
|
||||
p2.show()
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("t3; press any key to continue")
|
||||
p3.show()
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("t4; press any key to continue")
|
||||
p4.show()
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
for itmp in range(0, 6):
|
||||
w4 = p4.window()
|
||||
w5 = p5.window()
|
||||
|
||||
saywhat("m4; press any key to continue")
|
||||
w4.move(curses.LINES // 8, 1)
|
||||
w4.addstr(mod[itmp])
|
||||
p4.move(curses.LINES // 6, itmp * curses.COLS // 8)
|
||||
w5.move(curses.LINES // 6, 1)
|
||||
w5.addstr(mod[itmp])
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("m5; press any key to continue")
|
||||
w4.move(curses.LINES // 6, 1)
|
||||
w4.addstr(mod[itmp])
|
||||
p5.move(curses.LINES // 3 - 1, itmp * 10 + 6)
|
||||
w5.move(curses.LINES // 8, 1)
|
||||
w5.addstr(mod[itmp])
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("m4; press any key to continue")
|
||||
p4.move(curses.LINES // 6, (itmp + 1) * curses.COLS // 8)
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("t5; press any key to continue")
|
||||
p5.top()
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("t2; press any key to continue")
|
||||
p2.top()
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("t1; press any key to continue")
|
||||
p1.top()
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("d2; press any key to continue")
|
||||
del p2
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("h3; press any key to continue")
|
||||
p3.hide()
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("d1; press any key to continue")
|
||||
del p1
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("d4; press any key to continue")
|
||||
del p4
|
||||
pflush()
|
||||
wait_a_while()
|
||||
|
||||
saywhat("d5; press any key to continue")
|
||||
del p5
|
||||
pflush()
|
||||
wait_a_while()
|
||||
if nap_msec == 1:
|
||||
break
|
||||
nap_msec = 100
|
||||
|
||||
#
|
||||
# one fine day there'll be the menu at this place
|
||||
#
|
||||
curses.wrapper(demo_panels)
|
94
2.7/Python-2.7.16/Demo/curses/rain.py
Normal file
94
2.7/Python-2.7.16/Demo/curses/rain.py
Normal file
@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# somebody should probably check the randrange()s...
|
||||
|
||||
import curses
|
||||
from random import randrange
|
||||
|
||||
def next_j(j):
|
||||
if j == 0:
|
||||
j = 4
|
||||
else:
|
||||
j -= 1
|
||||
|
||||
if curses.has_colors():
|
||||
z = randrange(0, 3)
|
||||
color = curses.color_pair(z)
|
||||
if z:
|
||||
color = color | curses.A_BOLD
|
||||
stdscr.attrset(color)
|
||||
|
||||
return j
|
||||
|
||||
def main(win):
|
||||
# we know that the first argument from curses.wrapper() is stdscr.
|
||||
# Initialize it globally for convenience.
|
||||
global stdscr
|
||||
stdscr = win
|
||||
|
||||
if curses.has_colors():
|
||||
bg = curses.COLOR_BLACK
|
||||
curses.init_pair(1, curses.COLOR_BLUE, bg)
|
||||
curses.init_pair(2, curses.COLOR_CYAN, bg)
|
||||
|
||||
curses.nl()
|
||||
curses.noecho()
|
||||
# XXX curs_set() always returns ERR
|
||||
# curses.curs_set(0)
|
||||
stdscr.timeout(0)
|
||||
|
||||
c = curses.COLS - 4
|
||||
r = curses.LINES - 4
|
||||
xpos = [0] * c
|
||||
ypos = [0] * r
|
||||
for j in range(4, -1, -1):
|
||||
xpos[j] = randrange(0, c) + 2
|
||||
ypos[j] = randrange(0, r) + 2
|
||||
|
||||
j = 0
|
||||
while True:
|
||||
x = randrange(0, c) + 2
|
||||
y = randrange(0, r) + 2
|
||||
|
||||
stdscr.addch(y, x, ord('.'))
|
||||
|
||||
stdscr.addch(ypos[j], xpos[j], ord('o'))
|
||||
|
||||
j = next_j(j)
|
||||
stdscr.addch(ypos[j], xpos[j], ord('O'))
|
||||
|
||||
j = next_j(j)
|
||||
stdscr.addch( ypos[j] - 1, xpos[j], ord('-'))
|
||||
stdscr.addstr(ypos[j], xpos[j] - 1, "|.|")
|
||||
stdscr.addch( ypos[j] + 1, xpos[j], ord('-'))
|
||||
|
||||
j = next_j(j)
|
||||
stdscr.addch( ypos[j] - 2, xpos[j], ord('-'))
|
||||
stdscr.addstr(ypos[j] - 1, xpos[j] - 1, "/ \\")
|
||||
stdscr.addstr(ypos[j], xpos[j] - 2, "| O |")
|
||||
stdscr.addstr(ypos[j] + 1, xpos[j] - 1, "\\ /")
|
||||
stdscr.addch( ypos[j] + 2, xpos[j], ord('-'))
|
||||
|
||||
j = next_j(j)
|
||||
stdscr.addch( ypos[j] - 2, xpos[j], ord(' '))
|
||||
stdscr.addstr(ypos[j] - 1, xpos[j] - 1, " ")
|
||||
stdscr.addstr(ypos[j], xpos[j] - 2, " ")
|
||||
stdscr.addstr(ypos[j] + 1, xpos[j] - 1, " ")
|
||||
stdscr.addch( ypos[j] + 2, xpos[j], ord(' '))
|
||||
|
||||
xpos[j] = x
|
||||
ypos[j] = y
|
||||
|
||||
ch = stdscr.getch()
|
||||
if ch == ord('q') or ch == ord('Q'):
|
||||
return
|
||||
elif ch == ord('s'):
|
||||
stdscr.nodelay(0)
|
||||
elif ch == ord(' '):
|
||||
stdscr.nodelay(1)
|
||||
|
||||
curses.napms(50)
|
||||
|
||||
curses.wrapper(main)
|
58
2.7/Python-2.7.16/Demo/curses/repeat.py
Normal file
58
2.7/Python-2.7.16/Demo/curses/repeat.py
Normal file
@ -0,0 +1,58 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"""repeat <shell-command>
|
||||
|
||||
This simple program repeatedly (at 1-second intervals) executes the
|
||||
shell command given on the command line and displays the output (or as
|
||||
much of it as fits on the screen). It uses curses to paint each new
|
||||
output on top of the old output, so that if nothing changes, the
|
||||
screen doesn't change. This is handy to watch for changes in e.g. a
|
||||
directory or process listing.
|
||||
|
||||
To end, hit Control-C.
|
||||
"""
|
||||
|
||||
# Author: Guido van Rossum
|
||||
|
||||
# Disclaimer: there's a Linux program named 'watch' that does the same
|
||||
# thing. Honestly, I didn't know of its existence when I wrote this!
|
||||
|
||||
# To do: add features until it has the same functionality as watch(1);
|
||||
# then compare code size and development time.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import curses
|
||||
|
||||
def main():
|
||||
if not sys.argv[1:]:
|
||||
print __doc__
|
||||
sys.exit(0)
|
||||
cmd = " ".join(sys.argv[1:])
|
||||
p = os.popen(cmd, "r")
|
||||
text = p.read()
|
||||
sts = p.close()
|
||||
if sts:
|
||||
print >>sys.stderr, "Exit code:", sts
|
||||
sys.exit(sts)
|
||||
w = curses.initscr()
|
||||
try:
|
||||
while True:
|
||||
w.erase()
|
||||
try:
|
||||
w.addstr(text)
|
||||
except curses.error:
|
||||
pass
|
||||
w.refresh()
|
||||
time.sleep(1)
|
||||
p = os.popen(cmd, "r")
|
||||
text = p.read()
|
||||
sts = p.close()
|
||||
if sts:
|
||||
print >>sys.stderr, "Exit code:", sts
|
||||
sys.exit(sts)
|
||||
finally:
|
||||
curses.endwin()
|
||||
|
||||
main()
|
147
2.7/Python-2.7.16/Demo/curses/tclock.py
Normal file
147
2.7/Python-2.7.16/Demo/curses/tclock.py
Normal file
@ -0,0 +1,147 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# From tclock.c, Copyright Howard Jones <ha.jones@ic.ac.uk>, September 1994.
|
||||
|
||||
from math import *
|
||||
import curses, time
|
||||
|
||||
ASPECT = 2.2
|
||||
|
||||
def sign(_x):
|
||||
if _x < 0: return -1
|
||||
return 1
|
||||
|
||||
def A2XY(angle, radius):
|
||||
return (int(round(ASPECT * radius * sin(angle))),
|
||||
int(round(radius * cos(angle))))
|
||||
|
||||
def plot(x, y, col):
|
||||
stdscr.addch(y, x, col)
|
||||
|
||||
# draw a diagonal line using Bresenham's algorithm
|
||||
def dline(pair, from_x, from_y, x2, y2, ch):
|
||||
if curses.has_colors():
|
||||
stdscr.attrset(curses.color_pair(pair))
|
||||
|
||||
dx = x2 - from_x
|
||||
dy = y2 - from_y
|
||||
|
||||
ax = abs(dx * 2)
|
||||
ay = abs(dy * 2)
|
||||
|
||||
sx = sign(dx)
|
||||
sy = sign(dy)
|
||||
|
||||
x = from_x
|
||||
y = from_y
|
||||
|
||||
if ax > ay:
|
||||
d = ay - ax // 2
|
||||
|
||||
while True:
|
||||
plot(x, y, ch)
|
||||
if x == x2:
|
||||
return
|
||||
|
||||
if d >= 0:
|
||||
y += sy
|
||||
d -= ax
|
||||
x += sx
|
||||
d += ay
|
||||
else:
|
||||
d = ax - ay // 2
|
||||
|
||||
while True:
|
||||
plot(x, y, ch)
|
||||
if y == y2:
|
||||
return
|
||||
|
||||
if d >= 0:
|
||||
x += sx
|
||||
d -= ay
|
||||
y += sy
|
||||
d += ax
|
||||
|
||||
def main(win):
|
||||
global stdscr
|
||||
stdscr = win
|
||||
|
||||
lastbeep = -1
|
||||
my_bg = curses.COLOR_BLACK
|
||||
|
||||
stdscr.nodelay(1)
|
||||
stdscr.timeout(0)
|
||||
# curses.curs_set(0)
|
||||
if curses.has_colors():
|
||||
curses.init_pair(1, curses.COLOR_RED, my_bg)
|
||||
curses.init_pair(2, curses.COLOR_MAGENTA, my_bg)
|
||||
curses.init_pair(3, curses.COLOR_GREEN, my_bg)
|
||||
|
||||
cx = (curses.COLS - 1) // 2
|
||||
cy = curses.LINES // 2
|
||||
ch = min( cy-1, int(cx // ASPECT) - 1)
|
||||
mradius = (3 * ch) // 4
|
||||
hradius = ch // 2
|
||||
sradius = 5 * ch // 6
|
||||
|
||||
for i in range(0, 12):
|
||||
sangle = (i + 1) * 2.0 * pi / 12.0
|
||||
sdx, sdy = A2XY(sangle, sradius)
|
||||
|
||||
stdscr.addstr(cy - sdy, cx + sdx, "%d" % (i + 1))
|
||||
|
||||
stdscr.addstr(0, 0,
|
||||
"ASCII Clock by Howard Jones <ha.jones@ic.ac.uk>, 1994")
|
||||
|
||||
sradius = max(sradius-4, 8)
|
||||
|
||||
while True:
|
||||
curses.napms(1000)
|
||||
|
||||
tim = time.time()
|
||||
t = time.localtime(tim)
|
||||
|
||||
hours = t[3] + t[4] / 60.0
|
||||
if hours > 12.0:
|
||||
hours -= 12.0
|
||||
|
||||
mangle = t[4] * 2 * pi / 60.0
|
||||
mdx, mdy = A2XY(mangle, mradius)
|
||||
|
||||
hangle = hours * 2 * pi / 12.0
|
||||
hdx, hdy = A2XY(hangle, hradius)
|
||||
|
||||
sangle = t[5] * 2 * pi / 60.0
|
||||
sdx, sdy = A2XY(sangle, sradius)
|
||||
|
||||
dline(3, cx, cy, cx + mdx, cy - mdy, ord('#'))
|
||||
|
||||
stdscr.attrset(curses.A_REVERSE)
|
||||
dline(2, cx, cy, cx + hdx, cy - hdy, ord('.'))
|
||||
stdscr.attroff(curses.A_REVERSE)
|
||||
|
||||
if curses.has_colors():
|
||||
stdscr.attrset(curses.color_pair(1))
|
||||
|
||||
plot(cx + sdx, cy - sdy, ord('O'))
|
||||
|
||||
if curses.has_colors():
|
||||
stdscr.attrset(curses.color_pair(0))
|
||||
|
||||
stdscr.addstr(curses.LINES - 2, 0, time.ctime(tim))
|
||||
stdscr.refresh()
|
||||
if (t[5] % 5) == 0 and t[5] != lastbeep:
|
||||
lastbeep = t[5]
|
||||
curses.beep()
|
||||
|
||||
ch = stdscr.getch()
|
||||
if ch == ord('q'):
|
||||
return 0
|
||||
|
||||
plot(cx + sdx, cy - sdy, ord(' '))
|
||||
dline(0, cx, cy, cx + hdx, cy - hdy, ord(' '))
|
||||
dline(0, cx, cy, cx + mdx, cy - mdy, ord(' '))
|
||||
|
||||
curses.wrapper(main)
|
906
2.7/Python-2.7.16/Demo/curses/xmas.py
Normal file
906
2.7/Python-2.7.16/Demo/curses/xmas.py
Normal file
@ -0,0 +1,906 @@
|
||||
# asciixmas
|
||||
# December 1989 Larry Bartz Indianapolis, IN
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# I'm dreaming of an ascii character-based monochrome Christmas,
|
||||
# Just like the ones I used to know!
|
||||
# Via a full duplex communications channel,
|
||||
# At 9600 bits per second,
|
||||
# Even though it's kinda slow.
|
||||
#
|
||||
# I'm dreaming of an ascii character-based monochrome Christmas,
|
||||
# With ev'ry C program I write!
|
||||
# May your screen be merry and bright!
|
||||
# And may all your Christmases be amber or green,
|
||||
# (for reduced eyestrain and improved visibility)!
|
||||
#
|
||||
#
|
||||
# Notes on the Python version:
|
||||
# I used a couple of `try...except curses.error' to get around some functions
|
||||
# returning ERR. The errors come from using wrapping functions to fill
|
||||
# windows to the last character cell. The C version doesn't have this problem,
|
||||
# it simply ignores any return values.
|
||||
#
|
||||
|
||||
import curses
|
||||
import sys
|
||||
|
||||
FROMWHO = "Thomas Gellekum <tg@FreeBSD.org>"
|
||||
|
||||
def set_color(win, color):
|
||||
if curses.has_colors():
|
||||
n = color + 1
|
||||
curses.init_pair(n, color, my_bg)
|
||||
win.attroff(curses.A_COLOR)
|
||||
win.attron(curses.color_pair(n))
|
||||
|
||||
def unset_color(win):
|
||||
if curses.has_colors():
|
||||
win.attrset(curses.color_pair(0))
|
||||
|
||||
def look_out(msecs):
|
||||
curses.napms(msecs)
|
||||
if stdscr.getch() != -1:
|
||||
curses.beep()
|
||||
sys.exit(0)
|
||||
|
||||
def boxit():
|
||||
for y in range(0, 20):
|
||||
stdscr.addch(y, 7, ord('|'))
|
||||
|
||||
for x in range(8, 80):
|
||||
stdscr.addch(19, x, ord('_'))
|
||||
|
||||
for x in range(0, 80):
|
||||
stdscr.addch(22, x, ord('_'))
|
||||
|
||||
return
|
||||
|
||||
def seas():
|
||||
stdscr.addch(4, 1, ord('S'))
|
||||
stdscr.addch(6, 1, ord('E'))
|
||||
stdscr.addch(8, 1, ord('A'))
|
||||
stdscr.addch(10, 1, ord('S'))
|
||||
stdscr.addch(12, 1, ord('O'))
|
||||
stdscr.addch(14, 1, ord('N'))
|
||||
stdscr.addch(16, 1, ord("'"))
|
||||
stdscr.addch(18, 1, ord('S'))
|
||||
|
||||
return
|
||||
|
||||
def greet():
|
||||
stdscr.addch(3, 5, ord('G'))
|
||||
stdscr.addch(5, 5, ord('R'))
|
||||
stdscr.addch(7, 5, ord('E'))
|
||||
stdscr.addch(9, 5, ord('E'))
|
||||
stdscr.addch(11, 5, ord('T'))
|
||||
stdscr.addch(13, 5, ord('I'))
|
||||
stdscr.addch(15, 5, ord('N'))
|
||||
stdscr.addch(17, 5, ord('G'))
|
||||
stdscr.addch(19, 5, ord('S'))
|
||||
|
||||
return
|
||||
|
||||
def fromwho():
|
||||
stdscr.addstr(21, 13, FROMWHO)
|
||||
return
|
||||
|
||||
def tree():
|
||||
set_color(treescrn, curses.COLOR_GREEN)
|
||||
treescrn.addch(1, 11, ord('/'))
|
||||
treescrn.addch(2, 11, ord('/'))
|
||||
treescrn.addch(3, 10, ord('/'))
|
||||
treescrn.addch(4, 9, ord('/'))
|
||||
treescrn.addch(5, 9, ord('/'))
|
||||
treescrn.addch(6, 8, ord('/'))
|
||||
treescrn.addch(7, 7, ord('/'))
|
||||
treescrn.addch(8, 6, ord('/'))
|
||||
treescrn.addch(9, 6, ord('/'))
|
||||
treescrn.addch(10, 5, ord('/'))
|
||||
treescrn.addch(11, 3, ord('/'))
|
||||
treescrn.addch(12, 2, ord('/'))
|
||||
|
||||
treescrn.addch(1, 13, ord('\\'))
|
||||
treescrn.addch(2, 13, ord('\\'))
|
||||
treescrn.addch(3, 14, ord('\\'))
|
||||
treescrn.addch(4, 15, ord('\\'))
|
||||
treescrn.addch(5, 15, ord('\\'))
|
||||
treescrn.addch(6, 16, ord('\\'))
|
||||
treescrn.addch(7, 17, ord('\\'))
|
||||
treescrn.addch(8, 18, ord('\\'))
|
||||
treescrn.addch(9, 18, ord('\\'))
|
||||
treescrn.addch(10, 19, ord('\\'))
|
||||
treescrn.addch(11, 21, ord('\\'))
|
||||
treescrn.addch(12, 22, ord('\\'))
|
||||
|
||||
treescrn.addch(4, 10, ord('_'))
|
||||
treescrn.addch(4, 14, ord('_'))
|
||||
treescrn.addch(8, 7, ord('_'))
|
||||
treescrn.addch(8, 17, ord('_'))
|
||||
|
||||
treescrn.addstr(13, 0, "//////////// \\\\\\\\\\\\\\\\\\\\\\\\")
|
||||
|
||||
treescrn.addstr(14, 11, "| |")
|
||||
treescrn.addstr(15, 11, "|_|")
|
||||
|
||||
unset_color(treescrn)
|
||||
treescrn.refresh()
|
||||
w_del_msg.refresh()
|
||||
|
||||
return
|
||||
|
||||
def balls():
|
||||
treescrn.overlay(treescrn2)
|
||||
|
||||
set_color(treescrn2, curses.COLOR_BLUE)
|
||||
treescrn2.addch(3, 9, ord('@'))
|
||||
treescrn2.addch(3, 15, ord('@'))
|
||||
treescrn2.addch(4, 8, ord('@'))
|
||||
treescrn2.addch(4, 16, ord('@'))
|
||||
treescrn2.addch(5, 7, ord('@'))
|
||||
treescrn2.addch(5, 17, ord('@'))
|
||||
treescrn2.addch(7, 6, ord('@'))
|
||||
treescrn2.addch(7, 18, ord('@'))
|
||||
treescrn2.addch(8, 5, ord('@'))
|
||||
treescrn2.addch(8, 19, ord('@'))
|
||||
treescrn2.addch(10, 4, ord('@'))
|
||||
treescrn2.addch(10, 20, ord('@'))
|
||||
treescrn2.addch(11, 2, ord('@'))
|
||||
treescrn2.addch(11, 22, ord('@'))
|
||||
treescrn2.addch(12, 1, ord('@'))
|
||||
treescrn2.addch(12, 23, ord('@'))
|
||||
|
||||
unset_color(treescrn2)
|
||||
treescrn2.refresh()
|
||||
w_del_msg.refresh()
|
||||
return
|
||||
|
||||
def star():
|
||||
treescrn2.attrset(curses.A_BOLD | curses.A_BLINK)
|
||||
set_color(treescrn2, curses.COLOR_YELLOW)
|
||||
|
||||
treescrn2.addch(0, 12, ord('*'))
|
||||
treescrn2.standend()
|
||||
|
||||
unset_color(treescrn2)
|
||||
treescrn2.refresh()
|
||||
w_del_msg.refresh()
|
||||
return
|
||||
|
||||
def strng1():
|
||||
treescrn2.attrset(curses.A_BOLD | curses.A_BLINK)
|
||||
set_color(treescrn2, curses.COLOR_WHITE)
|
||||
|
||||
treescrn2.addch(3, 13, ord('\''))
|
||||
treescrn2.addch(3, 12, ord(':'))
|
||||
treescrn2.addch(3, 11, ord('.'))
|
||||
|
||||
treescrn2.attroff(curses.A_BOLD | curses.A_BLINK)
|
||||
unset_color(treescrn2)
|
||||
|
||||
treescrn2.refresh()
|
||||
w_del_msg.refresh()
|
||||
return
|
||||
|
||||
def strng2():
|
||||
treescrn2.attrset(curses.A_BOLD | curses.A_BLINK)
|
||||
set_color(treescrn2, curses.COLOR_WHITE)
|
||||
|
||||
treescrn2.addch(5, 14, ord('\''))
|
||||
treescrn2.addch(5, 13, ord(':'))
|
||||
treescrn2.addch(5, 12, ord('.'))
|
||||
treescrn2.addch(5, 11, ord(','))
|
||||
treescrn2.addch(6, 10, ord('\''))
|
||||
treescrn2.addch(6, 9, ord(':'))
|
||||
|
||||
treescrn2.attroff(curses.A_BOLD | curses.A_BLINK)
|
||||
unset_color(treescrn2)
|
||||
|
||||
treescrn2.refresh()
|
||||
w_del_msg.refresh()
|
||||
return
|
||||
|
||||
def strng3():
|
||||
treescrn2.attrset(curses.A_BOLD | curses.A_BLINK)
|
||||
set_color(treescrn2, curses.COLOR_WHITE)
|
||||
|
||||
treescrn2.addch(7, 16, ord('\''))
|
||||
treescrn2.addch(7, 15, ord(':'))
|
||||
treescrn2.addch(7, 14, ord('.'))
|
||||
treescrn2.addch(7, 13, ord(','))
|
||||
treescrn2.addch(8, 12, ord('\''))
|
||||
treescrn2.addch(8, 11, ord(':'))
|
||||
treescrn2.addch(8, 10, ord('.'))
|
||||
treescrn2.addch(8, 9, ord(','))
|
||||
|
||||
treescrn2.attroff(curses.A_BOLD | curses.A_BLINK)
|
||||
unset_color(treescrn2)
|
||||
|
||||
treescrn2.refresh()
|
||||
w_del_msg.refresh()
|
||||
return
|
||||
|
||||
def strng4():
|
||||
treescrn2.attrset(curses.A_BOLD | curses.A_BLINK)
|
||||
set_color(treescrn2, curses.COLOR_WHITE)
|
||||
|
||||
treescrn2.addch(9, 17, ord('\''))
|
||||
treescrn2.addch(9, 16, ord(':'))
|
||||
treescrn2.addch(9, 15, ord('.'))
|
||||
treescrn2.addch(9, 14, ord(','))
|
||||
treescrn2.addch(10, 13, ord('\''))
|
||||
treescrn2.addch(10, 12, ord(':'))
|
||||
treescrn2.addch(10, 11, ord('.'))
|
||||
treescrn2.addch(10, 10, ord(','))
|
||||
treescrn2.addch(11, 9, ord('\''))
|
||||
treescrn2.addch(11, 8, ord(':'))
|
||||
treescrn2.addch(11, 7, ord('.'))
|
||||
treescrn2.addch(11, 6, ord(','))
|
||||
treescrn2.addch(12, 5, ord('\''))
|
||||
|
||||
treescrn2.attroff(curses.A_BOLD | curses.A_BLINK)
|
||||
unset_color(treescrn2)
|
||||
|
||||
treescrn2.refresh()
|
||||
w_del_msg.refresh()
|
||||
return
|
||||
|
||||
def strng5():
|
||||
treescrn2.attrset(curses.A_BOLD | curses.A_BLINK)
|
||||
set_color(treescrn2, curses.COLOR_WHITE)
|
||||
|
||||
treescrn2.addch(11, 19, ord('\''))
|
||||
treescrn2.addch(11, 18, ord(':'))
|
||||
treescrn2.addch(11, 17, ord('.'))
|
||||
treescrn2.addch(11, 16, ord(','))
|
||||
treescrn2.addch(12, 15, ord('\''))
|
||||
treescrn2.addch(12, 14, ord(':'))
|
||||
treescrn2.addch(12, 13, ord('.'))
|
||||
treescrn2.addch(12, 12, ord(','))
|
||||
|
||||
treescrn2.attroff(curses.A_BOLD | curses.A_BLINK)
|
||||
unset_color(treescrn2)
|
||||
|
||||
# save a fully lit tree
|
||||
treescrn2.overlay(treescrn)
|
||||
|
||||
treescrn2.refresh()
|
||||
w_del_msg.refresh()
|
||||
return
|
||||
|
||||
def blinkit():
|
||||
treescrn8.touchwin()
|
||||
|
||||
for cycle in range(5):
|
||||
if cycle == 0:
|
||||
treescrn3.overlay(treescrn8)
|
||||
treescrn8.refresh()
|
||||
w_del_msg.refresh()
|
||||
break
|
||||
elif cycle == 1:
|
||||
treescrn4.overlay(treescrn8)
|
||||
treescrn8.refresh()
|
||||
w_del_msg.refresh()
|
||||
break
|
||||
elif cycle == 2:
|
||||
treescrn5.overlay(treescrn8)
|
||||
treescrn8.refresh()
|
||||
w_del_msg.refresh()
|
||||
break
|
||||
elif cycle == 3:
|
||||
treescrn6.overlay(treescrn8)
|
||||
treescrn8.refresh()
|
||||
w_del_msg.refresh()
|
||||
break
|
||||
elif cycle == 4:
|
||||
treescrn7.overlay(treescrn8)
|
||||
treescrn8.refresh()
|
||||
w_del_msg.refresh()
|
||||
break
|
||||
|
||||
treescrn8.touchwin()
|
||||
|
||||
# ALL ON
|
||||
treescrn.overlay(treescrn8)
|
||||
treescrn8.refresh()
|
||||
w_del_msg.refresh()
|
||||
|
||||
return
|
||||
|
||||
def deer_step(win, y, x):
|
||||
win.mvwin(y, x)
|
||||
win.refresh()
|
||||
w_del_msg.refresh()
|
||||
look_out(5)
|
||||
|
||||
def reindeer():
|
||||
y_pos = 0
|
||||
|
||||
for x_pos in range(70, 62, -1):
|
||||
if x_pos < 66: y_pos = 1
|
||||
for looper in range(0, 4):
|
||||
dotdeer0.addch(y_pos, x_pos, ord('.'))
|
||||
dotdeer0.refresh()
|
||||
w_del_msg.refresh()
|
||||
dotdeer0.erase()
|
||||
dotdeer0.refresh()
|
||||
w_del_msg.refresh()
|
||||
look_out(50)
|
||||
|
||||
y_pos = 2
|
||||
|
||||
for x_pos in range(x_pos - 1, 50, -1):
|
||||
for looper in range(0, 4):
|
||||
if x_pos < 56:
|
||||
y_pos = 3
|
||||
|
||||
try:
|
||||
stardeer0.addch(y_pos, x_pos, ord('*'))
|
||||
except curses.error:
|
||||
pass
|
||||
stardeer0.refresh()
|
||||
w_del_msg.refresh()
|
||||
stardeer0.erase()
|
||||
stardeer0.refresh()
|
||||
w_del_msg.refresh()
|
||||
else:
|
||||
dotdeer0.addch(y_pos, x_pos, ord('*'))
|
||||
dotdeer0.refresh()
|
||||
w_del_msg.refresh()
|
||||
dotdeer0.erase()
|
||||
dotdeer0.refresh()
|
||||
w_del_msg.refresh()
|
||||
|
||||
x_pos = 58
|
||||
|
||||
for y_pos in range(2, 5):
|
||||
lildeer0.touchwin()
|
||||
lildeer0.refresh()
|
||||
w_del_msg.refresh()
|
||||
|
||||
for looper in range(0, 4):
|
||||
deer_step(lildeer3, y_pos, x_pos)
|
||||
deer_step(lildeer2, y_pos, x_pos)
|
||||
deer_step(lildeer1, y_pos, x_pos)
|
||||
deer_step(lildeer2, y_pos, x_pos)
|
||||
deer_step(lildeer3, y_pos, x_pos)
|
||||
|
||||
lildeer0.touchwin()
|
||||
lildeer0.refresh()
|
||||
w_del_msg.refresh()
|
||||
|
||||
x_pos -= 2
|
||||
|
||||
x_pos = 35
|
||||
|
||||
for y_pos in range(5, 10):
|
||||
|
||||
middeer0.touchwin()
|
||||
middeer0.refresh()
|
||||
w_del_msg.refresh()
|
||||
|
||||
for looper in range(2):
|
||||
deer_step(middeer3, y_pos, x_pos)
|
||||
deer_step(middeer2, y_pos, x_pos)
|
||||
deer_step(middeer1, y_pos, x_pos)
|
||||
deer_step(middeer2, y_pos, x_pos)
|
||||
deer_step(middeer3, y_pos, x_pos)
|
||||
|
||||
middeer0.touchwin()
|
||||
middeer0.refresh()
|
||||
w_del_msg.refresh()
|
||||
|
||||
x_pos -= 3
|
||||
|
||||
look_out(300)
|
||||
|
||||
y_pos = 1
|
||||
|
||||
for x_pos in range(8, 16):
|
||||
deer_step(bigdeer4, y_pos, x_pos)
|
||||
deer_step(bigdeer3, y_pos, x_pos)
|
||||
deer_step(bigdeer2, y_pos, x_pos)
|
||||
deer_step(bigdeer1, y_pos, x_pos)
|
||||
deer_step(bigdeer2, y_pos, x_pos)
|
||||
deer_step(bigdeer3, y_pos, x_pos)
|
||||
deer_step(bigdeer4, y_pos, x_pos)
|
||||
deer_step(bigdeer0, y_pos, x_pos)
|
||||
|
||||
x_pos -= 1
|
||||
|
||||
for looper in range(0, 6):
|
||||
deer_step(lookdeer4, y_pos, x_pos)
|
||||
deer_step(lookdeer3, y_pos, x_pos)
|
||||
deer_step(lookdeer2, y_pos, x_pos)
|
||||
deer_step(lookdeer1, y_pos, x_pos)
|
||||
deer_step(lookdeer2, y_pos, x_pos)
|
||||
deer_step(lookdeer3, y_pos, x_pos)
|
||||
deer_step(lookdeer4, y_pos, x_pos)
|
||||
|
||||
deer_step(lookdeer0, y_pos, x_pos)
|
||||
|
||||
for y_pos in range(y_pos, 10):
|
||||
for looper in range(0, 2):
|
||||
deer_step(bigdeer4, y_pos, x_pos)
|
||||
deer_step(bigdeer3, y_pos, x_pos)
|
||||
deer_step(bigdeer2, y_pos, x_pos)
|
||||
deer_step(bigdeer1, y_pos, x_pos)
|
||||
deer_step(bigdeer2, y_pos, x_pos)
|
||||
deer_step(bigdeer3, y_pos, x_pos)
|
||||
deer_step(bigdeer4, y_pos, x_pos)
|
||||
deer_step(bigdeer0, y_pos, x_pos)
|
||||
|
||||
y_pos -= 1
|
||||
|
||||
deer_step(lookdeer3, y_pos, x_pos)
|
||||
return
|
||||
|
||||
def main(win):
|
||||
global stdscr
|
||||
stdscr = win
|
||||
|
||||
global my_bg, y_pos, x_pos
|
||||
global treescrn, treescrn2, treescrn3, treescrn4
|
||||
global treescrn5, treescrn6, treescrn7, treescrn8
|
||||
global dotdeer0, stardeer0
|
||||
global lildeer0, lildeer1, lildeer2, lildeer3
|
||||
global middeer0, middeer1, middeer2, middeer3
|
||||
global bigdeer0, bigdeer1, bigdeer2, bigdeer3, bigdeer4
|
||||
global lookdeer0, lookdeer1, lookdeer2, lookdeer3, lookdeer4
|
||||
global w_holiday, w_del_msg
|
||||
|
||||
my_bg = curses.COLOR_BLACK
|
||||
# curses.curs_set(0)
|
||||
|
||||
treescrn = curses.newwin(16, 27, 3, 53)
|
||||
treescrn2 = curses.newwin(16, 27, 3, 53)
|
||||
treescrn3 = curses.newwin(16, 27, 3, 53)
|
||||
treescrn4 = curses.newwin(16, 27, 3, 53)
|
||||
treescrn5 = curses.newwin(16, 27, 3, 53)
|
||||
treescrn6 = curses.newwin(16, 27, 3, 53)
|
||||
treescrn7 = curses.newwin(16, 27, 3, 53)
|
||||
treescrn8 = curses.newwin(16, 27, 3, 53)
|
||||
|
||||
dotdeer0 = curses.newwin(3, 71, 0, 8)
|
||||
|
||||
stardeer0 = curses.newwin(4, 56, 0, 8)
|
||||
|
||||
lildeer0 = curses.newwin(7, 53, 0, 8)
|
||||
lildeer1 = curses.newwin(2, 4, 0, 0)
|
||||
lildeer2 = curses.newwin(2, 4, 0, 0)
|
||||
lildeer3 = curses.newwin(2, 4, 0, 0)
|
||||
|
||||
middeer0 = curses.newwin(15, 42, 0, 8)
|
||||
middeer1 = curses.newwin(3, 7, 0, 0)
|
||||
middeer2 = curses.newwin(3, 7, 0, 0)
|
||||
middeer3 = curses.newwin(3, 7, 0, 0)
|
||||
|
||||
bigdeer0 = curses.newwin(10, 23, 0, 0)
|
||||
bigdeer1 = curses.newwin(10, 23, 0, 0)
|
||||
bigdeer2 = curses.newwin(10, 23, 0, 0)
|
||||
bigdeer3 = curses.newwin(10, 23, 0, 0)
|
||||
bigdeer4 = curses.newwin(10, 23, 0, 0)
|
||||
|
||||
lookdeer0 = curses.newwin(10, 25, 0, 0)
|
||||
lookdeer1 = curses.newwin(10, 25, 0, 0)
|
||||
lookdeer2 = curses.newwin(10, 25, 0, 0)
|
||||
lookdeer3 = curses.newwin(10, 25, 0, 0)
|
||||
lookdeer4 = curses.newwin(10, 25, 0, 0)
|
||||
|
||||
w_holiday = curses.newwin(1, 27, 3, 27)
|
||||
|
||||
w_del_msg = curses.newwin(1, 20, 23, 60)
|
||||
|
||||
try:
|
||||
w_del_msg.addstr(0, 0, "Hit any key to quit")
|
||||
except curses.error:
|
||||
pass
|
||||
|
||||
try:
|
||||
w_holiday.addstr(0, 0, "H A P P Y H O L I D A Y S")
|
||||
except curses.error:
|
||||
pass
|
||||
|
||||
# set up the windows for our various reindeer
|
||||
lildeer1.addch(0, 0, ord('V'))
|
||||
lildeer1.addch(1, 0, ord('@'))
|
||||
lildeer1.addch(1, 1, ord('<'))
|
||||
lildeer1.addch(1, 2, ord('>'))
|
||||
try:
|
||||
lildeer1.addch(1, 3, ord('~'))
|
||||
except curses.error:
|
||||
pass
|
||||
|
||||
lildeer2.addch(0, 0, ord('V'))
|
||||
lildeer2.addch(1, 0, ord('@'))
|
||||
lildeer2.addch(1, 1, ord('|'))
|
||||
lildeer2.addch(1, 2, ord('|'))
|
||||
try:
|
||||
lildeer2.addch(1, 3, ord('~'))
|
||||
except curses.error:
|
||||
pass
|
||||
|
||||
lildeer3.addch(0, 0, ord('V'))
|
||||
lildeer3.addch(1, 0, ord('@'))
|
||||
lildeer3.addch(1, 1, ord('>'))
|
||||
lildeer3.addch(1, 2, ord('<'))
|
||||
try:
|
||||
lildeer2.addch(1, 3, ord('~')) # XXX
|
||||
except curses.error:
|
||||
pass
|
||||
|
||||
middeer1.addch(0, 2, ord('y'))
|
||||
middeer1.addch(0, 3, ord('y'))
|
||||
middeer1.addch(1, 2, ord('0'))
|
||||
middeer1.addch(1, 3, ord('('))
|
||||
middeer1.addch(1, 4, ord('='))
|
||||
middeer1.addch(1, 5, ord(')'))
|
||||
middeer1.addch(1, 6, ord('~'))
|
||||
middeer1.addch(2, 3, ord('\\'))
|
||||
middeer1.addch(2, 5, ord('/'))
|
||||
|
||||
middeer2.addch(0, 2, ord('y'))
|
||||
middeer2.addch(0, 3, ord('y'))
|
||||
middeer2.addch(1, 2, ord('0'))
|
||||
middeer2.addch(1, 3, ord('('))
|
||||
middeer2.addch(1, 4, ord('='))
|
||||
middeer2.addch(1, 5, ord(')'))
|
||||
middeer2.addch(1, 6, ord('~'))
|
||||
middeer2.addch(2, 3, ord('|'))
|
||||
middeer2.addch(2, 5, ord('|'))
|
||||
|
||||
middeer3.addch(0, 2, ord('y'))
|
||||
middeer3.addch(0, 3, ord('y'))
|
||||
middeer3.addch(1, 2, ord('0'))
|
||||
middeer3.addch(1, 3, ord('('))
|
||||
middeer3.addch(1, 4, ord('='))
|
||||
middeer3.addch(1, 5, ord(')'))
|
||||
middeer3.addch(1, 6, ord('~'))
|
||||
middeer3.addch(2, 3, ord('/'))
|
||||
middeer3.addch(2, 5, ord('\\'))
|
||||
|
||||
bigdeer1.addch(0, 17, ord('\\'))
|
||||
bigdeer1.addch(0, 18, ord('/'))
|
||||
bigdeer1.addch(0, 19, ord('\\'))
|
||||
bigdeer1.addch(0, 20, ord('/'))
|
||||
bigdeer1.addch(1, 18, ord('\\'))
|
||||
bigdeer1.addch(1, 20, ord('/'))
|
||||
bigdeer1.addch(2, 19, ord('|'))
|
||||
bigdeer1.addch(2, 20, ord('_'))
|
||||
bigdeer1.addch(3, 18, ord('/'))
|
||||
bigdeer1.addch(3, 19, ord('^'))
|
||||
bigdeer1.addch(3, 20, ord('0'))
|
||||
bigdeer1.addch(3, 21, ord('\\'))
|
||||
bigdeer1.addch(4, 17, ord('/'))
|
||||
bigdeer1.addch(4, 18, ord('/'))
|
||||
bigdeer1.addch(4, 19, ord('\\'))
|
||||
bigdeer1.addch(4, 22, ord('\\'))
|
||||
bigdeer1.addstr(5, 7, "^~~~~~~~~// ~~U")
|
||||
bigdeer1.addstr(6, 7, "( \\_____( /") # ))
|
||||
bigdeer1.addstr(7, 8, "( ) /")
|
||||
bigdeer1.addstr(8, 9, "\\\\ /")
|
||||
bigdeer1.addstr(9, 11, "\\>/>")
|
||||
|
||||
bigdeer2.addch(0, 17, ord('\\'))
|
||||
bigdeer2.addch(0, 18, ord('/'))
|
||||
bigdeer2.addch(0, 19, ord('\\'))
|
||||
bigdeer2.addch(0, 20, ord('/'))
|
||||
bigdeer2.addch(1, 18, ord('\\'))
|
||||
bigdeer2.addch(1, 20, ord('/'))
|
||||
bigdeer2.addch(2, 19, ord('|'))
|
||||
bigdeer2.addch(2, 20, ord('_'))
|
||||
bigdeer2.addch(3, 18, ord('/'))
|
||||
bigdeer2.addch(3, 19, ord('^'))
|
||||
bigdeer2.addch(3, 20, ord('0'))
|
||||
bigdeer2.addch(3, 21, ord('\\'))
|
||||
bigdeer2.addch(4, 17, ord('/'))
|
||||
bigdeer2.addch(4, 18, ord('/'))
|
||||
bigdeer2.addch(4, 19, ord('\\'))
|
||||
bigdeer2.addch(4, 22, ord('\\'))
|
||||
bigdeer2.addstr(5, 7, "^~~~~~~~~// ~~U")
|
||||
bigdeer2.addstr(6, 7, "(( )____( /") # ))
|
||||
bigdeer2.addstr(7, 7, "( / |")
|
||||
bigdeer2.addstr(8, 8, "\\/ |")
|
||||
bigdeer2.addstr(9, 9, "|> |>")
|
||||
|
||||
bigdeer3.addch(0, 17, ord('\\'))
|
||||
bigdeer3.addch(0, 18, ord('/'))
|
||||
bigdeer3.addch(0, 19, ord('\\'))
|
||||
bigdeer3.addch(0, 20, ord('/'))
|
||||
bigdeer3.addch(1, 18, ord('\\'))
|
||||
bigdeer3.addch(1, 20, ord('/'))
|
||||
bigdeer3.addch(2, 19, ord('|'))
|
||||
bigdeer3.addch(2, 20, ord('_'))
|
||||
bigdeer3.addch(3, 18, ord('/'))
|
||||
bigdeer3.addch(3, 19, ord('^'))
|
||||
bigdeer3.addch(3, 20, ord('0'))
|
||||
bigdeer3.addch(3, 21, ord('\\'))
|
||||
bigdeer3.addch(4, 17, ord('/'))
|
||||
bigdeer3.addch(4, 18, ord('/'))
|
||||
bigdeer3.addch(4, 19, ord('\\'))
|
||||
bigdeer3.addch(4, 22, ord('\\'))
|
||||
bigdeer3.addstr(5, 7, "^~~~~~~~~// ~~U")
|
||||
bigdeer3.addstr(6, 6, "( ()_____( /") # ))
|
||||
bigdeer3.addstr(7, 6, "/ / /")
|
||||
bigdeer3.addstr(8, 5, "|/ \\")
|
||||
bigdeer3.addstr(9, 5, "/> \\>")
|
||||
|
||||
bigdeer4.addch(0, 17, ord('\\'))
|
||||
bigdeer4.addch(0, 18, ord('/'))
|
||||
bigdeer4.addch(0, 19, ord('\\'))
|
||||
bigdeer4.addch(0, 20, ord('/'))
|
||||
bigdeer4.addch(1, 18, ord('\\'))
|
||||
bigdeer4.addch(1, 20, ord('/'))
|
||||
bigdeer4.addch(2, 19, ord('|'))
|
||||
bigdeer4.addch(2, 20, ord('_'))
|
||||
bigdeer4.addch(3, 18, ord('/'))
|
||||
bigdeer4.addch(3, 19, ord('^'))
|
||||
bigdeer4.addch(3, 20, ord('0'))
|
||||
bigdeer4.addch(3, 21, ord('\\'))
|
||||
bigdeer4.addch(4, 17, ord('/'))
|
||||
bigdeer4.addch(4, 18, ord('/'))
|
||||
bigdeer4.addch(4, 19, ord('\\'))
|
||||
bigdeer4.addch(4, 22, ord('\\'))
|
||||
bigdeer4.addstr(5, 7, "^~~~~~~~~// ~~U")
|
||||
bigdeer4.addstr(6, 6, "( )______( /") # )
|
||||
bigdeer4.addstr(7, 5, "(/ \\") # )
|
||||
bigdeer4.addstr(8, 0, "v___= ----^")
|
||||
|
||||
lookdeer1.addstr(0, 16, "\\/ \\/")
|
||||
lookdeer1.addstr(1, 17, "\\Y/ \\Y/")
|
||||
lookdeer1.addstr(2, 19, "\\=/")
|
||||
lookdeer1.addstr(3, 17, "^\\o o/^")
|
||||
lookdeer1.addstr(4, 17, "//( )")
|
||||
lookdeer1.addstr(5, 7, "^~~~~~~~~// \\O/")
|
||||
lookdeer1.addstr(6, 7, "( \\_____( /") # ))
|
||||
lookdeer1.addstr(7, 8, "( ) /")
|
||||
lookdeer1.addstr(8, 9, "\\\\ /")
|
||||
lookdeer1.addstr(9, 11, "\\>/>")
|
||||
|
||||
lookdeer2.addstr(0, 16, "\\/ \\/")
|
||||
lookdeer2.addstr(1, 17, "\\Y/ \\Y/")
|
||||
lookdeer2.addstr(2, 19, "\\=/")
|
||||
lookdeer2.addstr(3, 17, "^\\o o/^")
|
||||
lookdeer2.addstr(4, 17, "//( )")
|
||||
lookdeer2.addstr(5, 7, "^~~~~~~~~// \\O/")
|
||||
lookdeer2.addstr(6, 7, "(( )____( /") # ))
|
||||
lookdeer2.addstr(7, 7, "( / |")
|
||||
lookdeer2.addstr(8, 8, "\\/ |")
|
||||
lookdeer2.addstr(9, 9, "|> |>")
|
||||
|
||||
lookdeer3.addstr(0, 16, "\\/ \\/")
|
||||
lookdeer3.addstr(1, 17, "\\Y/ \\Y/")
|
||||
lookdeer3.addstr(2, 19, "\\=/")
|
||||
lookdeer3.addstr(3, 17, "^\\o o/^")
|
||||
lookdeer3.addstr(4, 17, "//( )")
|
||||
lookdeer3.addstr(5, 7, "^~~~~~~~~// \\O/")
|
||||
lookdeer3.addstr(6, 6, "( ()_____( /") # ))
|
||||
lookdeer3.addstr(7, 6, "/ / /")
|
||||
lookdeer3.addstr(8, 5, "|/ \\")
|
||||
lookdeer3.addstr(9, 5, "/> \\>")
|
||||
|
||||
lookdeer4.addstr(0, 16, "\\/ \\/")
|
||||
lookdeer4.addstr(1, 17, "\\Y/ \\Y/")
|
||||
lookdeer4.addstr(2, 19, "\\=/")
|
||||
lookdeer4.addstr(3, 17, "^\\o o/^")
|
||||
lookdeer4.addstr(4, 17, "//( )")
|
||||
lookdeer4.addstr(5, 7, "^~~~~~~~~// \\O/")
|
||||
lookdeer4.addstr(6, 6, "( )______( /") # )
|
||||
lookdeer4.addstr(7, 5, "(/ \\") # )
|
||||
lookdeer4.addstr(8, 0, "v___= ----^")
|
||||
|
||||
###############################################
|
||||
curses.cbreak()
|
||||
stdscr.nodelay(1)
|
||||
|
||||
while 1:
|
||||
stdscr.clear()
|
||||
treescrn.erase()
|
||||
w_del_msg.touchwin()
|
||||
treescrn.touchwin()
|
||||
treescrn2.erase()
|
||||
treescrn2.touchwin()
|
||||
treescrn8.erase()
|
||||
treescrn8.touchwin()
|
||||
stdscr.refresh()
|
||||
look_out(150)
|
||||
boxit()
|
||||
stdscr.refresh()
|
||||
look_out(150)
|
||||
seas()
|
||||
stdscr.refresh()
|
||||
greet()
|
||||
stdscr.refresh()
|
||||
look_out(150)
|
||||
fromwho()
|
||||
stdscr.refresh()
|
||||
look_out(150)
|
||||
tree()
|
||||
look_out(150)
|
||||
balls()
|
||||
look_out(150)
|
||||
star()
|
||||
look_out(150)
|
||||
strng1()
|
||||
strng2()
|
||||
strng3()
|
||||
strng4()
|
||||
strng5()
|
||||
|
||||
# set up the windows for our blinking trees
|
||||
#
|
||||
# treescrn3
|
||||
treescrn.overlay(treescrn3)
|
||||
|
||||
# balls
|
||||
treescrn3.addch(4, 18, ord(' '))
|
||||
treescrn3.addch(7, 6, ord(' '))
|
||||
treescrn3.addch(8, 19, ord(' '))
|
||||
treescrn3.addch(11, 22, ord(' '))
|
||||
|
||||
# star
|
||||
treescrn3.addch(0, 12, ord('*'))
|
||||
|
||||
# strng1
|
||||
treescrn3.addch(3, 11, ord(' '))
|
||||
|
||||
# strng2
|
||||
treescrn3.addch(5, 13, ord(' '))
|
||||
treescrn3.addch(6, 10, ord(' '))
|
||||
|
||||
# strng3
|
||||
treescrn3.addch(7, 16, ord(' '))
|
||||
treescrn3.addch(7, 14, ord(' '))
|
||||
|
||||
# strng4
|
||||
treescrn3.addch(10, 13, ord(' '))
|
||||
treescrn3.addch(10, 10, ord(' '))
|
||||
treescrn3.addch(11, 8, ord(' '))
|
||||
|
||||
# strng5
|
||||
treescrn3.addch(11, 18, ord(' '))
|
||||
treescrn3.addch(12, 13, ord(' '))
|
||||
|
||||
# treescrn4
|
||||
treescrn.overlay(treescrn4)
|
||||
|
||||
# balls
|
||||
treescrn4.addch(3, 9, ord(' '))
|
||||
treescrn4.addch(4, 16, ord(' '))
|
||||
treescrn4.addch(7, 6, ord(' '))
|
||||
treescrn4.addch(8, 19, ord(' '))
|
||||
treescrn4.addch(11, 2, ord(' '))
|
||||
treescrn4.addch(12, 23, ord(' '))
|
||||
|
||||
# star
|
||||
treescrn4.standout()
|
||||
treescrn4.addch(0, 12, ord('*'))
|
||||
treescrn4.standend()
|
||||
|
||||
# strng1
|
||||
treescrn4.addch(3, 13, ord(' '))
|
||||
|
||||
# strng2
|
||||
|
||||
# strng3
|
||||
treescrn4.addch(7, 15, ord(' '))
|
||||
treescrn4.addch(8, 11, ord(' '))
|
||||
|
||||
# strng4
|
||||
treescrn4.addch(9, 16, ord(' '))
|
||||
treescrn4.addch(10, 12, ord(' '))
|
||||
treescrn4.addch(11, 8, ord(' '))
|
||||
|
||||
# strng5
|
||||
treescrn4.addch(11, 18, ord(' '))
|
||||
treescrn4.addch(12, 14, ord(' '))
|
||||
|
||||
# treescrn5
|
||||
treescrn.overlay(treescrn5)
|
||||
|
||||
# balls
|
||||
treescrn5.addch(3, 15, ord(' '))
|
||||
treescrn5.addch(10, 20, ord(' '))
|
||||
treescrn5.addch(12, 1, ord(' '))
|
||||
|
||||
# star
|
||||
treescrn5.addch(0, 12, ord(' '))
|
||||
|
||||
# strng1
|
||||
treescrn5.addch(3, 11, ord(' '))
|
||||
|
||||
# strng2
|
||||
treescrn5.addch(5, 12, ord(' '))
|
||||
|
||||
# strng3
|
||||
treescrn5.addch(7, 14, ord(' '))
|
||||
treescrn5.addch(8, 10, ord(' '))
|
||||
|
||||
# strng4
|
||||
treescrn5.addch(9, 15, ord(' '))
|
||||
treescrn5.addch(10, 11, ord(' '))
|
||||
treescrn5.addch(11, 7, ord(' '))
|
||||
|
||||
# strng5
|
||||
treescrn5.addch(11, 17, ord(' '))
|
||||
treescrn5.addch(12, 13, ord(' '))
|
||||
|
||||
# treescrn6
|
||||
treescrn.overlay(treescrn6)
|
||||
|
||||
# balls
|
||||
treescrn6.addch(6, 7, ord(' '))
|
||||
treescrn6.addch(7, 18, ord(' '))
|
||||
treescrn6.addch(10, 4, ord(' '))
|
||||
treescrn6.addch(11, 23, ord(' '))
|
||||
|
||||
# star
|
||||
treescrn6.standout()
|
||||
treescrn6.addch(0, 12, ord('*'))
|
||||
treescrn6.standend()
|
||||
|
||||
# strng1
|
||||
|
||||
# strng2
|
||||
treescrn6.addch(5, 11, ord(' '))
|
||||
|
||||
# strng3
|
||||
treescrn6.addch(7, 13, ord(' '))
|
||||
treescrn6.addch(8, 9, ord(' '))
|
||||
|
||||
# strng4
|
||||
treescrn6.addch(9, 14, ord(' '))
|
||||
treescrn6.addch(10, 10, ord(' '))
|
||||
treescrn6.addch(11, 6, ord(' '))
|
||||
|
||||
# strng5
|
||||
treescrn6.addch(11, 16, ord(' '))
|
||||
treescrn6.addch(12, 12, ord(' '))
|
||||
|
||||
# treescrn7
|
||||
|
||||
treescrn.overlay(treescrn7)
|
||||
|
||||
# balls
|
||||
treescrn7.addch(3, 15, ord(' '))
|
||||
treescrn7.addch(6, 7, ord(' '))
|
||||
treescrn7.addch(7, 18, ord(' '))
|
||||
treescrn7.addch(10, 4, ord(' '))
|
||||
treescrn7.addch(11, 22, ord(' '))
|
||||
|
||||
# star
|
||||
treescrn7.addch(0, 12, ord('*'))
|
||||
|
||||
# strng1
|
||||
treescrn7.addch(3, 12, ord(' '))
|
||||
|
||||
# strng2
|
||||
treescrn7.addch(5, 13, ord(' '))
|
||||
treescrn7.addch(6, 9, ord(' '))
|
||||
|
||||
# strng3
|
||||
treescrn7.addch(7, 15, ord(' '))
|
||||
treescrn7.addch(8, 11, ord(' '))
|
||||
|
||||
# strng4
|
||||
treescrn7.addch(9, 16, ord(' '))
|
||||
treescrn7.addch(10, 12, ord(' '))
|
||||
treescrn7.addch(11, 8, ord(' '))
|
||||
|
||||
# strng5
|
||||
treescrn7.addch(11, 18, ord(' '))
|
||||
treescrn7.addch(12, 14, ord(' '))
|
||||
|
||||
look_out(150)
|
||||
reindeer()
|
||||
|
||||
w_holiday.touchwin()
|
||||
w_holiday.refresh()
|
||||
w_del_msg.refresh()
|
||||
|
||||
look_out(500)
|
||||
for i in range(0, 20):
|
||||
blinkit()
|
||||
|
||||
curses.wrapper(main)
|
57
2.7/Python-2.7.16/Demo/embed/Makefile
Normal file
57
2.7/Python-2.7.16/Demo/embed/Makefile
Normal file
@ -0,0 +1,57 @@
|
||||
# Makefile for embedded Python use demo.
|
||||
# (This version originally written on Red Hat Linux 6.1;
|
||||
# edit lines marked with XXX.)
|
||||
|
||||
# XXX The compiler you are using
|
||||
CC= gcc
|
||||
|
||||
# XXX Top of the build tree and source tree
|
||||
blddir= ../..
|
||||
srcdir= ../..
|
||||
|
||||
# Python version
|
||||
VERSION= 2.7
|
||||
|
||||
# Compiler flags
|
||||
OPT= -g
|
||||
INCLUDES= -I$(srcdir)/Include -I$(blddir)
|
||||
CFLAGS= $(OPT)
|
||||
CPPFLAGS= $(INCLUDES)
|
||||
|
||||
# The Python library
|
||||
LIBPYTHON= $(blddir)/libpython$(VERSION).a
|
||||
|
||||
# XXX edit LIBS (in particular) to match $(blddir)/Makefile
|
||||
LIBS= -lnsl -ldl -lreadline -ltermcap -lieee -lpthread -lutil
|
||||
LDFLAGS= -Xlinker -export-dynamic
|
||||
SYSLIBS= -lm
|
||||
MODLIBS=
|
||||
ALLLIBS= $(LIBPYTHON) $(MODLIBS) $(LIBS) $(SYSLIBS)
|
||||
|
||||
# Build the demo applications
|
||||
all: demo loop importexc
|
||||
demo: demo.o
|
||||
$(CC) $(LDFLAGS) demo.o $(ALLLIBS) -o demo
|
||||
|
||||
loop: loop.o
|
||||
$(CC) $(LDFLAGS) loop.o $(ALLLIBS) -o loop
|
||||
|
||||
importexc: importexc.o
|
||||
$(CC) $(LDFLAGS) importexc.o $(ALLLIBS) -o importexc
|
||||
|
||||
# Administrative targets
|
||||
|
||||
test: demo
|
||||
./demo
|
||||
|
||||
COMMAND="print 'hello world'"
|
||||
looptest: loop
|
||||
./loop $(COMMAND)
|
||||
|
||||
clean:
|
||||
-rm -f *.o core
|
||||
|
||||
clobber: clean
|
||||
-rm -f *~ @* '#'* demo loop importexc
|
||||
|
||||
realclean: clobber
|
19
2.7/Python-2.7.16/Demo/embed/README
Normal file
19
2.7/Python-2.7.16/Demo/embed/README
Normal file
@ -0,0 +1,19 @@
|
||||
This directory show how to embed the Python interpreter in your own
|
||||
application. The file demo.c shows you all that is needed in your C
|
||||
code.
|
||||
|
||||
To build it, you may have to edit the Makefile:
|
||||
|
||||
1) set blddir to the directory where you built Python, if it isn't in
|
||||
the source directory (../..)
|
||||
|
||||
2) change the variables that together define the list of libraries
|
||||
(MODLIBS, LIBS, SYSLIBS) to link with, to match their definitions in
|
||||
$(blddir)/Modules/Makefile
|
||||
|
||||
An additional test program, loop.c, is used to experiment with memory
|
||||
leakage caused by repeated initialization and finalization of the
|
||||
interpreter. It can be build by saying "make loop" and tested with
|
||||
"make looptest". Command line usage is "./loop <python-command>",
|
||||
e.g. "./loop 'print 2+2'" should spit out an endless number of lines
|
||||
containing the number 4.
|
74
2.7/Python-2.7.16/Demo/embed/demo.c
Normal file
74
2.7/Python-2.7.16/Demo/embed/demo.c
Normal file
@ -0,0 +1,74 @@
|
||||
/* Example of embedding Python in another program */
|
||||
|
||||
#include "Python.h"
|
||||
|
||||
void initxyzzy(void); /* Forward */
|
||||
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
/* Pass argv[0] to the Python interpreter */
|
||||
Py_SetProgramName(argv[0]);
|
||||
|
||||
/* Initialize the Python interpreter. Required. */
|
||||
Py_Initialize();
|
||||
|
||||
/* Add a static module */
|
||||
initxyzzy();
|
||||
|
||||
/* Define sys.argv. It is up to the application if you
|
||||
want this; you can also leave it undefined (since the Python
|
||||
code is generally not a main program it has no business
|
||||
touching sys.argv...)
|
||||
|
||||
If the third argument is true, sys.path is modified to include
|
||||
either the directory containing the script named by argv[0], or
|
||||
the current working directory. This can be risky; if you run
|
||||
an application embedding Python in a directory controlled by
|
||||
someone else, attackers could put a Trojan-horse module in the
|
||||
directory (say, a file named os.py) that your application would
|
||||
then import and run.
|
||||
*/
|
||||
PySys_SetArgvEx(argc, argv, 0);
|
||||
|
||||
/* Do some application specific code */
|
||||
printf("Hello, brave new world\n\n");
|
||||
|
||||
/* Execute some Python statements (in module __main__) */
|
||||
PyRun_SimpleString("import sys\n");
|
||||
PyRun_SimpleString("print sys.builtin_module_names\n");
|
||||
PyRun_SimpleString("print sys.modules.keys()\n");
|
||||
PyRun_SimpleString("print sys.executable\n");
|
||||
PyRun_SimpleString("print sys.argv\n");
|
||||
|
||||
/* Note that you can call any public function of the Python
|
||||
interpreter here, e.g. call_object(). */
|
||||
|
||||
/* Some more application specific code */
|
||||
printf("\nGoodbye, cruel world\n");
|
||||
|
||||
/* Exit, cleaning up the interpreter */
|
||||
Py_Exit(0);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/* A static module */
|
||||
|
||||
/* 'self' is not used */
|
||||
static PyObject *
|
||||
xyzzy_foo(PyObject *self, PyObject* args)
|
||||
{
|
||||
return PyInt_FromLong(42L);
|
||||
}
|
||||
|
||||
static PyMethodDef xyzzy_methods[] = {
|
||||
{"foo", xyzzy_foo, METH_NOARGS,
|
||||
"Return the meaning of everything."},
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
void
|
||||
initxyzzy(void)
|
||||
{
|
||||
PyImport_AddModule("xyzzy");
|
||||
Py_InitModule("xyzzy", xyzzy_methods);
|
||||
}
|
17
2.7/Python-2.7.16/Demo/embed/importexc.c
Normal file
17
2.7/Python-2.7.16/Demo/embed/importexc.c
Normal file
@ -0,0 +1,17 @@
|
||||
#include <Python.h>
|
||||
|
||||
char* cmd = "import exceptions";
|
||||
|
||||
int main()
|
||||
{
|
||||
Py_Initialize();
|
||||
PyEval_InitThreads();
|
||||
PyRun_SimpleString(cmd);
|
||||
Py_EndInterpreter(PyThreadState_Get());
|
||||
|
||||
Py_NewInterpreter();
|
||||
PyRun_SimpleString(cmd);
|
||||
Py_Finalize();
|
||||
|
||||
return 0;
|
||||
}
|
33
2.7/Python-2.7.16/Demo/embed/loop.c
Normal file
33
2.7/Python-2.7.16/Demo/embed/loop.c
Normal file
@ -0,0 +1,33 @@
|
||||
/* Simple program that repeatedly calls Py_Initialize(), does something, and
|
||||
then calls Py_Finalize(). This should help finding leaks related to
|
||||
initialization. */
|
||||
|
||||
#include "Python.h"
|
||||
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int count = -1;
|
||||
char *command;
|
||||
|
||||
if (argc < 2 || argc > 3) {
|
||||
fprintf(stderr, "usage: loop <python-command> [count]\n");
|
||||
exit(2);
|
||||
}
|
||||
command = argv[1];
|
||||
|
||||
if (argc == 3) {
|
||||
count = atoi(argv[2]);
|
||||
}
|
||||
|
||||
Py_SetProgramName(argv[0]);
|
||||
|
||||
/* uncomment this if you don't want to load site.py */
|
||||
/* Py_NoSiteFlag = 1; */
|
||||
|
||||
while (count == -1 || --count >= 0 ) {
|
||||
Py_Initialize();
|
||||
PyRun_SimpleString(command);
|
||||
Py_Finalize();
|
||||
}
|
||||
return 0;
|
||||
}
|
10
2.7/Python-2.7.16/Demo/md5test/README
Normal file
10
2.7/Python-2.7.16/Demo/md5test/README
Normal file
@ -0,0 +1,10 @@
|
||||
This is the Python version of the MD5 test program from the MD5
|
||||
Internet Draft (Rivest and Dusse, The MD5 Message-Digest Algorithm, 10
|
||||
July 1991). The file "foo" contains the string "abc" with no trailing
|
||||
newline.
|
||||
|
||||
When called without arguments, it acts as a filter. When called with
|
||||
"-x", it executes a self-test, and the output should literally match
|
||||
the output given in the RFC.
|
||||
|
||||
Code by Jan-Hein B\"uhrman after the original in C.
|
1
2.7/Python-2.7.16/Demo/md5test/foo
Normal file
1
2.7/Python-2.7.16/Demo/md5test/foo
Normal file
@ -0,0 +1 @@
|
||||
abc
|
123
2.7/Python-2.7.16/Demo/md5test/md5driver.py
Normal file
123
2.7/Python-2.7.16/Demo/md5test/md5driver.py
Normal file
@ -0,0 +1,123 @@
|
||||
import string
|
||||
import md5
|
||||
from sys import argv
|
||||
|
||||
def MDPrint(str):
|
||||
outstr = ''
|
||||
for i in str:
|
||||
o = ord(i)
|
||||
outstr = (outstr
|
||||
+ string.hexdigits[(o >> 4) & 0xF]
|
||||
+ string.hexdigits[o & 0xF])
|
||||
print outstr,
|
||||
|
||||
|
||||
from time import time
|
||||
|
||||
def makestr(start, end):
|
||||
result = ''
|
||||
for i in range(start, end + 1):
|
||||
result = result + chr(i)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def MDTimeTrial():
|
||||
TEST_BLOCK_SIZE = 1000
|
||||
TEST_BLOCKS = 10000
|
||||
|
||||
TEST_BYTES = TEST_BLOCK_SIZE * TEST_BLOCKS
|
||||
|
||||
# initialize test data, need temporary string filler
|
||||
|
||||
filsiz = 1 << 8
|
||||
filler = makestr(0, filsiz-1)
|
||||
data = filler * (TEST_BLOCK_SIZE // filsiz)
|
||||
data = data + filler[:(TEST_BLOCK_SIZE % filsiz)]
|
||||
|
||||
del filsiz, filler
|
||||
|
||||
|
||||
# start timer
|
||||
print 'MD5 time trial. Processing', TEST_BYTES, 'characters...'
|
||||
t1 = time()
|
||||
|
||||
mdContext = md5.new()
|
||||
|
||||
for i in range(TEST_BLOCKS):
|
||||
mdContext.update(data)
|
||||
|
||||
str = mdContext.digest()
|
||||
t2 = time()
|
||||
|
||||
MDPrint(str)
|
||||
print 'is digest of test input.'
|
||||
print 'Seconds to process test input:', t2 - t1
|
||||
print 'Characters processed per second:', TEST_BYTES / (t2 - t1)
|
||||
|
||||
|
||||
def MDString(str):
|
||||
MDPrint(md5.new(str).digest())
|
||||
print '"' + str + '"'
|
||||
|
||||
|
||||
def MDFile(filename):
|
||||
f = open(filename, 'rb')
|
||||
mdContext = md5.new()
|
||||
|
||||
while 1:
|
||||
data = f.read(1024)
|
||||
if not data:
|
||||
break
|
||||
mdContext.update(data)
|
||||
|
||||
MDPrint(mdContext.digest())
|
||||
print filename
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
def MDFilter():
|
||||
mdContext = md5.new()
|
||||
|
||||
while 1:
|
||||
data = sys.stdin.read(16)
|
||||
if not data:
|
||||
break
|
||||
mdContext.update(data)
|
||||
|
||||
MDPrint(mdContext.digest())
|
||||
print
|
||||
|
||||
|
||||
def MDTestSuite():
|
||||
print 'MD5 test suite results:'
|
||||
MDString('')
|
||||
MDString('a')
|
||||
MDString('abc')
|
||||
MDString('message digest')
|
||||
MDString(makestr(ord('a'), ord('z')))
|
||||
MDString(makestr(ord('A'), ord('Z'))
|
||||
+ makestr(ord('a'), ord('z'))
|
||||
+ makestr(ord('0'), ord('9')))
|
||||
MDString((makestr(ord('1'), ord('9')) + '0') * 8)
|
||||
|
||||
# Contents of file foo are "abc"
|
||||
MDFile('foo')
|
||||
|
||||
|
||||
# I don't wanna use getopt(), since I want to use the same i/f...
|
||||
def main():
|
||||
if len(argv) == 1:
|
||||
MDFilter()
|
||||
for arg in argv[1:]:
|
||||
if arg[:2] == '-s':
|
||||
MDString(arg[2:])
|
||||
elif arg == '-t':
|
||||
MDTimeTrial()
|
||||
elif arg == '-x':
|
||||
MDTestSuite()
|
||||
else:
|
||||
MDFile(arg)
|
||||
|
||||
main()
|
113
2.7/Python-2.7.16/Demo/metaclasses/Eiffel.py
Normal file
113
2.7/Python-2.7.16/Demo/metaclasses/Eiffel.py
Normal file
@ -0,0 +1,113 @@
|
||||
"""Support Eiffel-style preconditions and postconditions.
|
||||
|
||||
For example,
|
||||
|
||||
class C:
|
||||
def m1(self, arg):
|
||||
require arg > 0
|
||||
return whatever
|
||||
ensure Result > arg
|
||||
|
||||
can be written (clumsily, I agree) as:
|
||||
|
||||
class C(Eiffel):
|
||||
def m1(self, arg):
|
||||
return whatever
|
||||
def m1_pre(self, arg):
|
||||
assert arg > 0
|
||||
def m1_post(self, Result, arg):
|
||||
assert Result > arg
|
||||
|
||||
Pre- and post-conditions for a method, being implemented as methods
|
||||
themselves, are inherited independently from the method. This gives
|
||||
much of the same effect of Eiffel, where pre- and post-conditions are
|
||||
inherited when a method is overridden by a derived class. However,
|
||||
when a derived class in Python needs to extend a pre- or
|
||||
post-condition, it must manually merge the base class' pre- or
|
||||
post-condition with that defined in the derived class', for example:
|
||||
|
||||
class D(C):
|
||||
def m1(self, arg):
|
||||
return arg**2
|
||||
def m1_post(self, Result, arg):
|
||||
C.m1_post(self, Result, arg)
|
||||
assert Result < 100
|
||||
|
||||
This gives derived classes more freedom but also more responsibility
|
||||
than in Eiffel, where the compiler automatically takes care of this.
|
||||
|
||||
In Eiffel, pre-conditions combine using contravariance, meaning a
|
||||
derived class can only make a pre-condition weaker; in Python, this is
|
||||
up to the derived class. For example, a derived class that takes away
|
||||
the requirement that arg > 0 could write:
|
||||
|
||||
def m1_pre(self, arg):
|
||||
pass
|
||||
|
||||
but one could equally write a derived class that makes a stronger
|
||||
requirement:
|
||||
|
||||
def m1_pre(self, arg):
|
||||
require arg > 50
|
||||
|
||||
It would be easy to modify the classes shown here so that pre- and
|
||||
post-conditions can be disabled (separately, on a per-class basis).
|
||||
|
||||
A different design would have the pre- or post-condition testing
|
||||
functions return true for success and false for failure. This would
|
||||
make it possible to implement automatic combination of inherited
|
||||
and new pre-/post-conditions. All this is left as an exercise to the
|
||||
reader.
|
||||
|
||||
"""
|
||||
|
||||
from Meta import MetaClass, MetaHelper, MetaMethodWrapper
|
||||
|
||||
class EiffelMethodWrapper(MetaMethodWrapper):
|
||||
|
||||
def __init__(self, func, inst):
|
||||
MetaMethodWrapper.__init__(self, func, inst)
|
||||
# Note that the following causes recursive wrappers around
|
||||
# the pre-/post-condition testing methods. These are harmless
|
||||
# but inefficient; to avoid them, the lookup must be done
|
||||
# using the class.
|
||||
try:
|
||||
self.pre = getattr(inst, self.__name__ + "_pre")
|
||||
except AttributeError:
|
||||
self.pre = None
|
||||
try:
|
||||
self.post = getattr(inst, self.__name__ + "_post")
|
||||
except AttributeError:
|
||||
self.post = None
|
||||
|
||||
def __call__(self, *args, **kw):
|
||||
if self.pre:
|
||||
apply(self.pre, args, kw)
|
||||
Result = apply(self.func, (self.inst,) + args, kw)
|
||||
if self.post:
|
||||
apply(self.post, (Result,) + args, kw)
|
||||
return Result
|
||||
|
||||
class EiffelHelper(MetaHelper):
|
||||
__methodwrapper__ = EiffelMethodWrapper
|
||||
|
||||
class EiffelMetaClass(MetaClass):
|
||||
__helper__ = EiffelHelper
|
||||
|
||||
Eiffel = EiffelMetaClass('Eiffel', (), {})
|
||||
|
||||
|
||||
def _test():
|
||||
class C(Eiffel):
|
||||
def m1(self, arg):
|
||||
return arg+1
|
||||
def m1_pre(self, arg):
|
||||
assert arg > 0, "precondition for m1 failed"
|
||||
def m1_post(self, Result, arg):
|
||||
assert Result > arg
|
||||
x = C()
|
||||
x.m1(12)
|
||||
## x.m1(-1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
_test()
|
169
2.7/Python-2.7.16/Demo/metaclasses/Enum.py
Normal file
169
2.7/Python-2.7.16/Demo/metaclasses/Enum.py
Normal file
@ -0,0 +1,169 @@
|
||||
"""Enumeration metaclass.
|
||||
|
||||
XXX This is very much a work in progress.
|
||||
|
||||
"""
|
||||
|
||||
import string
|
||||
|
||||
class EnumMetaClass:
|
||||
"""Metaclass for enumeration.
|
||||
|
||||
To define your own enumeration, do something like
|
||||
|
||||
class Color(Enum):
|
||||
red = 1
|
||||
green = 2
|
||||
blue = 3
|
||||
|
||||
Now, Color.red, Color.green and Color.blue behave totally
|
||||
different: they are enumerated values, not integers.
|
||||
|
||||
Enumerations cannot be instantiated; however they can be
|
||||
subclassed.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, name, bases, dict):
|
||||
"""Constructor -- create an enumeration.
|
||||
|
||||
Called at the end of the class statement. The arguments are
|
||||
the name of the new class, a tuple containing the base
|
||||
classes, and a dictionary containing everything that was
|
||||
entered in the class' namespace during execution of the class
|
||||
statement. In the above example, it would be {'red': 1,
|
||||
'green': 2, 'blue': 3}.
|
||||
|
||||
"""
|
||||
for base in bases:
|
||||
if base.__class__ is not EnumMetaClass:
|
||||
raise TypeError, "Enumeration base class must be enumeration"
|
||||
bases = filter(lambda x: x is not Enum, bases)
|
||||
self.__name__ = name
|
||||
self.__bases__ = bases
|
||||
self.__dict = {}
|
||||
for key, value in dict.items():
|
||||
self.__dict[key] = EnumInstance(name, key, value)
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""Return an enumeration value.
|
||||
|
||||
For example, Color.red returns the value corresponding to red.
|
||||
|
||||
XXX Perhaps the values should be created in the constructor?
|
||||
|
||||
This looks in the class dictionary and if it is not found
|
||||
there asks the base classes.
|
||||
|
||||
The special attribute __members__ returns the list of names
|
||||
defined in this class (it does not merge in the names defined
|
||||
in base classes).
|
||||
|
||||
"""
|
||||
if name == '__members__':
|
||||
return self.__dict.keys()
|
||||
|
||||
try:
|
||||
return self.__dict[name]
|
||||
except KeyError:
|
||||
for base in self.__bases__:
|
||||
try:
|
||||
return getattr(base, name)
|
||||
except AttributeError:
|
||||
continue
|
||||
|
||||
raise AttributeError, name
|
||||
|
||||
def __repr__(self):
|
||||
s = self.__name__
|
||||
if self.__bases__:
|
||||
s = s + '(' + string.join(map(lambda x: x.__name__,
|
||||
self.__bases__), ", ") + ')'
|
||||
if self.__dict:
|
||||
list = []
|
||||
for key, value in self.__dict.items():
|
||||
list.append("%s: %s" % (key, int(value)))
|
||||
s = "%s: {%s}" % (s, string.join(list, ", "))
|
||||
return s
|
||||
|
||||
|
||||
class EnumInstance:
|
||||
"""Class to represent an enumeration value.
|
||||
|
||||
EnumInstance('Color', 'red', 12) prints as 'Color.red' and behaves
|
||||
like the integer 12 when compared, but doesn't support arithmetic.
|
||||
|
||||
XXX Should it record the actual enumeration rather than just its
|
||||
name?
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, classname, enumname, value):
|
||||
self.__classname = classname
|
||||
self.__enumname = enumname
|
||||
self.__value = value
|
||||
|
||||
def __int__(self):
|
||||
return self.__value
|
||||
|
||||
def __repr__(self):
|
||||
return "EnumInstance(%r, %r, %r)" % (self.__classname,
|
||||
self.__enumname,
|
||||
self.__value)
|
||||
|
||||
def __str__(self):
|
||||
return "%s.%s" % (self.__classname, self.__enumname)
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.__value, int(other))
|
||||
|
||||
|
||||
# Create the base class for enumerations.
|
||||
# It is an empty enumeration.
|
||||
Enum = EnumMetaClass("Enum", (), {})
|
||||
|
||||
|
||||
def _test():
|
||||
|
||||
class Color(Enum):
|
||||
red = 1
|
||||
green = 2
|
||||
blue = 3
|
||||
|
||||
print Color.red
|
||||
print dir(Color)
|
||||
|
||||
print Color.red == Color.red
|
||||
print Color.red == Color.blue
|
||||
print Color.red == 1
|
||||
print Color.red == 2
|
||||
|
||||
class ExtendedColor(Color):
|
||||
white = 0
|
||||
orange = 4
|
||||
yellow = 5
|
||||
purple = 6
|
||||
black = 7
|
||||
|
||||
print ExtendedColor.orange
|
||||
print ExtendedColor.red
|
||||
|
||||
print Color.red == ExtendedColor.red
|
||||
|
||||
class OtherColor(Enum):
|
||||
white = 4
|
||||
blue = 5
|
||||
|
||||
class MergedColor(Color, OtherColor):
|
||||
pass
|
||||
|
||||
print MergedColor.red
|
||||
print MergedColor.white
|
||||
|
||||
print Color
|
||||
print ExtendedColor
|
||||
print OtherColor
|
||||
print MergedColor
|
||||
|
||||
if __name__ == '__main__':
|
||||
_test()
|
118
2.7/Python-2.7.16/Demo/metaclasses/Meta.py
Normal file
118
2.7/Python-2.7.16/Demo/metaclasses/Meta.py
Normal file
@ -0,0 +1,118 @@
|
||||
"""Generic metaclass.
|
||||
|
||||
XXX This is very much a work in progress.
|
||||
|
||||
"""
|
||||
|
||||
import types
|
||||
|
||||
class MetaMethodWrapper:
|
||||
|
||||
def __init__(self, func, inst):
|
||||
self.func = func
|
||||
self.inst = inst
|
||||
self.__name__ = self.func.__name__
|
||||
|
||||
def __call__(self, *args, **kw):
|
||||
return apply(self.func, (self.inst,) + args, kw)
|
||||
|
||||
class MetaHelper:
|
||||
|
||||
__methodwrapper__ = MetaMethodWrapper # For derived helpers to override
|
||||
|
||||
def __helperinit__(self, formalclass):
|
||||
self.__formalclass__ = formalclass
|
||||
|
||||
def __getattr__(self, name):
|
||||
# Invoked for any attr not in the instance's __dict__
|
||||
try:
|
||||
raw = self.__formalclass__.__getattr__(name)
|
||||
except AttributeError:
|
||||
try:
|
||||
ga = self.__formalclass__.__getattr__('__usergetattr__')
|
||||
except (KeyError, AttributeError):
|
||||
raise AttributeError, name
|
||||
return ga(self, name)
|
||||
if type(raw) != types.FunctionType:
|
||||
return raw
|
||||
return self.__methodwrapper__(raw, self)
|
||||
|
||||
class MetaClass:
|
||||
|
||||
"""A generic metaclass.
|
||||
|
||||
This can be subclassed to implement various kinds of meta-behavior.
|
||||
|
||||
"""
|
||||
|
||||
__helper__ = MetaHelper # For derived metaclasses to override
|
||||
|
||||
__inited = 0
|
||||
|
||||
def __init__(self, name, bases, dict):
|
||||
try:
|
||||
ga = dict['__getattr__']
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
dict['__usergetattr__'] = ga
|
||||
del dict['__getattr__']
|
||||
self.__name__ = name
|
||||
self.__bases__ = bases
|
||||
self.__realdict__ = dict
|
||||
self.__inited = 1
|
||||
|
||||
def __getattr__(self, name):
|
||||
try:
|
||||
return self.__realdict__[name]
|
||||
except KeyError:
|
||||
for base in self.__bases__:
|
||||
try:
|
||||
return base.__getattr__(name)
|
||||
except AttributeError:
|
||||
pass
|
||||
raise AttributeError, name
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if not self.__inited:
|
||||
self.__dict__[name] = value
|
||||
else:
|
||||
self.__realdict__[name] = value
|
||||
|
||||
def __call__(self, *args, **kw):
|
||||
inst = self.__helper__()
|
||||
inst.__helperinit__(self)
|
||||
try:
|
||||
init = inst.__getattr__('__init__')
|
||||
except AttributeError:
|
||||
init = lambda: None
|
||||
apply(init, args, kw)
|
||||
return inst
|
||||
|
||||
|
||||
Meta = MetaClass('Meta', (), {})
|
||||
|
||||
|
||||
def _test():
|
||||
class C(Meta):
|
||||
def __init__(self, *args):
|
||||
print "__init__, args =", args
|
||||
def m1(self, x):
|
||||
print "m1(x=%r)" % (x,)
|
||||
print C
|
||||
x = C()
|
||||
print x
|
||||
x.m1(12)
|
||||
class D(C):
|
||||
def __getattr__(self, name):
|
||||
if name[:2] == '__': raise AttributeError, name
|
||||
return "getattr:%s" % name
|
||||
x = D()
|
||||
print x.foo
|
||||
print x._foo
|
||||
## print x.__foo
|
||||
## print x.__foo__
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
_test()
|
45
2.7/Python-2.7.16/Demo/metaclasses/Simple.py
Normal file
45
2.7/Python-2.7.16/Demo/metaclasses/Simple.py
Normal file
@ -0,0 +1,45 @@
|
||||
import types
|
||||
|
||||
class Tracing:
|
||||
def __init__(self, name, bases, namespace):
|
||||
"""Create a new class."""
|
||||
self.__name__ = name
|
||||
self.__bases__ = bases
|
||||
self.__namespace__ = namespace
|
||||
def __call__(self):
|
||||
"""Create a new instance."""
|
||||
return Instance(self)
|
||||
|
||||
class Instance:
|
||||
def __init__(self, klass):
|
||||
self.__klass__ = klass
|
||||
def __getattr__(self, name):
|
||||
try:
|
||||
value = self.__klass__.__namespace__[name]
|
||||
except KeyError:
|
||||
raise AttributeError, name
|
||||
if type(value) is not types.FunctionType:
|
||||
return value
|
||||
return BoundMethod(value, self)
|
||||
|
||||
class BoundMethod:
|
||||
def __init__(self, function, instance):
|
||||
self.function = function
|
||||
self.instance = instance
|
||||
def __call__(self, *args):
|
||||
print "calling", self.function, "for", self.instance, "with", args
|
||||
return apply(self.function, (self.instance,) + args)
|
||||
|
||||
Trace = Tracing('Trace', (), {})
|
||||
|
||||
class MyTracedClass(Trace):
|
||||
def method1(self, a):
|
||||
self.a = a
|
||||
def method2(self):
|
||||
return self.a
|
||||
|
||||
aninstance = MyTracedClass()
|
||||
|
||||
aninstance.method1(10)
|
||||
|
||||
print aninstance.method2()
|
256
2.7/Python-2.7.16/Demo/metaclasses/Synch.py
Normal file
256
2.7/Python-2.7.16/Demo/metaclasses/Synch.py
Normal file
@ -0,0 +1,256 @@
|
||||
"""Synchronization metaclass.
|
||||
|
||||
This metaclass makes it possible to declare synchronized methods.
|
||||
|
||||
"""
|
||||
|
||||
import thread
|
||||
|
||||
# First we need to define a reentrant lock.
|
||||
# This is generally useful and should probably be in a standard Python
|
||||
# library module. For now, we in-line it.
|
||||
|
||||
class Lock:
|
||||
|
||||
"""Reentrant lock.
|
||||
|
||||
This is a mutex-like object which can be acquired by the same
|
||||
thread more than once. It keeps a reference count of the number
|
||||
of times it has been acquired by the same thread. Each acquire()
|
||||
call must be matched by a release() call and only the last
|
||||
release() call actually releases the lock for acquisition by
|
||||
another thread.
|
||||
|
||||
The implementation uses two locks internally:
|
||||
|
||||
__mutex is a short term lock used to protect the instance variables
|
||||
__wait is the lock for which other threads wait
|
||||
|
||||
A thread intending to acquire both locks should acquire __wait
|
||||
first.
|
||||
|
||||
The implementation uses two other instance variables, protected by
|
||||
locking __mutex:
|
||||
|
||||
__tid is the thread ID of the thread that currently has the lock
|
||||
__count is the number of times the current thread has acquired it
|
||||
|
||||
When the lock is released, __tid is None and __count is zero.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""Constructor. Initialize all instance variables."""
|
||||
self.__mutex = thread.allocate_lock()
|
||||
self.__wait = thread.allocate_lock()
|
||||
self.__tid = None
|
||||
self.__count = 0
|
||||
|
||||
def acquire(self, flag=1):
|
||||
"""Acquire the lock.
|
||||
|
||||
If the optional flag argument is false, returns immediately
|
||||
when it cannot acquire the __wait lock without blocking (it
|
||||
may still block for a little while in order to acquire the
|
||||
__mutex lock).
|
||||
|
||||
The return value is only relevant when the flag argument is
|
||||
false; it is 1 if the lock is acquired, 0 if not.
|
||||
|
||||
"""
|
||||
self.__mutex.acquire()
|
||||
try:
|
||||
if self.__tid == thread.get_ident():
|
||||
self.__count = self.__count + 1
|
||||
return 1
|
||||
finally:
|
||||
self.__mutex.release()
|
||||
locked = self.__wait.acquire(flag)
|
||||
if not flag and not locked:
|
||||
return 0
|
||||
try:
|
||||
self.__mutex.acquire()
|
||||
assert self.__tid == None
|
||||
assert self.__count == 0
|
||||
self.__tid = thread.get_ident()
|
||||
self.__count = 1
|
||||
return 1
|
||||
finally:
|
||||
self.__mutex.release()
|
||||
|
||||
def release(self):
|
||||
"""Release the lock.
|
||||
|
||||
If this thread doesn't currently have the lock, an assertion
|
||||
error is raised.
|
||||
|
||||
Only allow another thread to acquire the lock when the count
|
||||
reaches zero after decrementing it.
|
||||
|
||||
"""
|
||||
self.__mutex.acquire()
|
||||
try:
|
||||
assert self.__tid == thread.get_ident()
|
||||
assert self.__count > 0
|
||||
self.__count = self.__count - 1
|
||||
if self.__count == 0:
|
||||
self.__tid = None
|
||||
self.__wait.release()
|
||||
finally:
|
||||
self.__mutex.release()
|
||||
|
||||
|
||||
def _testLock():
|
||||
|
||||
done = []
|
||||
|
||||
def f2(lock, done=done):
|
||||
lock.acquire()
|
||||
print "f2 running in thread %d\n" % thread.get_ident(),
|
||||
lock.release()
|
||||
done.append(1)
|
||||
|
||||
def f1(lock, f2=f2, done=done):
|
||||
lock.acquire()
|
||||
print "f1 running in thread %d\n" % thread.get_ident(),
|
||||
try:
|
||||
f2(lock)
|
||||
finally:
|
||||
lock.release()
|
||||
done.append(1)
|
||||
|
||||
lock = Lock()
|
||||
lock.acquire()
|
||||
f1(lock) # Adds 2 to done
|
||||
lock.release()
|
||||
|
||||
lock.acquire()
|
||||
|
||||
thread.start_new_thread(f1, (lock,)) # Adds 2
|
||||
thread.start_new_thread(f1, (lock, f1)) # Adds 3
|
||||
thread.start_new_thread(f2, (lock,)) # Adds 1
|
||||
thread.start_new_thread(f2, (lock,)) # Adds 1
|
||||
|
||||
lock.release()
|
||||
import time
|
||||
while len(done) < 9:
|
||||
print len(done)
|
||||
time.sleep(0.001)
|
||||
print len(done)
|
||||
|
||||
|
||||
# Now, the Locking metaclass is a piece of cake.
|
||||
# As an example feature, methods whose name begins with exactly one
|
||||
# underscore are not synchronized.
|
||||
|
||||
from Meta import MetaClass, MetaHelper, MetaMethodWrapper
|
||||
|
||||
class LockingMethodWrapper(MetaMethodWrapper):
|
||||
def __call__(self, *args, **kw):
|
||||
if self.__name__[:1] == '_' and self.__name__[1:] != '_':
|
||||
return apply(self.func, (self.inst,) + args, kw)
|
||||
self.inst.__lock__.acquire()
|
||||
try:
|
||||
return apply(self.func, (self.inst,) + args, kw)
|
||||
finally:
|
||||
self.inst.__lock__.release()
|
||||
|
||||
class LockingHelper(MetaHelper):
|
||||
__methodwrapper__ = LockingMethodWrapper
|
||||
def __helperinit__(self, formalclass):
|
||||
MetaHelper.__helperinit__(self, formalclass)
|
||||
self.__lock__ = Lock()
|
||||
|
||||
class LockingMetaClass(MetaClass):
|
||||
__helper__ = LockingHelper
|
||||
|
||||
Locking = LockingMetaClass('Locking', (), {})
|
||||
|
||||
def _test():
|
||||
# For kicks, take away the Locking base class and see it die
|
||||
class Buffer(Locking):
|
||||
def __init__(self, initialsize):
|
||||
assert initialsize > 0
|
||||
self.size = initialsize
|
||||
self.buffer = [None]*self.size
|
||||
self.first = self.last = 0
|
||||
def put(self, item):
|
||||
# Do we need to grow the buffer?
|
||||
if (self.last+1) % self.size != self.first:
|
||||
# Insert the new item
|
||||
self.buffer[self.last] = item
|
||||
self.last = (self.last+1) % self.size
|
||||
return
|
||||
# Double the buffer size
|
||||
# First normalize it so that first==0 and last==size-1
|
||||
print "buffer =", self.buffer
|
||||
print "first = %d, last = %d, size = %d" % (
|
||||
self.first, self.last, self.size)
|
||||
if self.first <= self.last:
|
||||
temp = self.buffer[self.first:self.last]
|
||||
else:
|
||||
temp = self.buffer[self.first:] + self.buffer[:self.last]
|
||||
print "temp =", temp
|
||||
self.buffer = temp + [None]*(self.size+1)
|
||||
self.first = 0
|
||||
self.last = self.size-1
|
||||
self.size = self.size*2
|
||||
print "Buffer size doubled to", self.size
|
||||
print "new buffer =", self.buffer
|
||||
print "first = %d, last = %d, size = %d" % (
|
||||
self.first, self.last, self.size)
|
||||
self.put(item) # Recursive call to test the locking
|
||||
def get(self):
|
||||
# Is the buffer empty?
|
||||
if self.first == self.last:
|
||||
raise EOFError # Avoid defining a new exception
|
||||
item = self.buffer[self.first]
|
||||
self.first = (self.first+1) % self.size
|
||||
return item
|
||||
|
||||
def producer(buffer, wait, n=1000):
|
||||
import time
|
||||
i = 0
|
||||
while i < n:
|
||||
print "put", i
|
||||
buffer.put(i)
|
||||
i = i+1
|
||||
print "Producer: done producing", n, "items"
|
||||
wait.release()
|
||||
|
||||
def consumer(buffer, wait, n=1000):
|
||||
import time
|
||||
i = 0
|
||||
tout = 0.001
|
||||
while i < n:
|
||||
try:
|
||||
x = buffer.get()
|
||||
if x != i:
|
||||
raise AssertionError, \
|
||||
"get() returned %s, expected %s" % (x, i)
|
||||
print "got", i
|
||||
i = i+1
|
||||
tout = 0.001
|
||||
except EOFError:
|
||||
time.sleep(tout)
|
||||
tout = tout*2
|
||||
print "Consumer: done consuming", n, "items"
|
||||
wait.release()
|
||||
|
||||
pwait = thread.allocate_lock()
|
||||
pwait.acquire()
|
||||
cwait = thread.allocate_lock()
|
||||
cwait.acquire()
|
||||
buffer = Buffer(1)
|
||||
n = 1000
|
||||
thread.start_new_thread(consumer, (buffer, cwait, n))
|
||||
thread.start_new_thread(producer, (buffer, pwait, n))
|
||||
pwait.acquire()
|
||||
print "Producer done"
|
||||
cwait.acquire()
|
||||
print "All done"
|
||||
print "buffer size ==", len(buffer.buffer)
|
||||
|
||||
if __name__ == '__main__':
|
||||
_testLock()
|
||||
_test()
|
144
2.7/Python-2.7.16/Demo/metaclasses/Trace.py
Normal file
144
2.7/Python-2.7.16/Demo/metaclasses/Trace.py
Normal file
@ -0,0 +1,144 @@
|
||||
"""Tracing metaclass.
|
||||
|
||||
XXX This is very much a work in progress.
|
||||
|
||||
"""
|
||||
|
||||
import types, sys
|
||||
|
||||
class TraceMetaClass:
|
||||
"""Metaclass for tracing.
|
||||
|
||||
Classes defined using this metaclass have an automatic tracing
|
||||
feature -- by setting the __trace_output__ instance (or class)
|
||||
variable to a file object, trace messages about all calls are
|
||||
written to the file. The trace formatting can be changed by
|
||||
defining a suitable __trace_call__ method.
|
||||
|
||||
"""
|
||||
|
||||
__inited = 0
|
||||
|
||||
def __init__(self, name, bases, dict):
|
||||
self.__name__ = name
|
||||
self.__bases__ = bases
|
||||
self.__dict = dict
|
||||
# XXX Can't define __dict__, alas
|
||||
self.__inited = 1
|
||||
|
||||
def __getattr__(self, name):
|
||||
try:
|
||||
return self.__dict[name]
|
||||
except KeyError:
|
||||
for base in self.__bases__:
|
||||
try:
|
||||
return base.__getattr__(name)
|
||||
except AttributeError:
|
||||
pass
|
||||
raise AttributeError, name
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if not self.__inited:
|
||||
self.__dict__[name] = value
|
||||
else:
|
||||
self.__dict[name] = value
|
||||
|
||||
def __call__(self, *args, **kw):
|
||||
inst = TracingInstance()
|
||||
inst.__meta_init__(self)
|
||||
try:
|
||||
init = inst.__getattr__('__init__')
|
||||
except AttributeError:
|
||||
init = lambda: None
|
||||
apply(init, args, kw)
|
||||
return inst
|
||||
|
||||
__trace_output__ = None
|
||||
|
||||
class TracingInstance:
|
||||
"""Helper class to represent an instance of a tracing class."""
|
||||
|
||||
def __trace_call__(self, fp, fmt, *args):
|
||||
fp.write((fmt+'\n') % args)
|
||||
|
||||
def __meta_init__(self, klass):
|
||||
self.__class = klass
|
||||
|
||||
def __getattr__(self, name):
|
||||
# Invoked for any attr not in the instance's __dict__
|
||||
try:
|
||||
raw = self.__class.__getattr__(name)
|
||||
except AttributeError:
|
||||
raise AttributeError, name
|
||||
if type(raw) != types.FunctionType:
|
||||
return raw
|
||||
# It's a function
|
||||
fullname = self.__class.__name__ + "." + name
|
||||
if not self.__trace_output__ or name == '__trace_call__':
|
||||
return NotTracingWrapper(fullname, raw, self)
|
||||
else:
|
||||
return TracingWrapper(fullname, raw, self)
|
||||
|
||||
class NotTracingWrapper:
|
||||
def __init__(self, name, func, inst):
|
||||
self.__name__ = name
|
||||
self.func = func
|
||||
self.inst = inst
|
||||
def __call__(self, *args, **kw):
|
||||
return apply(self.func, (self.inst,) + args, kw)
|
||||
|
||||
class TracingWrapper(NotTracingWrapper):
|
||||
def __call__(self, *args, **kw):
|
||||
self.inst.__trace_call__(self.inst.__trace_output__,
|
||||
"calling %s, inst=%s, args=%s, kw=%s",
|
||||
self.__name__, self.inst, args, kw)
|
||||
try:
|
||||
rv = apply(self.func, (self.inst,) + args, kw)
|
||||
except:
|
||||
t, v, tb = sys.exc_info()
|
||||
self.inst.__trace_call__(self.inst.__trace_output__,
|
||||
"returning from %s with exception %s: %s",
|
||||
self.__name__, t, v)
|
||||
raise t, v, tb
|
||||
else:
|
||||
self.inst.__trace_call__(self.inst.__trace_output__,
|
||||
"returning from %s with value %s",
|
||||
self.__name__, rv)
|
||||
return rv
|
||||
|
||||
Traced = TraceMetaClass('Traced', (), {'__trace_output__': None})
|
||||
|
||||
|
||||
def _test():
|
||||
global C, D
|
||||
class C(Traced):
|
||||
def __init__(self, x=0): self.x = x
|
||||
def m1(self, x): self.x = x
|
||||
def m2(self, y): return self.x + y
|
||||
__trace_output__ = sys.stdout
|
||||
class D(C):
|
||||
def m2(self, y): print "D.m2(%r)" % (y,); return C.m2(self, y)
|
||||
__trace_output__ = None
|
||||
x = C(4321)
|
||||
print x
|
||||
print x.x
|
||||
print x.m1(100)
|
||||
print x.m1(10)
|
||||
print x.m2(33)
|
||||
print x.m1(5)
|
||||
print x.m2(4000)
|
||||
print x.x
|
||||
|
||||
print C.__init__
|
||||
print C.m2
|
||||
print D.__init__
|
||||
print D.m2
|
||||
|
||||
y = D()
|
||||
print y
|
||||
print y.m1(10)
|
||||
print y.m2(100)
|
||||
print y.x
|
||||
|
||||
if __name__ == '__main__':
|
||||
_test()
|
605
2.7/Python-2.7.16/Demo/metaclasses/index.html
Normal file
605
2.7/Python-2.7.16/Demo/metaclasses/index.html
Normal file
@ -0,0 +1,605 @@
|
||||
<HTML>
|
||||
|
||||
<HEAD>
|
||||
<TITLE>Metaclasses in Python 1.5</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY BGCOLOR="FFFFFF">
|
||||
|
||||
<H1>Metaclasses in Python 1.5</H1>
|
||||
<H2>(A.k.a. The Killer Joke :-)</H2>
|
||||
|
||||
<HR>
|
||||
|
||||
(<i>Postscript:</i> reading this essay is probably not the best way to
|
||||
understand the metaclass hook described here. See a <A
|
||||
HREF="meta-vladimir.txt">message posted by Vladimir Marangozov</A>
|
||||
which may give a gentler introduction to the matter. You may also
|
||||
want to search Deja News for messages with "metaclass" in the subject
|
||||
posted to comp.lang.python in July and August 1998.)
|
||||
|
||||
<HR>
|
||||
|
||||
<P>In previous Python releases (and still in 1.5), there is something
|
||||
called the ``Don Beaudry hook'', after its inventor and champion.
|
||||
This allows C extensions to provide alternate class behavior, thereby
|
||||
allowing the Python class syntax to be used to define other class-like
|
||||
entities. Don Beaudry has used this in his infamous <A
|
||||
HREF="http://maigret.cog.brown.edu/pyutil/">MESS</A> package; Jim
|
||||
Fulton has used it in his <A
|
||||
HREF="http://www.digicool.com/releases/ExtensionClass/">Extension
|
||||
Classes</A> package. (It has also been referred to as the ``Don
|
||||
Beaudry <i>hack</i>,'' but that's a misnomer. There's nothing hackish
|
||||
about it -- in fact, it is rather elegant and deep, even though
|
||||
there's something dark to it.)
|
||||
|
||||
<P>(On first reading, you may want to skip directly to the examples in
|
||||
the section "Writing Metaclasses in Python" below, unless you want
|
||||
your head to explode.)
|
||||
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<P>Documentation of the Don Beaudry hook has purposefully been kept
|
||||
minimal, since it is a feature of incredible power, and is easily
|
||||
abused. Basically, it checks whether the <b>type of the base
|
||||
class</b> is callable, and if so, it is called to create the new
|
||||
class.
|
||||
|
||||
<P>Note the two indirection levels. Take a simple example:
|
||||
|
||||
<PRE>
|
||||
class B:
|
||||
pass
|
||||
|
||||
class C(B):
|
||||
pass
|
||||
</PRE>
|
||||
|
||||
Take a look at the second class definition, and try to fathom ``the
|
||||
type of the base class is callable.''
|
||||
|
||||
<P>(Types are not classes, by the way. See questions 4.2, 4.19 and in
|
||||
particular 6.22 in the <A
|
||||
HREF="http://www.python.org/cgi-bin/faqw.py" >Python FAQ</A>
|
||||
for more on this topic.)
|
||||
|
||||
<P>
|
||||
|
||||
<UL>
|
||||
|
||||
<LI>The <b>base class</b> is B; this one's easy.<P>
|
||||
|
||||
<LI>Since B is a class, its type is ``class''; so the <b>type of the
|
||||
base class</b> is the type ``class''. This is also known as
|
||||
types.ClassType, assuming the standard module <code>types</code> has
|
||||
been imported.<P>
|
||||
|
||||
<LI>Now is the type ``class'' <b>callable</b>? No, because types (in
|
||||
core Python) are never callable. Classes are callable (calling a
|
||||
class creates a new instance) but types aren't.<P>
|
||||
|
||||
</UL>
|
||||
|
||||
<P>So our conclusion is that in our example, the type of the base
|
||||
class (of C) is not callable. So the Don Beaudry hook does not apply,
|
||||
and the default class creation mechanism is used (which is also used
|
||||
when there is no base class). In fact, the Don Beaudry hook never
|
||||
applies when using only core Python, since the type of a core object
|
||||
is never callable.
|
||||
|
||||
<P>So what do Don and Jim do in order to use Don's hook? Write an
|
||||
extension that defines at least two new Python object types. The
|
||||
first would be the type for ``class-like'' objects usable as a base
|
||||
class, to trigger Don's hook. This type must be made callable.
|
||||
That's why we need a second type. Whether an object is callable
|
||||
depends on its type. So whether a type object is callable depends on
|
||||
<i>its</i> type, which is a <i>meta-type</i>. (In core Python there
|
||||
is only one meta-type, the type ``type'' (types.TypeType), which is
|
||||
the type of all type objects, even itself.) A new meta-type must
|
||||
be defined that makes the type of the class-like objects callable.
|
||||
(Normally, a third type would also be needed, the new ``instance''
|
||||
type, but this is not an absolute requirement -- the new class type
|
||||
could return an object of some existing type when invoked to create an
|
||||
instance.)
|
||||
|
||||
<P>Still confused? Here's a simple device due to Don himself to
|
||||
explain metaclasses. Take a simple class definition; assume B is a
|
||||
special class that triggers Don's hook:
|
||||
|
||||
<PRE>
|
||||
class C(B):
|
||||
a = 1
|
||||
b = 2
|
||||
</PRE>
|
||||
|
||||
This can be though of as equivalent to:
|
||||
|
||||
<PRE>
|
||||
C = type(B)('C', (B,), {'a': 1, 'b': 2})
|
||||
</PRE>
|
||||
|
||||
If that's too dense for you, here's the same thing written out using
|
||||
temporary variables:
|
||||
|
||||
<PRE>
|
||||
creator = type(B) # The type of the base class
|
||||
name = 'C' # The name of the new class
|
||||
bases = (B,) # A tuple containing the base class(es)
|
||||
namespace = {'a': 1, 'b': 2} # The namespace of the class statement
|
||||
C = creator(name, bases, namespace)
|
||||
</PRE>
|
||||
|
||||
This is analogous to what happens without the Don Beaudry hook, except
|
||||
that in that case the creator function is set to the default class
|
||||
creator.
|
||||
|
||||
<P>In either case, the creator is called with three arguments. The
|
||||
first one, <i>name</i>, is the name of the new class (as given at the
|
||||
top of the class statement). The <i>bases</i> argument is a tuple of
|
||||
base classes (a singleton tuple if there's only one base class, like
|
||||
the example). Finally, <i>namespace</i> is a dictionary containing
|
||||
the local variables collected during execution of the class statement.
|
||||
|
||||
<P>Note that the contents of the namespace dictionary is simply
|
||||
whatever names were defined in the class statement. A little-known
|
||||
fact is that when Python executes a class statement, it enters a new
|
||||
local namespace, and all assignments and function definitions take
|
||||
place in this namespace. Thus, after executing the following class
|
||||
statement:
|
||||
|
||||
<PRE>
|
||||
class C:
|
||||
a = 1
|
||||
def f(s): pass
|
||||
</PRE>
|
||||
|
||||
the class namespace's contents would be {'a': 1, 'f': <function f
|
||||
...>}.
|
||||
|
||||
<P>But enough already about writing Python metaclasses in C; read the
|
||||
documentation of <A
|
||||
HREF="http://maigret.cog.brown.edu/pyutil/">MESS</A> or <A
|
||||
HREF="http://www.digicool.com/papers/ExtensionClass.html" >Extension
|
||||
Classes</A> for more information.
|
||||
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<H2>Writing Metaclasses in Python</H2>
|
||||
|
||||
<P>In Python 1.5, the requirement to write a C extension in order to
|
||||
write metaclasses has been dropped (though you can still do
|
||||
it, of course). In addition to the check ``is the type of the base
|
||||
class callable,'' there's a check ``does the base class have a
|
||||
__class__ attribute.'' If so, it is assumed that the __class__
|
||||
attribute refers to a class.
|
||||
|
||||
<P>Let's repeat our simple example from above:
|
||||
|
||||
<PRE>
|
||||
class C(B):
|
||||
a = 1
|
||||
b = 2
|
||||
</PRE>
|
||||
|
||||
Assuming B has a __class__ attribute, this translates into:
|
||||
|
||||
<PRE>
|
||||
C = B.__class__('C', (B,), {'a': 1, 'b': 2})
|
||||
</PRE>
|
||||
|
||||
This is exactly the same as before except that instead of type(B),
|
||||
B.__class__ is invoked. If you have read <A HREF=
|
||||
"http://www.python.org/cgi-bin/faqw.py?req=show&file=faq06.022.htp"
|
||||
>FAQ question 6.22</A> you will understand that while there is a big
|
||||
technical difference between type(B) and B.__class__, they play the
|
||||
same role at different abstraction levels. And perhaps at some point
|
||||
in the future they will really be the same thing (at which point you
|
||||
would be able to derive subclasses from built-in types).
|
||||
|
||||
<P>At this point it may be worth mentioning that C.__class__ is the
|
||||
same object as B.__class__, i.e., C's metaclass is the same as B's
|
||||
metaclass. In other words, subclassing an existing class creates a
|
||||
new (meta)inststance of the base class's metaclass.
|
||||
|
||||
<P>Going back to the example, the class B.__class__ is instantiated,
|
||||
passing its constructor the same three arguments that are passed to
|
||||
the default class constructor or to an extension's metaclass:
|
||||
<i>name</i>, <i>bases</i>, and <i>namespace</i>.
|
||||
|
||||
<P>It is easy to be confused by what exactly happens when using a
|
||||
metaclass, because we lose the absolute distinction between classes
|
||||
and instances: a class is an instance of a metaclass (a
|
||||
``metainstance''), but technically (i.e. in the eyes of the python
|
||||
runtime system), the metaclass is just a class, and the metainstance
|
||||
is just an instance. At the end of the class statement, the metaclass
|
||||
whose metainstance is used as a base class is instantiated, yielding a
|
||||
second metainstance (of the same metaclass). This metainstance is
|
||||
then used as a (normal, non-meta) class; instantiation of the class
|
||||
means calling the metainstance, and this will return a real instance.
|
||||
And what class is that an instance of? Conceptually, it is of course
|
||||
an instance of our metainstance; but in most cases the Python runtime
|
||||
system will see it as an instance of a helper class used by the
|
||||
metaclass to implement its (non-meta) instances...
|
||||
|
||||
<P>Hopefully an example will make things clearer. Let's presume we
|
||||
have a metaclass MetaClass1. It's helper class (for non-meta
|
||||
instances) is callled HelperClass1. We now (manually) instantiate
|
||||
MetaClass1 once to get an empty special base class:
|
||||
|
||||
<PRE>
|
||||
BaseClass1 = MetaClass1("BaseClass1", (), {})
|
||||
</PRE>
|
||||
|
||||
We can now use BaseClass1 as a base class in a class statement:
|
||||
|
||||
<PRE>
|
||||
class MySpecialClass(BaseClass1):
|
||||
i = 1
|
||||
def f(s): pass
|
||||
</PRE>
|
||||
|
||||
At this point, MySpecialClass is defined; it is a metainstance of
|
||||
MetaClass1 just like BaseClass1, and in fact the expression
|
||||
``BaseClass1.__class__ == MySpecialClass.__class__ == MetaClass1''
|
||||
yields true.
|
||||
|
||||
<P>We are now ready to create instances of MySpecialClass. Let's
|
||||
assume that no constructor arguments are required:
|
||||
|
||||
<PRE>
|
||||
x = MySpecialClass()
|
||||
y = MySpecialClass()
|
||||
print x.__class__, y.__class__
|
||||
</PRE>
|
||||
|
||||
The print statement shows that x and y are instances of HelperClass1.
|
||||
How did this happen? MySpecialClass is an instance of MetaClass1
|
||||
(``meta'' is irrelevant here); when an instance is called, its
|
||||
__call__ method is invoked, and presumably the __call__ method defined
|
||||
by MetaClass1 returns an instance of HelperClass1.
|
||||
|
||||
<P>Now let's see how we could use metaclasses -- what can we do
|
||||
with metaclasses that we can't easily do without them? Here's one
|
||||
idea: a metaclass could automatically insert trace calls for all
|
||||
method calls. Let's first develop a simplified example, without
|
||||
support for inheritance or other ``advanced'' Python features (we'll
|
||||
add those later).
|
||||
|
||||
<PRE>
|
||||
import types
|
||||
|
||||
class Tracing:
|
||||
def __init__(self, name, bases, namespace):
|
||||
"""Create a new class."""
|
||||
self.__name__ = name
|
||||
self.__bases__ = bases
|
||||
self.__namespace__ = namespace
|
||||
def __call__(self):
|
||||
"""Create a new instance."""
|
||||
return Instance(self)
|
||||
|
||||
class Instance:
|
||||
def __init__(self, klass):
|
||||
self.__klass__ = klass
|
||||
def __getattr__(self, name):
|
||||
try:
|
||||
value = self.__klass__.__namespace__[name]
|
||||
except KeyError:
|
||||
raise AttributeError, name
|
||||
if type(value) is not types.FunctionType:
|
||||
return value
|
||||
return BoundMethod(value, self)
|
||||
|
||||
class BoundMethod:
|
||||
def __init__(self, function, instance):
|
||||
self.function = function
|
||||
self.instance = instance
|
||||
def __call__(self, *args):
|
||||
print "calling", self.function, "for", self.instance, "with", args
|
||||
return apply(self.function, (self.instance,) + args)
|
||||
|
||||
Trace = Tracing('Trace', (), {})
|
||||
|
||||
class MyTracedClass(Trace):
|
||||
def method1(self, a):
|
||||
self.a = a
|
||||
def method2(self):
|
||||
return self.a
|
||||
|
||||
aninstance = MyTracedClass()
|
||||
|
||||
aninstance.method1(10)
|
||||
|
||||
print "the answer is %d" % aninstance.method2()
|
||||
</PRE>
|
||||
|
||||
Confused already? The intention is to read this from top down. The
|
||||
Tracing class is the metaclass we're defining. Its structure is
|
||||
really simple.
|
||||
|
||||
<P>
|
||||
|
||||
<UL>
|
||||
|
||||
<LI>The __init__ method is invoked when a new Tracing instance is
|
||||
created, e.g. the definition of class MyTracedClass later in the
|
||||
example. It simply saves the class name, base classes and namespace
|
||||
as instance variables.<P>
|
||||
|
||||
<LI>The __call__ method is invoked when a Tracing instance is called,
|
||||
e.g. the creation of aninstance later in the example. It returns an
|
||||
instance of the class Instance, which is defined next.<P>
|
||||
|
||||
</UL>
|
||||
|
||||
<P>The class Instance is the class used for all instances of classes
|
||||
built using the Tracing metaclass, e.g. aninstance. It has two
|
||||
methods:
|
||||
|
||||
<P>
|
||||
|
||||
<UL>
|
||||
|
||||
<LI>The __init__ method is invoked from the Tracing.__call__ method
|
||||
above to initialize a new instance. It saves the class reference as
|
||||
an instance variable. It uses a funny name because the user's
|
||||
instance variables (e.g. self.a later in the example) live in the same
|
||||
namespace.<P>
|
||||
|
||||
<LI>The __getattr__ method is invoked whenever the user code
|
||||
references an attribute of the instance that is not an instance
|
||||
variable (nor a class variable; but except for __init__ and
|
||||
__getattr__ there are no class variables). It will be called, for
|
||||
example, when aninstance.method1 is referenced in the example, with
|
||||
self set to aninstance and name set to the string "method1".<P>
|
||||
|
||||
</UL>
|
||||
|
||||
<P>The __getattr__ method looks the name up in the __namespace__
|
||||
dictionary. If it isn't found, it raises an AttributeError exception.
|
||||
(In a more realistic example, it would first have to look through the
|
||||
base classes as well.) If it is found, there are two possibilities:
|
||||
it's either a function or it isn't. If it's not a function, it is
|
||||
assumed to be a class variable, and its value is returned. If it's a
|
||||
function, we have to ``wrap'' it in instance of yet another helper
|
||||
class, BoundMethod.
|
||||
|
||||
<P>The BoundMethod class is needed to implement a familiar feature:
|
||||
when a method is defined, it has an initial argument, self, which is
|
||||
automatically bound to the relevant instance when it is called. For
|
||||
example, aninstance.method1(10) is equivalent to method1(aninstance,
|
||||
10). In the example if this call, first a temporary BoundMethod
|
||||
instance is created with the following constructor call: temp =
|
||||
BoundMethod(method1, aninstance); then this instance is called as
|
||||
temp(10). After the call, the temporary instance is discarded.
|
||||
|
||||
<P>
|
||||
|
||||
<UL>
|
||||
|
||||
<LI>The __init__ method is invoked for the constructor call
|
||||
BoundMethod(method1, aninstance). It simply saves away its
|
||||
arguments.<P>
|
||||
|
||||
<LI>The __call__ method is invoked when the bound method instance is
|
||||
called, as in temp(10). It needs to call method1(aninstance, 10).
|
||||
However, even though self.function is now method1 and self.instance is
|
||||
aninstance, it can't call self.function(self.instance, args) directly,
|
||||
because it should work regardless of the number of arguments passed.
|
||||
(For simplicity, support for keyword arguments has been omitted.)<P>
|
||||
|
||||
</UL>
|
||||
|
||||
<P>In order to be able to support arbitrary argument lists, the
|
||||
__call__ method first constructs a new argument tuple. Conveniently,
|
||||
because of the notation *args in __call__'s own argument list, the
|
||||
arguments to __call__ (except for self) are placed in the tuple args.
|
||||
To construct the desired argument list, we concatenate a singleton
|
||||
tuple containing the instance with the args tuple: (self.instance,) +
|
||||
args. (Note the trailing comma used to construct the singleton
|
||||
tuple.) In our example, the resulting argument tuple is (aninstance,
|
||||
10).
|
||||
|
||||
<P>The intrinsic function apply() takes a function and an argument
|
||||
tuple and calls the function for it. In our example, we are calling
|
||||
apply(method1, (aninstance, 10)) which is equivalent to calling
|
||||
method(aninstance, 10).
|
||||
|
||||
<P>From here on, things should come together quite easily. The output
|
||||
of the example code is something like this:
|
||||
|
||||
<PRE>
|
||||
calling <function method1 at ae8d8> for <Instance instance at 95ab0> with (10,)
|
||||
calling <function method2 at ae900> for <Instance instance at 95ab0> with ()
|
||||
the answer is 10
|
||||
</PRE>
|
||||
|
||||
<P>That was about the shortest meaningful example that I could come up
|
||||
with. A real tracing metaclass (for example, <A
|
||||
HREF="#Trace">Trace.py</A> discussed below) needs to be more
|
||||
complicated in two dimensions.
|
||||
|
||||
<P>First, it needs to support more advanced Python features such as
|
||||
class variables, inheritance, __init__ methods, and keyword arguments.
|
||||
|
||||
<P>Second, it needs to provide a more flexible way to handle the
|
||||
actual tracing information; perhaps it should be possible to write
|
||||
your own tracing function that gets called, perhaps it should be
|
||||
possible to enable and disable tracing on a per-class or per-instance
|
||||
basis, and perhaps a filter so that only interesting calls are traced;
|
||||
it should also be able to trace the return value of the call (or the
|
||||
exception it raised if an error occurs). Even the Trace.py example
|
||||
doesn't support all these features yet.
|
||||
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<H1>Real-life Examples</H1>
|
||||
|
||||
<P>Have a look at some very preliminary examples that I coded up to
|
||||
teach myself how to write metaclasses:
|
||||
|
||||
<DL>
|
||||
|
||||
<DT><A HREF="Enum.py">Enum.py</A>
|
||||
|
||||
<DD>This (ab)uses the class syntax as an elegant way to define
|
||||
enumerated types. The resulting classes are never instantiated --
|
||||
rather, their class attributes are the enumerated values. For
|
||||
example:
|
||||
|
||||
<PRE>
|
||||
class Color(Enum):
|
||||
red = 1
|
||||
green = 2
|
||||
blue = 3
|
||||
print Color.red
|
||||
</PRE>
|
||||
|
||||
will print the string ``Color.red'', while ``Color.red==1'' is true,
|
||||
and ``Color.red + 1'' raise a TypeError exception.
|
||||
|
||||
<P>
|
||||
|
||||
<DT><A NAME=Trace></A><A HREF="Trace.py">Trace.py</A>
|
||||
|
||||
<DD>The resulting classes work much like standard
|
||||
classes, but by setting a special class or instance attribute
|
||||
__trace_output__ to point to a file, all calls to the class's methods
|
||||
are traced. It was a bit of a struggle to get this right. This
|
||||
should probably redone using the generic metaclass below.
|
||||
|
||||
<P>
|
||||
|
||||
<DT><A HREF="Meta.py">Meta.py</A>
|
||||
|
||||
<DD>A generic metaclass. This is an attempt at finding out how much
|
||||
standard class behavior can be mimicked by a metaclass. The
|
||||
preliminary answer appears to be that everything's fine as long as the
|
||||
class (or its clients) don't look at the instance's __class__
|
||||
attribute, nor at the class's __dict__ attribute. The use of
|
||||
__getattr__ internally makes the classic implementation of __getattr__
|
||||
hooks tough; we provide a similar hook _getattr_ instead.
|
||||
(__setattr__ and __delattr__ are not affected.)
|
||||
(XXX Hm. Could detect presence of __getattr__ and rename it.)
|
||||
|
||||
<P>
|
||||
|
||||
<DT><A HREF="Eiffel.py">Eiffel.py</A>
|
||||
|
||||
<DD>Uses the above generic metaclass to implement Eiffel style
|
||||
pre-conditions and post-conditions.
|
||||
|
||||
<P>
|
||||
|
||||
<DT><A HREF="Synch.py">Synch.py</A>
|
||||
|
||||
<DD>Uses the above generic metaclass to implement synchronized
|
||||
methods.
|
||||
|
||||
<P>
|
||||
|
||||
<DT><A HREF="Simple.py">Simple.py</A>
|
||||
|
||||
<DD>The example module used above.
|
||||
|
||||
<P>
|
||||
|
||||
</DL>
|
||||
|
||||
<P>A pattern seems to be emerging: almost all these uses of
|
||||
metaclasses (except for Enum, which is probably more cute than useful)
|
||||
mostly work by placing wrappers around method calls. An obvious
|
||||
problem with that is that it's not easy to combine the features of
|
||||
different metaclasses, while this would actually be quite useful: for
|
||||
example, I wouldn't mind getting a trace from the test run of the
|
||||
Synch module, and it would be interesting to add preconditions to it
|
||||
as well. This needs more research. Perhaps a metaclass could be
|
||||
provided that allows stackable wrappers...
|
||||
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<H2>Things You Could Do With Metaclasses</H2>
|
||||
|
||||
<P>There are lots of things you could do with metaclasses. Most of
|
||||
these can also be done with creative use of __getattr__, but
|
||||
metaclasses make it easier to modify the attribute lookup behavior of
|
||||
classes. Here's a partial list.
|
||||
|
||||
<P>
|
||||
|
||||
<UL>
|
||||
|
||||
<LI>Enforce different inheritance semantics, e.g. automatically call
|
||||
base class methods when a derived class overrides<P>
|
||||
|
||||
<LI>Implement class methods (e.g. if the first argument is not named
|
||||
'self')<P>
|
||||
|
||||
<LI>Implement that each instance is initialized with <b>copies</b> of
|
||||
all class variables<P>
|
||||
|
||||
<LI>Implement a different way to store instance variables (e.g. in a
|
||||
list kept outside the instance but indexed by the instance's id())<P>
|
||||
|
||||
<LI>Automatically wrap or trap all or certain methods
|
||||
|
||||
<UL>
|
||||
|
||||
<LI>for tracing
|
||||
|
||||
<LI>for precondition and postcondition checking
|
||||
|
||||
<LI>for synchronized methods
|
||||
|
||||
<LI>for automatic value caching
|
||||
|
||||
</UL>
|
||||
<P>
|
||||
|
||||
<LI>When an attribute is a parameterless function, call it on
|
||||
reference (to mimic it being an instance variable); same on assignment<P>
|
||||
|
||||
<LI>Instrumentation: see how many times various attributes are used<P>
|
||||
|
||||
<LI>Different semantics for __setattr__ and __getattr__ (e.g. disable
|
||||
them when they are being used recursively)<P>
|
||||
|
||||
<LI>Abuse class syntax for other things<P>
|
||||
|
||||
<LI>Experiment with automatic type checking<P>
|
||||
|
||||
<LI>Delegation (or acquisition)<P>
|
||||
|
||||
<LI>Dynamic inheritance patterns<P>
|
||||
|
||||
<LI>Automatic caching of methods<P>
|
||||
|
||||
</UL>
|
||||
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<H4>Credits</H4>
|
||||
|
||||
<P>Many thanks to David Ascher and Donald Beaudry for their comments
|
||||
on earlier draft of this paper. Also thanks to Matt Conway and Tommy
|
||||
Burnette for putting a seed for the idea of metaclasses in my
|
||||
mind, nearly three years ago, even though at the time my response was
|
||||
``you can do that with __getattr__ hooks...'' :-)
|
||||
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
</BODY>
|
||||
|
||||
</HTML>
|
256
2.7/Python-2.7.16/Demo/metaclasses/meta-vladimir.txt
Normal file
256
2.7/Python-2.7.16/Demo/metaclasses/meta-vladimir.txt
Normal file
@ -0,0 +1,256 @@
|
||||
Subject: Re: The metaclass saga using Python
|
||||
From: Vladimir Marangozov <Vladimir.Marangozov@imag.fr>
|
||||
To: tim_one@email.msn.com (Tim Peters)
|
||||
Cc: python-list@cwi.nl
|
||||
Date: Wed, 5 Aug 1998 15:59:06 +0200 (DFT)
|
||||
|
||||
[Tim]
|
||||
>
|
||||
> building-on-examples-tends-to-prevent-abstract-thrashing-ly y'rs - tim
|
||||
>
|
||||
|
||||
OK, I stand corrected. I understand that anybody's interpretation of
|
||||
the meta-class concept is likely to be difficult to digest by others.
|
||||
|
||||
Here's another try, expressing the same thing, but using the Python
|
||||
programming model, examples and, perhaps, more popular terms.
|
||||
|
||||
1. Classes.
|
||||
|
||||
This is pure Python of today. Sorry about the tutorial, but it is
|
||||
meant to illustrate the second part, which is the one we're
|
||||
interested in and which will follow the same development scenario.
|
||||
Besides, newbies are likely to understand that the discussion is
|
||||
affordable even for them :-)
|
||||
|
||||
a) Class definition
|
||||
|
||||
A class is meant to define the common properties of a set of objects.
|
||||
A class is a "package" of properties. The assembly of properties
|
||||
in a class package is sometimes called a class structure (which isn't
|
||||
always appropriate).
|
||||
|
||||
>>> class A:
|
||||
attr1 = "Hello" # an attribute of A
|
||||
def method1(self, *args): pass # method1 of A
|
||||
def method2(self, *args): pass # method2 of A
|
||||
>>>
|
||||
|
||||
So far, we defined the structure of the class A. The class A is
|
||||
of type <class>. We can check this by asking Python: "what is A?"
|
||||
|
||||
>>> A # What is A?
|
||||
<class __main__.A at 2023e360>
|
||||
|
||||
b) Class instantiation
|
||||
|
||||
Creating an object with the properties defined in the class A is
|
||||
called instantiation of the class A. After an instantiation of A, we
|
||||
obtain a new object, called an instance, which has the properties
|
||||
packaged in the class A.
|
||||
|
||||
>>> a = A() # 'a' is the 1st instance of A
|
||||
>>> a # What is 'a'?
|
||||
<__main__.A instance at 2022b9d0>
|
||||
|
||||
>>> b = A() # 'b' is another instance of A
|
||||
>>> b # What is 'b'?
|
||||
<__main__.A instance at 2022b9c0>
|
||||
|
||||
The objects, 'a' and 'b', are of type <instance> and they both have
|
||||
the same properties. Note, that 'a' and 'b' are different objects.
|
||||
(their adresses differ). This is a bit hard to see, so let's ask Python:
|
||||
|
||||
>>> a == b # Is 'a' the same object as 'b'?
|
||||
0 # No.
|
||||
|
||||
Instance objects have one more special property, indicating the class
|
||||
they are an instance of. This property is named __class__.
|
||||
|
||||
>>> a.__class__ # What is the class of 'a'?
|
||||
<class __main__.A at 2023e360> # 'a' is an instance of A
|
||||
>>> b.__class__ # What is the class of 'b'?
|
||||
<class __main__.A at 2023e360> # 'b' is an instance of A
|
||||
>>> a.__class__ == b.__class__ # Is it really the same class A?
|
||||
1 # Yes.
|
||||
|
||||
c) Class inheritance (class composition and specialization)
|
||||
|
||||
Classes can be defined in terms of other existing classes (and only
|
||||
classes! -- don't bug me on this now). Thus, we can compose property
|
||||
packages and create new ones. We reuse the property set defined
|
||||
in a class by defining a new class, which "inherits" from the former.
|
||||
In other words, a class B which inherits from the class A, inherits
|
||||
the properties defined in A, or, B inherits the structure of A.
|
||||
|
||||
In the same time, at the definition of the new class B, we can enrich
|
||||
the inherited set of properties by adding new ones and/or modify some
|
||||
of the inherited properties.
|
||||
|
||||
>>> class B(A): # B inherits A's properties
|
||||
attr2 = "World" # additional attr2
|
||||
def method2(self, arg1): pass # method2 is redefined
|
||||
def method3(self, *args): pass # additional method3
|
||||
|
||||
>>> B # What is B?
|
||||
<class __main__.B at 2023e500>
|
||||
>>> B == A # Is B the same class as A?
|
||||
0 # No.
|
||||
|
||||
Classes define one special property, indicating whether a class
|
||||
inherits the properties of another class. This property is called
|
||||
__bases__ and it contains a list (a tuple) of the classes the new
|
||||
class inherits from. The classes from which a class is inheriting the
|
||||
properties are called superclasses (in Python, we call them also --
|
||||
base classes).
|
||||
|
||||
>>> A.__bases__ # Does A have any superclasses?
|
||||
() # No.
|
||||
>>> B.__bases__ # Does B have any superclasses?
|
||||
(<class __main__.A at 2023e360>,) # Yes. It has one superclass.
|
||||
>>> B.__bases__[0] == A # Is it really the class A?
|
||||
1 # Yes, it is.
|
||||
|
||||
--------
|
||||
|
||||
Congratulations on getting this far! This was the hard part.
|
||||
Now, let's continue with the easy one.
|
||||
|
||||
--------
|
||||
|
||||
2. Meta-classes
|
||||
|
||||
You have to admit, that an anonymous group of Python wizards are
|
||||
not satisfied with the property packaging facilities presented above.
|
||||
They say, that the Real-World bugs them with problems that cannot be
|
||||
modelled successfully with classes. Or, that the way classes are
|
||||
implemented in Python and the way classes and instances behave at
|
||||
runtime isn't always appropriate for reproducing the Real-World's
|
||||
behavior in a way that satisfies them.
|
||||
|
||||
Hence, what they want is the following:
|
||||
|
||||
a) leave objects as they are (instances of classes)
|
||||
b) leave classes as they are (property packages and object creators)
|
||||
|
||||
BUT, at the same time:
|
||||
|
||||
c) consider classes as being instances of mysterious objects.
|
||||
d) label mysterious objects "meta-classes".
|
||||
|
||||
Easy, eh?
|
||||
|
||||
You may ask: "Why on earth do they want to do that?".
|
||||
They answer: "Poor soul... Go and see how cruel the Real-World is!".
|
||||
You - fuzzy: "OK, will do!"
|
||||
|
||||
And here we go for another round of what I said in section 1 -- Classes.
|
||||
|
||||
However, be warned! The features we're going to talk about aren't fully
|
||||
implemented yet, because the Real-World don't let wizards to evaluate
|
||||
precisely how cruel it is, so the features are still highly-experimental.
|
||||
|
||||
a) Meta-class definition
|
||||
|
||||
A meta-class is meant to define the common properties of a set of
|
||||
classes. A meta-class is a "package" of properties. The assembly
|
||||
of properties in a meta-class package is sometimes called a meta-class
|
||||
structure (which isn't always appropriate).
|
||||
|
||||
In Python, a meta-class definition would have looked like this:
|
||||
|
||||
>>> metaclass M:
|
||||
attr1 = "Hello" # an attribute of M
|
||||
def method1(self, *args): pass # method1 of M
|
||||
def method2(self, *args): pass # method2 of M
|
||||
>>>
|
||||
|
||||
So far, we defined the structure of the meta-class M. The meta-class
|
||||
M is of type <metaclass>. We cannot check this by asking Python, but
|
||||
if we could, it would have answered:
|
||||
|
||||
>>> M # What is M?
|
||||
<metaclass __main__.M at 2023e4e0>
|
||||
|
||||
b) Meta-class instantiation
|
||||
|
||||
Creating an object with the properties defined in the meta-class M is
|
||||
called instantiation of the meta-class M. After an instantiation of M,
|
||||
we obtain a new object, called an class, but now it is called also
|
||||
a meta-instance, which has the properties packaged in the meta-class M.
|
||||
|
||||
In Python, instantiating a meta-class would have looked like this:
|
||||
|
||||
>>> A = M() # 'A' is the 1st instance of M
|
||||
>>> A # What is 'A'?
|
||||
<class __main__.A at 2022b9d0>
|
||||
|
||||
>>> B = M() # 'B' is another instance of M
|
||||
>>> B # What is 'B'?
|
||||
<class __main__.B at 2022b9c0>
|
||||
|
||||
The metaclass-instances, A and B, are of type <class> and they both
|
||||
have the same properties. Note, that A and B are different objects.
|
||||
(their adresses differ). This is a bit hard to see, but if it was
|
||||
possible to ask Python, it would have answered:
|
||||
|
||||
>>> A == B # Is A the same class as B?
|
||||
0 # No.
|
||||
|
||||
Class objects have one more special property, indicating the meta-class
|
||||
they are an instance of. This property is named __metaclass__.
|
||||
|
||||
>>> A.__metaclass__ # What is the meta-class of A?
|
||||
<metaclass __main__.M at 2023e4e0> # A is an instance of M
|
||||
>>> A.__metaclass__ # What is the meta-class of B?
|
||||
<metaclass __main__.M at 2023e4e0> # B is an instance of M
|
||||
>>> A.__metaclass__ == B.__metaclass__ # Is it the same meta-class M?
|
||||
1 # Yes.
|
||||
|
||||
c) Meta-class inheritance (meta-class composition and specialization)
|
||||
|
||||
Meta-classes can be defined in terms of other existing meta-classes
|
||||
(and only meta-classes!). Thus, we can compose property packages and
|
||||
create new ones. We reuse the property set defined in a meta-class by
|
||||
defining a new meta-class, which "inherits" from the former.
|
||||
In other words, a meta-class N which inherits from the meta-class M,
|
||||
inherits the properties defined in M, or, N inherits the structure of M.
|
||||
|
||||
In the same time, at the definition of the new meta-class N, we can
|
||||
enrich the inherited set of properties by adding new ones and/or modify
|
||||
some of the inherited properties.
|
||||
|
||||
>>> metaclass N(M): # N inherits M's properties
|
||||
attr2 = "World" # additional attr2
|
||||
def method2(self, arg1): pass # method2 is redefined
|
||||
def method3(self, *args): pass # additional method3
|
||||
|
||||
>>> N # What is N?
|
||||
<metaclass __main__.N at 2023e500>
|
||||
>>> N == M # Is N the same meta-class as M?
|
||||
0 # No.
|
||||
|
||||
Meta-classes define one special property, indicating whether a
|
||||
meta-class inherits the properties of another meta-class. This property
|
||||
is called __metabases__ and it contains a list (a tuple) of the
|
||||
meta-classes the new meta-class inherits from. The meta-classes from
|
||||
which a meta-class is inheriting the properties are called
|
||||
super-meta-classes (in Python, we call them also -- super meta-bases).
|
||||
|
||||
>>> M.__metabases__ # Does M have any supermetaclasses?
|
||||
() # No.
|
||||
>>> N.__metabases__ # Does N have any supermetaclasses?
|
||||
(<metaclass __main__.M at 2023e360>,) # Yes. It has a supermetaclass.
|
||||
>>> N.__metabases__[0] == M # Is it really the meta-class M?
|
||||
1 # Yes, it is.
|
||||
|
||||
--------
|
||||
|
||||
Triple congratulations on getting this far!
|
||||
Now you know everything about meta-classes and the Real-World!
|
||||
|
||||
<unless-wizards-want-meta-classes-be-instances-of-mysterious-objects!>
|
||||
|
||||
--
|
||||
Vladimir MARANGOZOV | Vladimir.Marangozov@inrialpes.fr
|
||||
http://sirac.inrialpes.fr/~marangoz | tel:(+33-4)76615277 fax:76615252
|
141
2.7/Python-2.7.16/Demo/newmetaclasses/Eiffel.py
Normal file
141
2.7/Python-2.7.16/Demo/newmetaclasses/Eiffel.py
Normal file
@ -0,0 +1,141 @@
|
||||
"""Support Eiffel-style preconditions and postconditions."""
|
||||
|
||||
from types import FunctionType as function
|
||||
|
||||
class EiffelBaseMetaClass(type):
|
||||
|
||||
def __new__(meta, name, bases, dict):
|
||||
meta.convert_methods(dict)
|
||||
return super(EiffelBaseMetaClass, meta).__new__(meta, name, bases,
|
||||
dict)
|
||||
|
||||
@classmethod
|
||||
def convert_methods(cls, dict):
|
||||
"""Replace functions in dict with EiffelMethod wrappers.
|
||||
|
||||
The dict is modified in place.
|
||||
|
||||
If a method ends in _pre or _post, it is removed from the dict
|
||||
regardless of whether there is a corresponding method.
|
||||
"""
|
||||
# find methods with pre or post conditions
|
||||
methods = []
|
||||
for k, v in dict.iteritems():
|
||||
if k.endswith('_pre') or k.endswith('_post'):
|
||||
assert isinstance(v, function)
|
||||
elif isinstance(v, function):
|
||||
methods.append(k)
|
||||
for m in methods:
|
||||
pre = dict.get("%s_pre" % m)
|
||||
post = dict.get("%s_post" % m)
|
||||
if pre or post:
|
||||
dict[m] = cls.make_eiffel_method(dict[m], pre, post)
|
||||
|
||||
class EiffelMetaClass1(EiffelBaseMetaClass):
|
||||
# an implementation of the "eiffel" meta class that uses nested functions
|
||||
|
||||
@staticmethod
|
||||
def make_eiffel_method(func, pre, post):
|
||||
def method(self, *args, **kwargs):
|
||||
if pre:
|
||||
pre(self, *args, **kwargs)
|
||||
x = func(self, *args, **kwargs)
|
||||
if post:
|
||||
post(self, x, *args, **kwargs)
|
||||
return x
|
||||
|
||||
if func.__doc__:
|
||||
method.__doc__ = func.__doc__
|
||||
|
||||
return method
|
||||
|
||||
class EiffelMethodWrapper:
|
||||
|
||||
def __init__(self, inst, descr):
|
||||
self._inst = inst
|
||||
self._descr = descr
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
return self._descr.callmethod(self._inst, args, kwargs)
|
||||
|
||||
class EiffelDescriptor(object):
|
||||
|
||||
def __init__(self, func, pre, post):
|
||||
self._func = func
|
||||
self._pre = pre
|
||||
self._post = post
|
||||
|
||||
self.__name__ = func.__name__
|
||||
self.__doc__ = func.__doc__
|
||||
|
||||
def __get__(self, obj, cls):
|
||||
return EiffelMethodWrapper(obj, self)
|
||||
|
||||
def callmethod(self, inst, args, kwargs):
|
||||
if self._pre:
|
||||
self._pre(inst, *args, **kwargs)
|
||||
x = self._func(inst, *args, **kwargs)
|
||||
if self._post:
|
||||
self._post(inst, x, *args, **kwargs)
|
||||
return x
|
||||
|
||||
class EiffelMetaClass2(EiffelBaseMetaClass):
|
||||
# an implementation of the "eiffel" meta class that uses descriptors
|
||||
|
||||
make_eiffel_method = EiffelDescriptor
|
||||
|
||||
def _test(metaclass):
|
||||
class Eiffel:
|
||||
__metaclass__ = metaclass
|
||||
|
||||
class Test(Eiffel):
|
||||
|
||||
def m(self, arg):
|
||||
"""Make it a little larger"""
|
||||
return arg + 1
|
||||
|
||||
def m2(self, arg):
|
||||
"""Make it a little larger"""
|
||||
return arg + 1
|
||||
|
||||
def m2_pre(self, arg):
|
||||
assert arg > 0
|
||||
|
||||
def m2_post(self, result, arg):
|
||||
assert result > arg
|
||||
|
||||
class Sub(Test):
|
||||
def m2(self, arg):
|
||||
return arg**2
|
||||
def m2_post(self, Result, arg):
|
||||
super(Sub, self).m2_post(Result, arg)
|
||||
assert Result < 100
|
||||
|
||||
t = Test()
|
||||
t.m(1)
|
||||
t.m2(1)
|
||||
try:
|
||||
t.m2(0)
|
||||
except AssertionError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
s = Sub()
|
||||
try:
|
||||
s.m2(1)
|
||||
except AssertionError:
|
||||
pass # result == arg
|
||||
else:
|
||||
assert False
|
||||
try:
|
||||
s.m2(10)
|
||||
except AssertionError:
|
||||
pass # result == 100
|
||||
else:
|
||||
assert False
|
||||
s.m2(5)
|
||||
|
||||
if __name__ == "__main__":
|
||||
_test(EiffelMetaClass1)
|
||||
_test(EiffelMetaClass2)
|
177
2.7/Python-2.7.16/Demo/newmetaclasses/Enum.py
Normal file
177
2.7/Python-2.7.16/Demo/newmetaclasses/Enum.py
Normal file
@ -0,0 +1,177 @@
|
||||
"""Enumeration metaclass."""
|
||||
|
||||
class EnumMetaclass(type):
|
||||
"""Metaclass for enumeration.
|
||||
|
||||
To define your own enumeration, do something like
|
||||
|
||||
class Color(Enum):
|
||||
red = 1
|
||||
green = 2
|
||||
blue = 3
|
||||
|
||||
Now, Color.red, Color.green and Color.blue behave totally
|
||||
different: they are enumerated values, not integers.
|
||||
|
||||
Enumerations cannot be instantiated; however they can be
|
||||
subclassed.
|
||||
"""
|
||||
|
||||
def __init__(cls, name, bases, dict):
|
||||
super(EnumMetaclass, cls).__init__(name, bases, dict)
|
||||
cls._members = []
|
||||
for attr in dict.keys():
|
||||
if not (attr.startswith('__') and attr.endswith('__')):
|
||||
enumval = EnumInstance(name, attr, dict[attr])
|
||||
setattr(cls, attr, enumval)
|
||||
cls._members.append(attr)
|
||||
|
||||
def __getattr__(cls, name):
|
||||
if name == "__members__":
|
||||
return cls._members
|
||||
raise AttributeError, name
|
||||
|
||||
def __repr__(cls):
|
||||
s1 = s2 = ""
|
||||
enumbases = [base.__name__ for base in cls.__bases__
|
||||
if isinstance(base, EnumMetaclass) and not base is Enum]
|
||||
if enumbases:
|
||||
s1 = "(%s)" % ", ".join(enumbases)
|
||||
enumvalues = ["%s: %d" % (val, getattr(cls, val))
|
||||
for val in cls._members]
|
||||
if enumvalues:
|
||||
s2 = ": {%s}" % ", ".join(enumvalues)
|
||||
return "%s%s%s" % (cls.__name__, s1, s2)
|
||||
|
||||
class FullEnumMetaclass(EnumMetaclass):
|
||||
"""Metaclass for full enumerations.
|
||||
|
||||
A full enumeration displays all the values defined in base classes.
|
||||
"""
|
||||
|
||||
def __init__(cls, name, bases, dict):
|
||||
super(FullEnumMetaclass, cls).__init__(name, bases, dict)
|
||||
for obj in cls.__mro__:
|
||||
if isinstance(obj, EnumMetaclass):
|
||||
for attr in obj._members:
|
||||
# XXX inefficient
|
||||
if not attr in cls._members:
|
||||
cls._members.append(attr)
|
||||
|
||||
class EnumInstance(int):
|
||||
"""Class to represent an enumeration value.
|
||||
|
||||
EnumInstance('Color', 'red', 12) prints as 'Color.red' and behaves
|
||||
like the integer 12 when compared, but doesn't support arithmetic.
|
||||
|
||||
XXX Should it record the actual enumeration rather than just its
|
||||
name?
|
||||
"""
|
||||
|
||||
def __new__(cls, classname, enumname, value):
|
||||
return int.__new__(cls, value)
|
||||
|
||||
def __init__(self, classname, enumname, value):
|
||||
self.__classname = classname
|
||||
self.__enumname = enumname
|
||||
|
||||
def __repr__(self):
|
||||
return "EnumInstance(%s, %s, %d)" % (self.__classname, self.__enumname,
|
||||
self)
|
||||
|
||||
def __str__(self):
|
||||
return "%s.%s" % (self.__classname, self.__enumname)
|
||||
|
||||
class Enum:
|
||||
__metaclass__ = EnumMetaclass
|
||||
|
||||
class FullEnum:
|
||||
__metaclass__ = FullEnumMetaclass
|
||||
|
||||
def _test():
|
||||
|
||||
class Color(Enum):
|
||||
red = 1
|
||||
green = 2
|
||||
blue = 3
|
||||
|
||||
print Color.red
|
||||
|
||||
print repr(Color.red)
|
||||
print Color.red == Color.red
|
||||
print Color.red == Color.blue
|
||||
print Color.red == 1
|
||||
print Color.red == 2
|
||||
|
||||
class ExtendedColor(Color):
|
||||
white = 0
|
||||
orange = 4
|
||||
yellow = 5
|
||||
purple = 6
|
||||
black = 7
|
||||
|
||||
print ExtendedColor.orange
|
||||
print ExtendedColor.red
|
||||
|
||||
print Color.red == ExtendedColor.red
|
||||
|
||||
class OtherColor(Enum):
|
||||
white = 4
|
||||
blue = 5
|
||||
|
||||
class MergedColor(Color, OtherColor):
|
||||
pass
|
||||
|
||||
print MergedColor.red
|
||||
print MergedColor.white
|
||||
|
||||
print Color
|
||||
print ExtendedColor
|
||||
print OtherColor
|
||||
print MergedColor
|
||||
|
||||
def _test2():
|
||||
|
||||
class Color(FullEnum):
|
||||
red = 1
|
||||
green = 2
|
||||
blue = 3
|
||||
|
||||
print Color.red
|
||||
|
||||
print repr(Color.red)
|
||||
print Color.red == Color.red
|
||||
print Color.red == Color.blue
|
||||
print Color.red == 1
|
||||
print Color.red == 2
|
||||
|
||||
class ExtendedColor(Color):
|
||||
white = 0
|
||||
orange = 4
|
||||
yellow = 5
|
||||
purple = 6
|
||||
black = 7
|
||||
|
||||
print ExtendedColor.orange
|
||||
print ExtendedColor.red
|
||||
|
||||
print Color.red == ExtendedColor.red
|
||||
|
||||
class OtherColor(FullEnum):
|
||||
white = 4
|
||||
blue = 5
|
||||
|
||||
class MergedColor(Color, OtherColor):
|
||||
pass
|
||||
|
||||
print MergedColor.red
|
||||
print MergedColor.white
|
||||
|
||||
print Color
|
||||
print ExtendedColor
|
||||
print OtherColor
|
||||
print MergedColor
|
||||
|
||||
if __name__ == '__main__':
|
||||
_test()
|
||||
_test2()
|
6
2.7/Python-2.7.16/Demo/parser/FILES
Normal file
6
2.7/Python-2.7.16/Demo/parser/FILES
Normal file
@ -0,0 +1,6 @@
|
||||
Demo/parser
|
||||
Doc/libparser.tex
|
||||
Lib/AST.py
|
||||
Lib/symbol.py
|
||||
Lib/token.py
|
||||
Modules/parsermodule.c
|
32
2.7/Python-2.7.16/Demo/parser/README
Normal file
32
2.7/Python-2.7.16/Demo/parser/README
Normal file
@ -0,0 +1,32 @@
|
||||
These files are from the large example of using the `parser' module. Refer
|
||||
to the Python Library Reference for more information.
|
||||
|
||||
It also contains examples for the AST parser.
|
||||
|
||||
Files:
|
||||
------
|
||||
|
||||
FILES -- list of files associated with the parser module.
|
||||
|
||||
README -- this file.
|
||||
|
||||
docstring.py -- sample source file containing only a module docstring.
|
||||
|
||||
example.py -- module that uses the `parser' module to extract
|
||||
information from the parse tree of Python source
|
||||
code.
|
||||
|
||||
simple.py -- sample source containing a "short form" definition.
|
||||
|
||||
source.py -- sample source code used to demonstrate ability to
|
||||
handle nested constructs easily using the functions
|
||||
and classes in example.py.
|
||||
|
||||
test_parser.py program to put the parser module through its paces.
|
||||
|
||||
test_unparse.py tests for the unparse module
|
||||
|
||||
unparse.py AST (2.7) based example to recreate source code
|
||||
from an AST.
|
||||
|
||||
Enjoy!
|
2
2.7/Python-2.7.16/Demo/parser/docstring.py
Normal file
2
2.7/Python-2.7.16/Demo/parser/docstring.py
Normal file
@ -0,0 +1,2 @@
|
||||
"""Some documentation.
|
||||
"""
|
190
2.7/Python-2.7.16/Demo/parser/example.py
Normal file
190
2.7/Python-2.7.16/Demo/parser/example.py
Normal file
@ -0,0 +1,190 @@
|
||||
"""Simple code to extract class & function docstrings from a module.
|
||||
|
||||
This code is used as an example in the library reference manual in the
|
||||
section on using the parser module. Refer to the manual for a thorough
|
||||
discussion of the operation of this code.
|
||||
"""
|
||||
|
||||
import os
|
||||
import parser
|
||||
import symbol
|
||||
import token
|
||||
import types
|
||||
|
||||
from types import ListType, TupleType
|
||||
|
||||
|
||||
def get_docs(fileName):
|
||||
"""Retrieve information from the parse tree of a source file.
|
||||
|
||||
fileName
|
||||
Name of the file to read Python source code from.
|
||||
"""
|
||||
source = open(fileName).read()
|
||||
basename = os.path.basename(os.path.splitext(fileName)[0])
|
||||
ast = parser.suite(source)
|
||||
return ModuleInfo(ast.totuple(), basename)
|
||||
|
||||
|
||||
class SuiteInfoBase:
|
||||
_docstring = ''
|
||||
_name = ''
|
||||
|
||||
def __init__(self, tree = None):
|
||||
self._class_info = {}
|
||||
self._function_info = {}
|
||||
if tree:
|
||||
self._extract_info(tree)
|
||||
|
||||
def _extract_info(self, tree):
|
||||
# extract docstring
|
||||
if len(tree) == 2:
|
||||
found, vars = match(DOCSTRING_STMT_PATTERN[1], tree[1])
|
||||
else:
|
||||
found, vars = match(DOCSTRING_STMT_PATTERN, tree[3])
|
||||
if found:
|
||||
self._docstring = eval(vars['docstring'])
|
||||
# discover inner definitions
|
||||
for node in tree[1:]:
|
||||
found, vars = match(COMPOUND_STMT_PATTERN, node)
|
||||
if found:
|
||||
cstmt = vars['compound']
|
||||
if cstmt[0] == symbol.funcdef:
|
||||
name = cstmt[2][1]
|
||||
self._function_info[name] = FunctionInfo(cstmt)
|
||||
elif cstmt[0] == symbol.classdef:
|
||||
name = cstmt[2][1]
|
||||
self._class_info[name] = ClassInfo(cstmt)
|
||||
|
||||
def get_docstring(self):
|
||||
return self._docstring
|
||||
|
||||
def get_name(self):
|
||||
return self._name
|
||||
|
||||
def get_class_names(self):
|
||||
return self._class_info.keys()
|
||||
|
||||
def get_class_info(self, name):
|
||||
return self._class_info[name]
|
||||
|
||||
def __getitem__(self, name):
|
||||
try:
|
||||
return self._class_info[name]
|
||||
except KeyError:
|
||||
return self._function_info[name]
|
||||
|
||||
|
||||
class SuiteFuncInfo:
|
||||
# Mixin class providing access to function names and info.
|
||||
|
||||
def get_function_names(self):
|
||||
return self._function_info.keys()
|
||||
|
||||
def get_function_info(self, name):
|
||||
return self._function_info[name]
|
||||
|
||||
|
||||
class FunctionInfo(SuiteInfoBase, SuiteFuncInfo):
|
||||
def __init__(self, tree = None):
|
||||
self._name = tree[2][1]
|
||||
SuiteInfoBase.__init__(self, tree and tree[-1] or None)
|
||||
|
||||
|
||||
class ClassInfo(SuiteInfoBase):
|
||||
def __init__(self, tree = None):
|
||||
self._name = tree[2][1]
|
||||
SuiteInfoBase.__init__(self, tree and tree[-1] or None)
|
||||
|
||||
def get_method_names(self):
|
||||
return self._function_info.keys()
|
||||
|
||||
def get_method_info(self, name):
|
||||
return self._function_info[name]
|
||||
|
||||
|
||||
class ModuleInfo(SuiteInfoBase, SuiteFuncInfo):
|
||||
def __init__(self, tree = None, name = "<string>"):
|
||||
self._name = name
|
||||
SuiteInfoBase.__init__(self, tree)
|
||||
if tree:
|
||||
found, vars = match(DOCSTRING_STMT_PATTERN, tree[1])
|
||||
if found:
|
||||
self._docstring = vars["docstring"]
|
||||
|
||||
|
||||
def match(pattern, data, vars=None):
|
||||
"""Match `data' to `pattern', with variable extraction.
|
||||
|
||||
pattern
|
||||
Pattern to match against, possibly containing variables.
|
||||
|
||||
data
|
||||
Data to be checked and against which variables are extracted.
|
||||
|
||||
vars
|
||||
Dictionary of variables which have already been found. If not
|
||||
provided, an empty dictionary is created.
|
||||
|
||||
The `pattern' value may contain variables of the form ['varname'] which
|
||||
are allowed to match anything. The value that is matched is returned as
|
||||
part of a dictionary which maps 'varname' to the matched value. 'varname'
|
||||
is not required to be a string object, but using strings makes patterns
|
||||
and the code which uses them more readable.
|
||||
|
||||
This function returns two values: a boolean indicating whether a match
|
||||
was found and a dictionary mapping variable names to their associated
|
||||
values.
|
||||
"""
|
||||
if vars is None:
|
||||
vars = {}
|
||||
if type(pattern) is ListType: # 'variables' are ['varname']
|
||||
vars[pattern[0]] = data
|
||||
return 1, vars
|
||||
if type(pattern) is not TupleType:
|
||||
return (pattern == data), vars
|
||||
if len(data) != len(pattern):
|
||||
return 0, vars
|
||||
for pattern, data in map(None, pattern, data):
|
||||
same, vars = match(pattern, data, vars)
|
||||
if not same:
|
||||
break
|
||||
return same, vars
|
||||
|
||||
|
||||
# This pattern identifies compound statements, allowing them to be readily
|
||||
# differentiated from simple statements.
|
||||
#
|
||||
COMPOUND_STMT_PATTERN = (
|
||||
symbol.stmt,
|
||||
(symbol.compound_stmt, ['compound'])
|
||||
)
|
||||
|
||||
|
||||
# This pattern will match a 'stmt' node which *might* represent a docstring;
|
||||
# docstrings require that the statement which provides the docstring be the
|
||||
# first statement in the class or function, which this pattern does not check.
|
||||
#
|
||||
DOCSTRING_STMT_PATTERN = (
|
||||
symbol.stmt,
|
||||
(symbol.simple_stmt,
|
||||
(symbol.small_stmt,
|
||||
(symbol.expr_stmt,
|
||||
(symbol.testlist,
|
||||
(symbol.test,
|
||||
(symbol.and_test,
|
||||
(symbol.not_test,
|
||||
(symbol.comparison,
|
||||
(symbol.expr,
|
||||
(symbol.xor_expr,
|
||||
(symbol.and_expr,
|
||||
(symbol.shift_expr,
|
||||
(symbol.arith_expr,
|
||||
(symbol.term,
|
||||
(symbol.factor,
|
||||
(symbol.power,
|
||||
(symbol.atom,
|
||||
(token.STRING, ['docstring'])
|
||||
)))))))))))))))),
|
||||
(token.NEWLINE, '')
|
||||
))
|
1
2.7/Python-2.7.16/Demo/parser/simple.py
Normal file
1
2.7/Python-2.7.16/Demo/parser/simple.py
Normal file
@ -0,0 +1 @@
|
||||
def f(): "maybe a docstring"
|
27
2.7/Python-2.7.16/Demo/parser/source.py
Normal file
27
2.7/Python-2.7.16/Demo/parser/source.py
Normal file
@ -0,0 +1,27 @@
|
||||
"""Exmaple file to be parsed for the parsermodule example.
|
||||
|
||||
The classes and functions in this module exist only to exhibit the ability
|
||||
of the handling information extraction from nested definitions using parse
|
||||
trees. They shouldn't interest you otherwise!
|
||||
"""
|
||||
|
||||
class Simple:
|
||||
"This class does very little."
|
||||
|
||||
def method(self):
|
||||
"This method does almost nothing."
|
||||
return 1
|
||||
|
||||
class Nested:
|
||||
"This is a nested class."
|
||||
|
||||
def nested_method(self):
|
||||
"Method of Nested class."
|
||||
def nested_function():
|
||||
"Function in method of Nested class."
|
||||
pass
|
||||
return nested_function
|
||||
|
||||
def function():
|
||||
"This function lives at the module level."
|
||||
return 0
|
48
2.7/Python-2.7.16/Demo/parser/test_parser.py
Normal file
48
2.7/Python-2.7.16/Demo/parser/test_parser.py
Normal file
@ -0,0 +1,48 @@
|
||||
#! /usr/bin/env python
|
||||
# (Force the script to use the latest build.)
|
||||
#
|
||||
# test_parser.py
|
||||
|
||||
import parser, traceback
|
||||
|
||||
_numFailed = 0
|
||||
|
||||
def testChunk(t, fileName):
|
||||
global _numFailed
|
||||
print '----', fileName,
|
||||
try:
|
||||
st = parser.suite(t)
|
||||
tup = parser.st2tuple(st)
|
||||
# this discards the first ST; a huge memory savings when running
|
||||
# against a large source file like Tkinter.py.
|
||||
st = None
|
||||
new = parser.tuple2st(tup)
|
||||
except parser.ParserError, err:
|
||||
print
|
||||
print 'parser module raised exception on input file', fileName + ':'
|
||||
traceback.print_exc()
|
||||
_numFailed = _numFailed + 1
|
||||
else:
|
||||
if tup != parser.st2tuple(new):
|
||||
print
|
||||
print 'parser module failed on input file', fileName
|
||||
_numFailed = _numFailed + 1
|
||||
else:
|
||||
print 'o.k.'
|
||||
|
||||
def testFile(fileName):
|
||||
t = open(fileName).read()
|
||||
testChunk(t, fileName)
|
||||
|
||||
def test():
|
||||
import sys
|
||||
args = sys.argv[1:]
|
||||
if not args:
|
||||
import glob
|
||||
args = glob.glob("*.py")
|
||||
args.sort()
|
||||
map(testFile, args)
|
||||
sys.exit(_numFailed != 0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
213
2.7/Python-2.7.16/Demo/parser/test_unparse.py
Normal file
213
2.7/Python-2.7.16/Demo/parser/test_unparse.py
Normal file
@ -0,0 +1,213 @@
|
||||
import unittest
|
||||
from test import test_support
|
||||
import cStringIO
|
||||
import sys
|
||||
import os
|
||||
import tokenize
|
||||
import ast
|
||||
import unparse
|
||||
|
||||
def read_pyfile(filename):
|
||||
"""Read and return the contents of a Python source file (as a
|
||||
string), taking into account the file encoding."""
|
||||
with open(filename, "r") as pyfile:
|
||||
source = pyfile.read()
|
||||
return source
|
||||
|
||||
for_else = """\
|
||||
def f():
|
||||
for x in range(10):
|
||||
break
|
||||
else:
|
||||
y = 2
|
||||
z = 3
|
||||
"""
|
||||
|
||||
while_else = """\
|
||||
def g():
|
||||
while True:
|
||||
break
|
||||
else:
|
||||
y = 2
|
||||
z = 3
|
||||
"""
|
||||
|
||||
relative_import = """\
|
||||
from . import fred
|
||||
from .. import barney
|
||||
from .australia import shrimp as prawns
|
||||
"""
|
||||
|
||||
class_decorator = """\
|
||||
@f1(arg)
|
||||
@f2
|
||||
class Foo: pass
|
||||
"""
|
||||
|
||||
elif1 = """\
|
||||
if cond1:
|
||||
suite1
|
||||
elif cond2:
|
||||
suite2
|
||||
else:
|
||||
suite3
|
||||
"""
|
||||
|
||||
elif2 = """\
|
||||
if cond1:
|
||||
suite1
|
||||
elif cond2:
|
||||
suite2
|
||||
"""
|
||||
|
||||
try_except_finally = """\
|
||||
try:
|
||||
suite1
|
||||
except ex1:
|
||||
suite2
|
||||
except ex2:
|
||||
suite3
|
||||
else:
|
||||
suite4
|
||||
finally:
|
||||
suite5
|
||||
"""
|
||||
|
||||
class ASTTestCase(unittest.TestCase):
|
||||
def assertASTEqual(self, ast1, ast2):
|
||||
dump1 = ast.dump(ast1)
|
||||
dump2 = ast.dump(ast2)
|
||||
self.assertEqual(ast.dump(ast1), ast.dump(ast2))
|
||||
|
||||
def check_roundtrip(self, code1, filename="internal"):
|
||||
ast1 = compile(code1, filename, "exec", ast.PyCF_ONLY_AST)
|
||||
unparse_buffer = cStringIO.StringIO()
|
||||
unparse.Unparser(ast1, unparse_buffer)
|
||||
code2 = unparse_buffer.getvalue()
|
||||
ast2 = compile(code2, filename, "exec", ast.PyCF_ONLY_AST)
|
||||
self.assertASTEqual(ast1, ast2)
|
||||
|
||||
class UnparseTestCase(ASTTestCase):
|
||||
# Tests for specific bugs found in earlier versions of unparse
|
||||
|
||||
def test_del_statement(self):
|
||||
self.check_roundtrip("del x, y, z")
|
||||
|
||||
def test_shifts(self):
|
||||
self.check_roundtrip("45 << 2")
|
||||
self.check_roundtrip("13 >> 7")
|
||||
|
||||
def test_for_else(self):
|
||||
self.check_roundtrip(for_else)
|
||||
|
||||
def test_while_else(self):
|
||||
self.check_roundtrip(while_else)
|
||||
|
||||
def test_unary_parens(self):
|
||||
self.check_roundtrip("(-1)**7")
|
||||
self.check_roundtrip("(-1.)**8")
|
||||
self.check_roundtrip("(-1j)**6")
|
||||
self.check_roundtrip("not True or False")
|
||||
self.check_roundtrip("True or not False")
|
||||
|
||||
def test_integer_parens(self):
|
||||
self.check_roundtrip("3 .__abs__()")
|
||||
|
||||
def test_huge_float(self):
|
||||
self.check_roundtrip("1e1000")
|
||||
self.check_roundtrip("-1e1000")
|
||||
self.check_roundtrip("1e1000j")
|
||||
self.check_roundtrip("-1e1000j")
|
||||
|
||||
def test_min_int(self):
|
||||
self.check_roundtrip(str(-sys.maxint-1))
|
||||
self.check_roundtrip("-(%s)" % (sys.maxint + 1))
|
||||
|
||||
def test_imaginary_literals(self):
|
||||
self.check_roundtrip("7j")
|
||||
self.check_roundtrip("-7j")
|
||||
self.check_roundtrip("-(7j)")
|
||||
self.check_roundtrip("0j")
|
||||
self.check_roundtrip("-0j")
|
||||
self.check_roundtrip("-(0j)")
|
||||
|
||||
def test_negative_zero(self):
|
||||
self.check_roundtrip("-0")
|
||||
self.check_roundtrip("-(0)")
|
||||
self.check_roundtrip("-0b0")
|
||||
self.check_roundtrip("-(0b0)")
|
||||
self.check_roundtrip("-0o0")
|
||||
self.check_roundtrip("-(0o0)")
|
||||
self.check_roundtrip("-0x0")
|
||||
self.check_roundtrip("-(0x0)")
|
||||
|
||||
def test_lambda_parentheses(self):
|
||||
self.check_roundtrip("(lambda: int)()")
|
||||
|
||||
def test_chained_comparisons(self):
|
||||
self.check_roundtrip("1 < 4 <= 5")
|
||||
self.check_roundtrip("a is b is c is not d")
|
||||
|
||||
def test_function_arguments(self):
|
||||
self.check_roundtrip("def f(): pass")
|
||||
self.check_roundtrip("def f(a): pass")
|
||||
self.check_roundtrip("def f(b = 2): pass")
|
||||
self.check_roundtrip("def f(a, b): pass")
|
||||
self.check_roundtrip("def f(a, b = 2): pass")
|
||||
self.check_roundtrip("def f(a = 5, b = 2): pass")
|
||||
self.check_roundtrip("def f(*args, **kwargs): pass")
|
||||
|
||||
def test_relative_import(self):
|
||||
self.check_roundtrip(relative_import)
|
||||
|
||||
def test_bytes(self):
|
||||
self.check_roundtrip("b'123'")
|
||||
|
||||
def test_set_literal(self):
|
||||
self.check_roundtrip("{'a', 'b', 'c'}")
|
||||
|
||||
def test_set_comprehension(self):
|
||||
self.check_roundtrip("{x for x in range(5)}")
|
||||
|
||||
def test_dict_comprehension(self):
|
||||
self.check_roundtrip("{x: x*x for x in range(10)}")
|
||||
|
||||
def test_class_decorators(self):
|
||||
self.check_roundtrip(class_decorator)
|
||||
|
||||
def test_elifs(self):
|
||||
self.check_roundtrip(elif1)
|
||||
self.check_roundtrip(elif2)
|
||||
|
||||
def test_try_except_finally(self):
|
||||
self.check_roundtrip(try_except_finally)
|
||||
|
||||
class DirectoryTestCase(ASTTestCase):
|
||||
"""Test roundtrip behaviour on all files in Lib and Lib/test."""
|
||||
|
||||
# test directories, relative to the root of the distribution
|
||||
test_directories = 'Lib', os.path.join('Lib', 'test')
|
||||
|
||||
def test_files(self):
|
||||
# get names of files to test
|
||||
dist_dir = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)
|
||||
|
||||
names = []
|
||||
for d in self.test_directories:
|
||||
test_dir = os.path.join(dist_dir, d)
|
||||
for n in os.listdir(test_dir):
|
||||
if n.endswith('.py') and not n.startswith('bad'):
|
||||
names.append(os.path.join(test_dir, n))
|
||||
|
||||
for filename in names:
|
||||
if test_support.verbose:
|
||||
print('Testing %s' % filename)
|
||||
source = read_pyfile(filename)
|
||||
self.check_roundtrip(source)
|
||||
|
||||
|
||||
def test_main():
|
||||
test_support.run_unittest(UnparseTestCase, DirectoryTestCase)
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_main()
|
606
2.7/Python-2.7.16/Demo/parser/unparse.py
Normal file
606
2.7/Python-2.7.16/Demo/parser/unparse.py
Normal file
@ -0,0 +1,606 @@
|
||||
"Usage: unparse.py <path to source file>"
|
||||
import sys
|
||||
import ast
|
||||
import cStringIO
|
||||
import os
|
||||
|
||||
# Large float and imaginary literals get turned into infinities in the AST.
|
||||
# We unparse those infinities to INFSTR.
|
||||
INFSTR = "1e" + repr(sys.float_info.max_10_exp + 1)
|
||||
|
||||
def interleave(inter, f, seq):
|
||||
"""Call f on each item in seq, calling inter() in between.
|
||||
"""
|
||||
seq = iter(seq)
|
||||
try:
|
||||
f(next(seq))
|
||||
except StopIteration:
|
||||
pass
|
||||
else:
|
||||
for x in seq:
|
||||
inter()
|
||||
f(x)
|
||||
|
||||
class Unparser:
|
||||
"""Methods in this class recursively traverse an AST and
|
||||
output source code for the abstract syntax; original formatting
|
||||
is disregarded. """
|
||||
|
||||
def __init__(self, tree, file = sys.stdout):
|
||||
"""Unparser(tree, file=sys.stdout) -> None.
|
||||
Print the source for tree to file."""
|
||||
self.f = file
|
||||
self.future_imports = []
|
||||
self._indent = 0
|
||||
self.dispatch(tree)
|
||||
self.f.write("")
|
||||
self.f.flush()
|
||||
|
||||
def fill(self, text = ""):
|
||||
"Indent a piece of text, according to the current indentation level"
|
||||
self.f.write("\n"+" "*self._indent + text)
|
||||
|
||||
def write(self, text):
|
||||
"Append a piece of text to the current line."
|
||||
self.f.write(text)
|
||||
|
||||
def enter(self):
|
||||
"Print ':', and increase the indentation."
|
||||
self.write(":")
|
||||
self._indent += 1
|
||||
|
||||
def leave(self):
|
||||
"Decrease the indentation level."
|
||||
self._indent -= 1
|
||||
|
||||
def dispatch(self, tree):
|
||||
"Dispatcher function, dispatching tree type T to method _T."
|
||||
if isinstance(tree, list):
|
||||
for t in tree:
|
||||
self.dispatch(t)
|
||||
return
|
||||
meth = getattr(self, "_"+tree.__class__.__name__)
|
||||
meth(tree)
|
||||
|
||||
|
||||
############### Unparsing methods ######################
|
||||
# There should be one method per concrete grammar type #
|
||||
# Constructors should be grouped by sum type. Ideally, #
|
||||
# this would follow the order in the grammar, but #
|
||||
# currently doesn't. #
|
||||
########################################################
|
||||
|
||||
def _Module(self, tree):
|
||||
for stmt in tree.body:
|
||||
self.dispatch(stmt)
|
||||
|
||||
# stmt
|
||||
def _Expr(self, tree):
|
||||
self.fill()
|
||||
self.dispatch(tree.value)
|
||||
|
||||
def _Import(self, t):
|
||||
self.fill("import ")
|
||||
interleave(lambda: self.write(", "), self.dispatch, t.names)
|
||||
|
||||
def _ImportFrom(self, t):
|
||||
# A from __future__ import may affect unparsing, so record it.
|
||||
if t.module and t.module == '__future__':
|
||||
self.future_imports.extend(n.name for n in t.names)
|
||||
|
||||
self.fill("from ")
|
||||
self.write("." * t.level)
|
||||
if t.module:
|
||||
self.write(t.module)
|
||||
self.write(" import ")
|
||||
interleave(lambda: self.write(", "), self.dispatch, t.names)
|
||||
|
||||
def _Assign(self, t):
|
||||
self.fill()
|
||||
for target in t.targets:
|
||||
self.dispatch(target)
|
||||
self.write(" = ")
|
||||
self.dispatch(t.value)
|
||||
|
||||
def _AugAssign(self, t):
|
||||
self.fill()
|
||||
self.dispatch(t.target)
|
||||
self.write(" "+self.binop[t.op.__class__.__name__]+"= ")
|
||||
self.dispatch(t.value)
|
||||
|
||||
def _Return(self, t):
|
||||
self.fill("return")
|
||||
if t.value:
|
||||
self.write(" ")
|
||||
self.dispatch(t.value)
|
||||
|
||||
def _Pass(self, t):
|
||||
self.fill("pass")
|
||||
|
||||
def _Break(self, t):
|
||||
self.fill("break")
|
||||
|
||||
def _Continue(self, t):
|
||||
self.fill("continue")
|
||||
|
||||
def _Delete(self, t):
|
||||
self.fill("del ")
|
||||
interleave(lambda: self.write(", "), self.dispatch, t.targets)
|
||||
|
||||
def _Assert(self, t):
|
||||
self.fill("assert ")
|
||||
self.dispatch(t.test)
|
||||
if t.msg:
|
||||
self.write(", ")
|
||||
self.dispatch(t.msg)
|
||||
|
||||
def _Exec(self, t):
|
||||
self.fill("exec ")
|
||||
self.dispatch(t.body)
|
||||
if t.globals:
|
||||
self.write(" in ")
|
||||
self.dispatch(t.globals)
|
||||
if t.locals:
|
||||
self.write(", ")
|
||||
self.dispatch(t.locals)
|
||||
|
||||
def _Print(self, t):
|
||||
self.fill("print ")
|
||||
do_comma = False
|
||||
if t.dest:
|
||||
self.write(">>")
|
||||
self.dispatch(t.dest)
|
||||
do_comma = True
|
||||
for e in t.values:
|
||||
if do_comma:self.write(", ")
|
||||
else:do_comma=True
|
||||
self.dispatch(e)
|
||||
if not t.nl:
|
||||
self.write(",")
|
||||
|
||||
def _Global(self, t):
|
||||
self.fill("global ")
|
||||
interleave(lambda: self.write(", "), self.write, t.names)
|
||||
|
||||
def _Yield(self, t):
|
||||
self.write("(")
|
||||
self.write("yield")
|
||||
if t.value:
|
||||
self.write(" ")
|
||||
self.dispatch(t.value)
|
||||
self.write(")")
|
||||
|
||||
def _Raise(self, t):
|
||||
self.fill('raise ')
|
||||
if t.type:
|
||||
self.dispatch(t.type)
|
||||
if t.inst:
|
||||
self.write(", ")
|
||||
self.dispatch(t.inst)
|
||||
if t.tback:
|
||||
self.write(", ")
|
||||
self.dispatch(t.tback)
|
||||
|
||||
def _TryExcept(self, t):
|
||||
self.fill("try")
|
||||
self.enter()
|
||||
self.dispatch(t.body)
|
||||
self.leave()
|
||||
|
||||
for ex in t.handlers:
|
||||
self.dispatch(ex)
|
||||
if t.orelse:
|
||||
self.fill("else")
|
||||
self.enter()
|
||||
self.dispatch(t.orelse)
|
||||
self.leave()
|
||||
|
||||
def _TryFinally(self, t):
|
||||
if len(t.body) == 1 and isinstance(t.body[0], ast.TryExcept):
|
||||
# try-except-finally
|
||||
self.dispatch(t.body)
|
||||
else:
|
||||
self.fill("try")
|
||||
self.enter()
|
||||
self.dispatch(t.body)
|
||||
self.leave()
|
||||
|
||||
self.fill("finally")
|
||||
self.enter()
|
||||
self.dispatch(t.finalbody)
|
||||
self.leave()
|
||||
|
||||
def _ExceptHandler(self, t):
|
||||
self.fill("except")
|
||||
if t.type:
|
||||
self.write(" ")
|
||||
self.dispatch(t.type)
|
||||
if t.name:
|
||||
self.write(" as ")
|
||||
self.dispatch(t.name)
|
||||
self.enter()
|
||||
self.dispatch(t.body)
|
||||
self.leave()
|
||||
|
||||
def _ClassDef(self, t):
|
||||
self.write("\n")
|
||||
for deco in t.decorator_list:
|
||||
self.fill("@")
|
||||
self.dispatch(deco)
|
||||
self.fill("class "+t.name)
|
||||
if t.bases:
|
||||
self.write("(")
|
||||
for a in t.bases:
|
||||
self.dispatch(a)
|
||||
self.write(", ")
|
||||
self.write(")")
|
||||
self.enter()
|
||||
self.dispatch(t.body)
|
||||
self.leave()
|
||||
|
||||
def _FunctionDef(self, t):
|
||||
self.write("\n")
|
||||
for deco in t.decorator_list:
|
||||
self.fill("@")
|
||||
self.dispatch(deco)
|
||||
self.fill("def "+t.name + "(")
|
||||
self.dispatch(t.args)
|
||||
self.write(")")
|
||||
self.enter()
|
||||
self.dispatch(t.body)
|
||||
self.leave()
|
||||
|
||||
def _For(self, t):
|
||||
self.fill("for ")
|
||||
self.dispatch(t.target)
|
||||
self.write(" in ")
|
||||
self.dispatch(t.iter)
|
||||
self.enter()
|
||||
self.dispatch(t.body)
|
||||
self.leave()
|
||||
if t.orelse:
|
||||
self.fill("else")
|
||||
self.enter()
|
||||
self.dispatch(t.orelse)
|
||||
self.leave()
|
||||
|
||||
def _If(self, t):
|
||||
self.fill("if ")
|
||||
self.dispatch(t.test)
|
||||
self.enter()
|
||||
self.dispatch(t.body)
|
||||
self.leave()
|
||||
# collapse nested ifs into equivalent elifs.
|
||||
while (t.orelse and len(t.orelse) == 1 and
|
||||
isinstance(t.orelse[0], ast.If)):
|
||||
t = t.orelse[0]
|
||||
self.fill("elif ")
|
||||
self.dispatch(t.test)
|
||||
self.enter()
|
||||
self.dispatch(t.body)
|
||||
self.leave()
|
||||
# final else
|
||||
if t.orelse:
|
||||
self.fill("else")
|
||||
self.enter()
|
||||
self.dispatch(t.orelse)
|
||||
self.leave()
|
||||
|
||||
def _While(self, t):
|
||||
self.fill("while ")
|
||||
self.dispatch(t.test)
|
||||
self.enter()
|
||||
self.dispatch(t.body)
|
||||
self.leave()
|
||||
if t.orelse:
|
||||
self.fill("else")
|
||||
self.enter()
|
||||
self.dispatch(t.orelse)
|
||||
self.leave()
|
||||
|
||||
def _With(self, t):
|
||||
self.fill("with ")
|
||||
self.dispatch(t.context_expr)
|
||||
if t.optional_vars:
|
||||
self.write(" as ")
|
||||
self.dispatch(t.optional_vars)
|
||||
self.enter()
|
||||
self.dispatch(t.body)
|
||||
self.leave()
|
||||
|
||||
# expr
|
||||
def _Str(self, tree):
|
||||
# if from __future__ import unicode_literals is in effect,
|
||||
# then we want to output string literals using a 'b' prefix
|
||||
# and unicode literals with no prefix.
|
||||
if "unicode_literals" not in self.future_imports:
|
||||
self.write(repr(tree.s))
|
||||
elif isinstance(tree.s, str):
|
||||
self.write("b" + repr(tree.s))
|
||||
elif isinstance(tree.s, unicode):
|
||||
self.write(repr(tree.s).lstrip("u"))
|
||||
else:
|
||||
assert False, "shouldn't get here"
|
||||
|
||||
def _Name(self, t):
|
||||
self.write(t.id)
|
||||
|
||||
def _Repr(self, t):
|
||||
self.write("`")
|
||||
self.dispatch(t.value)
|
||||
self.write("`")
|
||||
|
||||
def _Num(self, t):
|
||||
repr_n = repr(t.n)
|
||||
# Parenthesize negative numbers, to avoid turning (-1)**2 into -1**2.
|
||||
if repr_n.startswith("-"):
|
||||
self.write("(")
|
||||
# Substitute overflowing decimal literal for AST infinities.
|
||||
self.write(repr_n.replace("inf", INFSTR))
|
||||
if repr_n.startswith("-"):
|
||||
self.write(")")
|
||||
|
||||
def _List(self, t):
|
||||
self.write("[")
|
||||
interleave(lambda: self.write(", "), self.dispatch, t.elts)
|
||||
self.write("]")
|
||||
|
||||
def _ListComp(self, t):
|
||||
self.write("[")
|
||||
self.dispatch(t.elt)
|
||||
for gen in t.generators:
|
||||
self.dispatch(gen)
|
||||
self.write("]")
|
||||
|
||||
def _GeneratorExp(self, t):
|
||||
self.write("(")
|
||||
self.dispatch(t.elt)
|
||||
for gen in t.generators:
|
||||
self.dispatch(gen)
|
||||
self.write(")")
|
||||
|
||||
def _SetComp(self, t):
|
||||
self.write("{")
|
||||
self.dispatch(t.elt)
|
||||
for gen in t.generators:
|
||||
self.dispatch(gen)
|
||||
self.write("}")
|
||||
|
||||
def _DictComp(self, t):
|
||||
self.write("{")
|
||||
self.dispatch(t.key)
|
||||
self.write(": ")
|
||||
self.dispatch(t.value)
|
||||
for gen in t.generators:
|
||||
self.dispatch(gen)
|
||||
self.write("}")
|
||||
|
||||
def _comprehension(self, t):
|
||||
self.write(" for ")
|
||||
self.dispatch(t.target)
|
||||
self.write(" in ")
|
||||
self.dispatch(t.iter)
|
||||
for if_clause in t.ifs:
|
||||
self.write(" if ")
|
||||
self.dispatch(if_clause)
|
||||
|
||||
def _IfExp(self, t):
|
||||
self.write("(")
|
||||
self.dispatch(t.body)
|
||||
self.write(" if ")
|
||||
self.dispatch(t.test)
|
||||
self.write(" else ")
|
||||
self.dispatch(t.orelse)
|
||||
self.write(")")
|
||||
|
||||
def _Set(self, t):
|
||||
assert(t.elts) # should be at least one element
|
||||
self.write("{")
|
||||
interleave(lambda: self.write(", "), self.dispatch, t.elts)
|
||||
self.write("}")
|
||||
|
||||
def _Dict(self, t):
|
||||
self.write("{")
|
||||
def write_pair(pair):
|
||||
(k, v) = pair
|
||||
self.dispatch(k)
|
||||
self.write(": ")
|
||||
self.dispatch(v)
|
||||
interleave(lambda: self.write(", "), write_pair, zip(t.keys, t.values))
|
||||
self.write("}")
|
||||
|
||||
def _Tuple(self, t):
|
||||
self.write("(")
|
||||
if len(t.elts) == 1:
|
||||
(elt,) = t.elts
|
||||
self.dispatch(elt)
|
||||
self.write(",")
|
||||
else:
|
||||
interleave(lambda: self.write(", "), self.dispatch, t.elts)
|
||||
self.write(")")
|
||||
|
||||
unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"}
|
||||
def _UnaryOp(self, t):
|
||||
self.write("(")
|
||||
self.write(self.unop[t.op.__class__.__name__])
|
||||
self.write(" ")
|
||||
# If we're applying unary minus to a number, parenthesize the number.
|
||||
# This is necessary: -2147483648 is different from -(2147483648) on
|
||||
# a 32-bit machine (the first is an int, the second a long), and
|
||||
# -7j is different from -(7j). (The first has real part 0.0, the second
|
||||
# has real part -0.0.)
|
||||
if isinstance(t.op, ast.USub) and isinstance(t.operand, ast.Num):
|
||||
self.write("(")
|
||||
self.dispatch(t.operand)
|
||||
self.write(")")
|
||||
else:
|
||||
self.dispatch(t.operand)
|
||||
self.write(")")
|
||||
|
||||
binop = { "Add":"+", "Sub":"-", "Mult":"*", "Div":"/", "Mod":"%",
|
||||
"LShift":"<<", "RShift":">>", "BitOr":"|", "BitXor":"^", "BitAnd":"&",
|
||||
"FloorDiv":"//", "Pow": "**"}
|
||||
def _BinOp(self, t):
|
||||
self.write("(")
|
||||
self.dispatch(t.left)
|
||||
self.write(" " + self.binop[t.op.__class__.__name__] + " ")
|
||||
self.dispatch(t.right)
|
||||
self.write(")")
|
||||
|
||||
cmpops = {"Eq":"==", "NotEq":"!=", "Lt":"<", "LtE":"<=", "Gt":">", "GtE":">=",
|
||||
"Is":"is", "IsNot":"is not", "In":"in", "NotIn":"not in"}
|
||||
def _Compare(self, t):
|
||||
self.write("(")
|
||||
self.dispatch(t.left)
|
||||
for o, e in zip(t.ops, t.comparators):
|
||||
self.write(" " + self.cmpops[o.__class__.__name__] + " ")
|
||||
self.dispatch(e)
|
||||
self.write(")")
|
||||
|
||||
boolops = {ast.And: 'and', ast.Or: 'or'}
|
||||
def _BoolOp(self, t):
|
||||
self.write("(")
|
||||
s = " %s " % self.boolops[t.op.__class__]
|
||||
interleave(lambda: self.write(s), self.dispatch, t.values)
|
||||
self.write(")")
|
||||
|
||||
def _Attribute(self,t):
|
||||
self.dispatch(t.value)
|
||||
# Special case: 3.__abs__() is a syntax error, so if t.value
|
||||
# is an integer literal then we need to either parenthesize
|
||||
# it or add an extra space to get 3 .__abs__().
|
||||
if isinstance(t.value, ast.Num) and isinstance(t.value.n, int):
|
||||
self.write(" ")
|
||||
self.write(".")
|
||||
self.write(t.attr)
|
||||
|
||||
def _Call(self, t):
|
||||
self.dispatch(t.func)
|
||||
self.write("(")
|
||||
comma = False
|
||||
for e in t.args:
|
||||
if comma: self.write(", ")
|
||||
else: comma = True
|
||||
self.dispatch(e)
|
||||
for e in t.keywords:
|
||||
if comma: self.write(", ")
|
||||
else: comma = True
|
||||
self.dispatch(e)
|
||||
if t.starargs:
|
||||
if comma: self.write(", ")
|
||||
else: comma = True
|
||||
self.write("*")
|
||||
self.dispatch(t.starargs)
|
||||
if t.kwargs:
|
||||
if comma: self.write(", ")
|
||||
else: comma = True
|
||||
self.write("**")
|
||||
self.dispatch(t.kwargs)
|
||||
self.write(")")
|
||||
|
||||
def _Subscript(self, t):
|
||||
self.dispatch(t.value)
|
||||
self.write("[")
|
||||
self.dispatch(t.slice)
|
||||
self.write("]")
|
||||
|
||||
# slice
|
||||
def _Ellipsis(self, t):
|
||||
self.write("...")
|
||||
|
||||
def _Index(self, t):
|
||||
self.dispatch(t.value)
|
||||
|
||||
def _Slice(self, t):
|
||||
if t.lower:
|
||||
self.dispatch(t.lower)
|
||||
self.write(":")
|
||||
if t.upper:
|
||||
self.dispatch(t.upper)
|
||||
if t.step:
|
||||
self.write(":")
|
||||
self.dispatch(t.step)
|
||||
|
||||
def _ExtSlice(self, t):
|
||||
interleave(lambda: self.write(', '), self.dispatch, t.dims)
|
||||
|
||||
# others
|
||||
def _arguments(self, t):
|
||||
first = True
|
||||
# normal arguments
|
||||
defaults = [None] * (len(t.args) - len(t.defaults)) + t.defaults
|
||||
for a,d in zip(t.args, defaults):
|
||||
if first:first = False
|
||||
else: self.write(", ")
|
||||
self.dispatch(a),
|
||||
if d:
|
||||
self.write("=")
|
||||
self.dispatch(d)
|
||||
|
||||
# varargs
|
||||
if t.vararg:
|
||||
if first:first = False
|
||||
else: self.write(", ")
|
||||
self.write("*")
|
||||
self.write(t.vararg)
|
||||
|
||||
# kwargs
|
||||
if t.kwarg:
|
||||
if first:first = False
|
||||
else: self.write(", ")
|
||||
self.write("**"+t.kwarg)
|
||||
|
||||
def _keyword(self, t):
|
||||
self.write(t.arg)
|
||||
self.write("=")
|
||||
self.dispatch(t.value)
|
||||
|
||||
def _Lambda(self, t):
|
||||
self.write("(")
|
||||
self.write("lambda ")
|
||||
self.dispatch(t.args)
|
||||
self.write(": ")
|
||||
self.dispatch(t.body)
|
||||
self.write(")")
|
||||
|
||||
def _alias(self, t):
|
||||
self.write(t.name)
|
||||
if t.asname:
|
||||
self.write(" as "+t.asname)
|
||||
|
||||
def roundtrip(filename, output=sys.stdout):
|
||||
with open(filename, "r") as pyfile:
|
||||
source = pyfile.read()
|
||||
tree = compile(source, filename, "exec", ast.PyCF_ONLY_AST)
|
||||
Unparser(tree, output)
|
||||
|
||||
|
||||
|
||||
def testdir(a):
|
||||
try:
|
||||
names = [n for n in os.listdir(a) if n.endswith('.py')]
|
||||
except OSError:
|
||||
sys.stderr.write("Directory not readable: %s" % a)
|
||||
else:
|
||||
for n in names:
|
||||
fullname = os.path.join(a, n)
|
||||
if os.path.isfile(fullname):
|
||||
output = cStringIO.StringIO()
|
||||
print 'Testing %s' % fullname
|
||||
try:
|
||||
roundtrip(fullname, output)
|
||||
except Exception as e:
|
||||
print ' Failed to compile, exception is %s' % repr(e)
|
||||
elif os.path.isdir(fullname):
|
||||
testdir(fullname)
|
||||
|
||||
def main(args):
|
||||
if args[0] == '--testdir':
|
||||
for a in args[1:]:
|
||||
testdir(a)
|
||||
else:
|
||||
for a in args:
|
||||
roundtrip(a)
|
||||
|
||||
if __name__=='__main__':
|
||||
main(sys.argv[1:])
|
301
2.7/Python-2.7.16/Demo/pdist/FSProxy.py
Normal file
301
2.7/Python-2.7.16/Demo/pdist/FSProxy.py
Normal file
@ -0,0 +1,301 @@
|
||||
"""File System Proxy.
|
||||
|
||||
Provide an OS-neutral view on a file system, locally or remotely.
|
||||
The functionality is geared towards implementing some sort of
|
||||
rdist-like utility between a Mac and a UNIX system.
|
||||
|
||||
The module defines three classes:
|
||||
|
||||
FSProxyLocal -- used for local access
|
||||
FSProxyServer -- used on the server side of remote access
|
||||
FSProxyClient -- used on the client side of remote access
|
||||
|
||||
The remote classes are instantiated with an IP address and an optional
|
||||
verbosity flag.
|
||||
"""
|
||||
|
||||
import server
|
||||
import client
|
||||
import md5
|
||||
import os
|
||||
import fnmatch
|
||||
from stat import *
|
||||
import time
|
||||
import fnmatch
|
||||
|
||||
maxnamelen = 255
|
||||
|
||||
skipnames = (os.curdir, os.pardir)
|
||||
|
||||
|
||||
class FSProxyLocal:
|
||||
|
||||
def __init__(self):
|
||||
self._dirstack = []
|
||||
self._ignore = ['*.pyc'] + self._readignore()
|
||||
|
||||
def _close(self):
|
||||
while self._dirstack:
|
||||
self.back()
|
||||
|
||||
def _readignore(self):
|
||||
file = self._hide('ignore')
|
||||
try:
|
||||
f = open(file)
|
||||
except IOError:
|
||||
file = self._hide('synctree.ignorefiles')
|
||||
try:
|
||||
f = open(file)
|
||||
except IOError:
|
||||
return []
|
||||
ignore = []
|
||||
while 1:
|
||||
line = f.readline()
|
||||
if not line: break
|
||||
if line[-1] == '\n': line = line[:-1]
|
||||
ignore.append(line)
|
||||
f.close()
|
||||
return ignore
|
||||
|
||||
def _hidden(self, name):
|
||||
return name[0] == '.'
|
||||
|
||||
def _hide(self, name):
|
||||
return '.%s' % name
|
||||
|
||||
def visible(self, name):
|
||||
if len(name) > maxnamelen: return 0
|
||||
if name[-1] == '~': return 0
|
||||
if name in skipnames: return 0
|
||||
if self._hidden(name): return 0
|
||||
head, tail = os.path.split(name)
|
||||
if head or not tail: return 0
|
||||
if os.path.islink(name): return 0
|
||||
if '\0' in open(name, 'rb').read(512): return 0
|
||||
for ign in self._ignore:
|
||||
if fnmatch.fnmatch(name, ign): return 0
|
||||
return 1
|
||||
|
||||
def check(self, name):
|
||||
if not self.visible(name):
|
||||
raise os.error, "protected name %s" % repr(name)
|
||||
|
||||
def checkfile(self, name):
|
||||
self.check(name)
|
||||
if not os.path.isfile(name):
|
||||
raise os.error, "not a plain file %s" % repr(name)
|
||||
|
||||
def pwd(self):
|
||||
return os.getcwd()
|
||||
|
||||
def cd(self, name):
|
||||
self.check(name)
|
||||
save = os.getcwd(), self._ignore
|
||||
os.chdir(name)
|
||||
self._dirstack.append(save)
|
||||
self._ignore = self._ignore + self._readignore()
|
||||
|
||||
def back(self):
|
||||
if not self._dirstack:
|
||||
raise os.error, "empty directory stack"
|
||||
dir, ignore = self._dirstack[-1]
|
||||
os.chdir(dir)
|
||||
del self._dirstack[-1]
|
||||
self._ignore = ignore
|
||||
|
||||
def _filter(self, files, pat = None):
|
||||
if pat:
|
||||
def keep(name, pat = pat):
|
||||
return fnmatch.fnmatch(name, pat)
|
||||
files = filter(keep, files)
|
||||
files = filter(self.visible, files)
|
||||
files.sort()
|
||||
return files
|
||||
|
||||
def list(self, pat = None):
|
||||
files = os.listdir(os.curdir)
|
||||
return self._filter(files, pat)
|
||||
|
||||
def listfiles(self, pat = None):
|
||||
files = os.listdir(os.curdir)
|
||||
files = filter(os.path.isfile, files)
|
||||
return self._filter(files, pat)
|
||||
|
||||
def listsubdirs(self, pat = None):
|
||||
files = os.listdir(os.curdir)
|
||||
files = filter(os.path.isdir, files)
|
||||
return self._filter(files, pat)
|
||||
|
||||
def exists(self, name):
|
||||
return self.visible(name) and os.path.exists(name)
|
||||
|
||||
def isdir(self, name):
|
||||
return self.visible(name) and os.path.isdir(name)
|
||||
|
||||
def islink(self, name):
|
||||
return self.visible(name) and os.path.islink(name)
|
||||
|
||||
def isfile(self, name):
|
||||
return self.visible(name) and os.path.isfile(name)
|
||||
|
||||
def sum(self, name):
|
||||
self.checkfile(name)
|
||||
BUFFERSIZE = 1024*8
|
||||
f = open(name)
|
||||
sum = md5.new()
|
||||
while 1:
|
||||
buffer = f.read(BUFFERSIZE)
|
||||
if not buffer:
|
||||
break
|
||||
sum.update(buffer)
|
||||
return sum.digest()
|
||||
|
||||
def size(self, name):
|
||||
self.checkfile(name)
|
||||
return os.stat(name)[ST_SIZE]
|
||||
|
||||
def mtime(self, name):
|
||||
self.checkfile(name)
|
||||
return time.localtime(os.stat(name)[ST_MTIME])
|
||||
|
||||
def stat(self, name):
|
||||
self.checkfile(name)
|
||||
size = os.stat(name)[ST_SIZE]
|
||||
mtime = time.localtime(os.stat(name)[ST_MTIME])
|
||||
return size, mtime
|
||||
|
||||
def info(self, name):
|
||||
sum = self.sum(name)
|
||||
size = os.stat(name)[ST_SIZE]
|
||||
mtime = time.localtime(os.stat(name)[ST_MTIME])
|
||||
return sum, size, mtime
|
||||
|
||||
def _list(self, function, list):
|
||||
if list is None:
|
||||
list = self.listfiles()
|
||||
res = []
|
||||
for name in list:
|
||||
try:
|
||||
res.append((name, function(name)))
|
||||
except (os.error, IOError):
|
||||
res.append((name, None))
|
||||
return res
|
||||
|
||||
def sumlist(self, list = None):
|
||||
return self._list(self.sum, list)
|
||||
|
||||
def statlist(self, list = None):
|
||||
return self._list(self.stat, list)
|
||||
|
||||
def mtimelist(self, list = None):
|
||||
return self._list(self.mtime, list)
|
||||
|
||||
def sizelist(self, list = None):
|
||||
return self._list(self.size, list)
|
||||
|
||||
def infolist(self, list = None):
|
||||
return self._list(self.info, list)
|
||||
|
||||
def _dict(self, function, list):
|
||||
if list is None:
|
||||
list = self.listfiles()
|
||||
dict = {}
|
||||
for name in list:
|
||||
try:
|
||||
dict[name] = function(name)
|
||||
except (os.error, IOError):
|
||||
pass
|
||||
return dict
|
||||
|
||||
def sumdict(self, list = None):
|
||||
return self.dict(self.sum, list)
|
||||
|
||||
def sizedict(self, list = None):
|
||||
return self.dict(self.size, list)
|
||||
|
||||
def mtimedict(self, list = None):
|
||||
return self.dict(self.mtime, list)
|
||||
|
||||
def statdict(self, list = None):
|
||||
return self.dict(self.stat, list)
|
||||
|
||||
def infodict(self, list = None):
|
||||
return self._dict(self.info, list)
|
||||
|
||||
def read(self, name, offset = 0, length = -1):
|
||||
self.checkfile(name)
|
||||
f = open(name)
|
||||
f.seek(offset)
|
||||
if length == 0:
|
||||
data = ''
|
||||
elif length < 0:
|
||||
data = f.read()
|
||||
else:
|
||||
data = f.read(length)
|
||||
f.close()
|
||||
return data
|
||||
|
||||
def create(self, name):
|
||||
self.check(name)
|
||||
if os.path.exists(name):
|
||||
self.checkfile(name)
|
||||
bname = name + '~'
|
||||
try:
|
||||
os.unlink(bname)
|
||||
except os.error:
|
||||
pass
|
||||
os.rename(name, bname)
|
||||
f = open(name, 'w')
|
||||
f.close()
|
||||
|
||||
def write(self, name, data, offset = 0):
|
||||
self.checkfile(name)
|
||||
f = open(name, 'r+')
|
||||
f.seek(offset)
|
||||
f.write(data)
|
||||
f.close()
|
||||
|
||||
def mkdir(self, name):
|
||||
self.check(name)
|
||||
os.mkdir(name, 0777)
|
||||
|
||||
def rmdir(self, name):
|
||||
self.check(name)
|
||||
os.rmdir(name)
|
||||
|
||||
|
||||
class FSProxyServer(FSProxyLocal, server.Server):
|
||||
|
||||
def __init__(self, address, verbose = server.VERBOSE):
|
||||
FSProxyLocal.__init__(self)
|
||||
server.Server.__init__(self, address, verbose)
|
||||
|
||||
def _close(self):
|
||||
server.Server._close(self)
|
||||
FSProxyLocal._close(self)
|
||||
|
||||
def _serve(self):
|
||||
server.Server._serve(self)
|
||||
# Retreat into start directory
|
||||
while self._dirstack: self.back()
|
||||
|
||||
|
||||
class FSProxyClient(client.Client):
|
||||
|
||||
def __init__(self, address, verbose = client.VERBOSE):
|
||||
client.Client.__init__(self, address, verbose)
|
||||
|
||||
|
||||
def test():
|
||||
import string
|
||||
import sys
|
||||
if sys.argv[1:]:
|
||||
port = string.atoi(sys.argv[1])
|
||||
else:
|
||||
port = 4127
|
||||
proxy = FSProxyServer(('', port))
|
||||
proxy._serverloop()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
198
2.7/Python-2.7.16/Demo/pdist/RCSProxy.py
Normal file
198
2.7/Python-2.7.16/Demo/pdist/RCSProxy.py
Normal file
@ -0,0 +1,198 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"""RCS Proxy.
|
||||
|
||||
Provide a simplified interface on RCS files, locally or remotely.
|
||||
The functionality is geared towards implementing some sort of
|
||||
remote CVS like utility. It is modeled after the similar module
|
||||
FSProxy.
|
||||
|
||||
The module defines two classes:
|
||||
|
||||
RCSProxyLocal -- used for local access
|
||||
RCSProxyServer -- used on the server side of remote access
|
||||
|
||||
The corresponding client class, RCSProxyClient, is defined in module
|
||||
rcsclient.
|
||||
|
||||
The remote classes are instantiated with an IP address and an optional
|
||||
verbosity flag.
|
||||
"""
|
||||
|
||||
import server
|
||||
import md5
|
||||
import os
|
||||
import fnmatch
|
||||
import string
|
||||
import tempfile
|
||||
import rcslib
|
||||
|
||||
|
||||
class DirSupport:
|
||||
|
||||
def __init__(self):
|
||||
self._dirstack = []
|
||||
|
||||
def __del__(self):
|
||||
self._close()
|
||||
|
||||
def _close(self):
|
||||
while self._dirstack:
|
||||
self.back()
|
||||
|
||||
def pwd(self):
|
||||
return os.getcwd()
|
||||
|
||||
def cd(self, name):
|
||||
save = os.getcwd()
|
||||
os.chdir(name)
|
||||
self._dirstack.append(save)
|
||||
|
||||
def back(self):
|
||||
if not self._dirstack:
|
||||
raise os.error, "empty directory stack"
|
||||
dir = self._dirstack[-1]
|
||||
os.chdir(dir)
|
||||
del self._dirstack[-1]
|
||||
|
||||
def listsubdirs(self, pat = None):
|
||||
files = os.listdir(os.curdir)
|
||||
files = filter(os.path.isdir, files)
|
||||
return self._filter(files, pat)
|
||||
|
||||
def isdir(self, name):
|
||||
return os.path.isdir(name)
|
||||
|
||||
def mkdir(self, name):
|
||||
os.mkdir(name, 0777)
|
||||
|
||||
def rmdir(self, name):
|
||||
os.rmdir(name)
|
||||
|
||||
|
||||
class RCSProxyLocal(rcslib.RCS, DirSupport):
|
||||
|
||||
def __init__(self):
|
||||
rcslib.RCS.__init__(self)
|
||||
DirSupport.__init__(self)
|
||||
|
||||
def __del__(self):
|
||||
DirSupport.__del__(self)
|
||||
rcslib.RCS.__del__(self)
|
||||
|
||||
def sumlist(self, list = None):
|
||||
return self._list(self.sum, list)
|
||||
|
||||
def sumdict(self, list = None):
|
||||
return self._dict(self.sum, list)
|
||||
|
||||
def sum(self, name_rev):
|
||||
f = self._open(name_rev)
|
||||
BUFFERSIZE = 1024*8
|
||||
sum = md5.new()
|
||||
while 1:
|
||||
buffer = f.read(BUFFERSIZE)
|
||||
if not buffer:
|
||||
break
|
||||
sum.update(buffer)
|
||||
self._closepipe(f)
|
||||
return sum.digest()
|
||||
|
||||
def get(self, name_rev):
|
||||
f = self._open(name_rev)
|
||||
data = f.read()
|
||||
self._closepipe(f)
|
||||
return data
|
||||
|
||||
def put(self, name_rev, data, message=None):
|
||||
name, rev = self._unmangle(name_rev)
|
||||
f = open(name, 'w')
|
||||
f.write(data)
|
||||
f.close()
|
||||
self.checkin(name_rev, message)
|
||||
self._remove(name)
|
||||
|
||||
def _list(self, function, list = None):
|
||||
"""INTERNAL: apply FUNCTION to all files in LIST.
|
||||
|
||||
Return a list of the results.
|
||||
|
||||
The list defaults to all files in the directory if None.
|
||||
|
||||
"""
|
||||
if list is None:
|
||||
list = self.listfiles()
|
||||
res = []
|
||||
for name in list:
|
||||
try:
|
||||
res.append((name, function(name)))
|
||||
except (os.error, IOError):
|
||||
res.append((name, None))
|
||||
return res
|
||||
|
||||
def _dict(self, function, list = None):
|
||||
"""INTERNAL: apply FUNCTION to all files in LIST.
|
||||
|
||||
Return a dictionary mapping files to results.
|
||||
|
||||
The list defaults to all files in the directory if None.
|
||||
|
||||
"""
|
||||
if list is None:
|
||||
list = self.listfiles()
|
||||
dict = {}
|
||||
for name in list:
|
||||
try:
|
||||
dict[name] = function(name)
|
||||
except (os.error, IOError):
|
||||
pass
|
||||
return dict
|
||||
|
||||
|
||||
class RCSProxyServer(RCSProxyLocal, server.SecureServer):
|
||||
|
||||
def __init__(self, address, verbose = server.VERBOSE):
|
||||
RCSProxyLocal.__init__(self)
|
||||
server.SecureServer.__init__(self, address, verbose)
|
||||
|
||||
def _close(self):
|
||||
server.SecureServer._close(self)
|
||||
RCSProxyLocal._close(self)
|
||||
|
||||
def _serve(self):
|
||||
server.SecureServer._serve(self)
|
||||
# Retreat into start directory
|
||||
while self._dirstack: self.back()
|
||||
|
||||
|
||||
def test_server():
|
||||
import string
|
||||
import sys
|
||||
if sys.argv[1:]:
|
||||
port = string.atoi(sys.argv[1])
|
||||
else:
|
||||
port = 4127
|
||||
proxy = RCSProxyServer(('', port))
|
||||
proxy._serverloop()
|
||||
|
||||
|
||||
def test():
|
||||
import sys
|
||||
if not sys.argv[1:] or sys.argv[1] and sys.argv[1][0] in '0123456789':
|
||||
test_server()
|
||||
sys.exit(0)
|
||||
proxy = RCSProxyLocal()
|
||||
what = sys.argv[1]
|
||||
if hasattr(proxy, what):
|
||||
attr = getattr(proxy, what)
|
||||
if callable(attr):
|
||||
print apply(attr, tuple(sys.argv[2:]))
|
||||
else:
|
||||
print repr(attr)
|
||||
else:
|
||||
print "%s: no such attribute" % what
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
121
2.7/Python-2.7.16/Demo/pdist/README
Normal file
121
2.7/Python-2.7.16/Demo/pdist/README
Normal file
@ -0,0 +1,121 @@
|
||||
Filesystem, RCS and CVS client and server classes
|
||||
=================================================
|
||||
|
||||
*** See the security warning at the end of this file! ***
|
||||
|
||||
This directory contains various modules and classes that support
|
||||
remote file system operations.
|
||||
|
||||
CVS stuff
|
||||
---------
|
||||
|
||||
rcvs Script to put in your bin directory
|
||||
rcvs.py Remote CVS client command line interface
|
||||
|
||||
cvslib.py CVS admin files classes (used by rrcs)
|
||||
cvslock.py CVS locking algorithms
|
||||
|
||||
RCS stuff
|
||||
---------
|
||||
|
||||
rrcs Script to put in your bin directory
|
||||
rrcs.py Remote RCS client command line interface
|
||||
|
||||
rcsclient.py Return an RCSProxyClient instance
|
||||
(has reasonable default server/port/directory)
|
||||
|
||||
RCSProxy.py RCS proxy and server classes (on top of rcslib.py)
|
||||
|
||||
rcslib.py Local-only RCS base class (affects stdout &
|
||||
local work files)
|
||||
|
||||
FSProxy stuff
|
||||
-------------
|
||||
|
||||
sumtree.py Old demo for FSProxy
|
||||
cmptree.py First FSProxy client (used to sync from the Mac)
|
||||
FSProxy.py Filesystem interface classes
|
||||
|
||||
Generic client/server stuff
|
||||
---------------------------
|
||||
|
||||
client.py Client class
|
||||
server.py Server class
|
||||
|
||||
security.py Security mix-in class (not very secure I think)
|
||||
|
||||
Other generic stuff
|
||||
-------------------
|
||||
|
||||
cmdfw.py CommandFrameWork class
|
||||
(used by rcvs, should be used by rrcs as well)
|
||||
|
||||
|
||||
Client/Server operation
|
||||
-----------------------
|
||||
|
||||
The Client and Server classes implement a simple-minded RPC protocol,
|
||||
using Python's pickle module to transfer arguments, return values and
|
||||
exceptions with the most generality. The Server class is instantiated
|
||||
with a port number on which it should listen for requests; the Client
|
||||
class is instantiated with a host name and a port number where it
|
||||
should connect to. Once a client is connected, a TCP connection is
|
||||
maintained between client and server.
|
||||
|
||||
The Server class currently handles only one connection at a time;
|
||||
however it could be rewritten to allow various modes of operations,
|
||||
using multiple threads or processes or the select() system call as
|
||||
desired to serve multiple clients simultaneously (when using select(),
|
||||
still handling one request at a time). This would not require
|
||||
rewriting of the Client class. It may also be possible to adapt the
|
||||
code to use UDP instead of TCP, but then both classes will have to be
|
||||
rewritten (and unless extensive acknowlegements and request serial
|
||||
numbers are used, the server should handle duplicate requests, so its
|
||||
semantics should be idempotent -- shrudder).
|
||||
|
||||
Even though the FSProxy and RCSProxy modules define client classes,
|
||||
the client class is fully generic -- what methods it supports is
|
||||
determined entirely by the server. The server class, however, must be
|
||||
derived from. This is generally done as follows:
|
||||
|
||||
from server import Server
|
||||
from client import Client
|
||||
|
||||
# Define a class that performs the operations locally
|
||||
class MyClassLocal:
|
||||
def __init__(self): ...
|
||||
def _close(self): ...
|
||||
|
||||
# Derive a server class using multiple inheritance
|
||||
class MyClassServer(MyClassLocal, Server):
|
||||
def __init__(self, address):
|
||||
# Must initialize MyClassLocal as well as Server
|
||||
MyClassLocal.__init__(self)
|
||||
Server.__init__(self, address)
|
||||
def _close(self):
|
||||
Server._close()
|
||||
MyClassLocal._close()
|
||||
|
||||
# A dummy client class
|
||||
class MyClassClient(Client): pass
|
||||
|
||||
Note that because MyClassLocal isn't used in the definition of
|
||||
MyClassClient, it would actually be better to place it in a separate
|
||||
module so the definition of MyClassLocal isn't executed when we only
|
||||
instantiate a client.
|
||||
|
||||
The modules client and server should probably be renamed to Client and
|
||||
Server in order to match the class names.
|
||||
|
||||
|
||||
*** Security warning: this version requires that you have a file
|
||||
$HOME/.python_keyfile at the server and client side containing two
|
||||
comma- separated numbers. The security system at the moment makes no
|
||||
guarantees of actuallng being secure -- however it requires that the
|
||||
key file exists and contains the same numbers at both ends for this to
|
||||
work. (You can specify an alternative keyfile in $PYTHON_KEYFILE).
|
||||
Have a look at the Security class in security.py for details;
|
||||
basically, if the key file contains (x, y), then the security server
|
||||
class chooses a random number z (the challenge) in the range
|
||||
10..100000 and the client must be able to produce pow(z, x, y)
|
||||
(i.e. z**x mod y).
|
157
2.7/Python-2.7.16/Demo/pdist/client.py
Normal file
157
2.7/Python-2.7.16/Demo/pdist/client.py
Normal file
@ -0,0 +1,157 @@
|
||||
"""RPC Client module."""
|
||||
|
||||
import sys
|
||||
import socket
|
||||
import pickle
|
||||
import __builtin__
|
||||
import os
|
||||
|
||||
|
||||
# Default verbosity (0 = silent, 1 = print connections, 2 = print requests too)
|
||||
VERBOSE = 1
|
||||
|
||||
|
||||
class Client:
|
||||
|
||||
"""RPC Client class. No need to derive a class -- it's fully generic."""
|
||||
|
||||
def __init__(self, address, verbose = VERBOSE):
|
||||
self._pre_init(address, verbose)
|
||||
self._post_init()
|
||||
|
||||
def _pre_init(self, address, verbose = VERBOSE):
|
||||
if type(address) == type(0):
|
||||
address = ('', address)
|
||||
self._address = address
|
||||
self._verbose = verbose
|
||||
if self._verbose: print "Connecting to %s ..." % repr(address)
|
||||
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self._socket.connect(address)
|
||||
if self._verbose: print "Connected."
|
||||
self._lastid = 0 # Last id for which a reply has been received
|
||||
self._nextid = 1 # Id of next request
|
||||
self._replies = {} # Unprocessed replies
|
||||
self._rf = self._socket.makefile('r')
|
||||
self._wf = self._socket.makefile('w')
|
||||
|
||||
def _post_init(self):
|
||||
self._methods = self._call('.methods')
|
||||
|
||||
def __del__(self):
|
||||
self._close()
|
||||
|
||||
def _close(self):
|
||||
if self._rf: self._rf.close()
|
||||
self._rf = None
|
||||
if self._wf: self._wf.close()
|
||||
self._wf = None
|
||||
if self._socket: self._socket.close()
|
||||
self._socket = None
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name in self._methods:
|
||||
method = _stub(self, name)
|
||||
setattr(self, name, method) # XXX circular reference
|
||||
return method
|
||||
raise AttributeError, name
|
||||
|
||||
def _setverbose(self, verbose):
|
||||
self._verbose = verbose
|
||||
|
||||
def _call(self, name, *args):
|
||||
return self._vcall(name, args)
|
||||
|
||||
def _vcall(self, name, args):
|
||||
return self._recv(self._vsend(name, args))
|
||||
|
||||
def _send(self, name, *args):
|
||||
return self._vsend(name, args)
|
||||
|
||||
def _send_noreply(self, name, *args):
|
||||
return self._vsend(name, args, 0)
|
||||
|
||||
def _vsend_noreply(self, name, args):
|
||||
return self._vsend(name, args, 0)
|
||||
|
||||
def _vsend(self, name, args, wantreply = 1):
|
||||
id = self._nextid
|
||||
self._nextid = id+1
|
||||
if not wantreply: id = -id
|
||||
request = (name, args, id)
|
||||
if self._verbose > 1: print "sending request: %s" % repr(request)
|
||||
wp = pickle.Pickler(self._wf)
|
||||
wp.dump(request)
|
||||
return id
|
||||
|
||||
def _recv(self, id):
|
||||
exception, value, rid = self._vrecv(id)
|
||||
if rid != id:
|
||||
raise RuntimeError, "request/reply id mismatch: %d/%d" % (id, rid)
|
||||
if exception is None:
|
||||
return value
|
||||
x = exception
|
||||
if hasattr(__builtin__, exception):
|
||||
x = getattr(__builtin__, exception)
|
||||
elif exception in ('posix.error', 'mac.error'):
|
||||
x = os.error
|
||||
if x == exception:
|
||||
exception = x
|
||||
raise exception, value
|
||||
|
||||
def _vrecv(self, id):
|
||||
self._flush()
|
||||
if self._replies.has_key(id):
|
||||
if self._verbose > 1: print "retrieving previous reply, id = %d" % id
|
||||
reply = self._replies[id]
|
||||
del self._replies[id]
|
||||
return reply
|
||||
aid = abs(id)
|
||||
while 1:
|
||||
if self._verbose > 1: print "waiting for reply, id = %d" % id
|
||||
rp = pickle.Unpickler(self._rf)
|
||||
reply = rp.load()
|
||||
del rp
|
||||
if self._verbose > 1: print "got reply: %s" % repr(reply)
|
||||
rid = reply[2]
|
||||
arid = abs(rid)
|
||||
if arid == aid:
|
||||
if self._verbose > 1: print "got it"
|
||||
return reply
|
||||
self._replies[rid] = reply
|
||||
if arid > aid:
|
||||
if self._verbose > 1: print "got higher id, assume all ok"
|
||||
return (None, None, id)
|
||||
|
||||
def _flush(self):
|
||||
self._wf.flush()
|
||||
|
||||
|
||||
from security import Security
|
||||
|
||||
|
||||
class SecureClient(Client, Security):
|
||||
|
||||
def __init__(self, *args):
|
||||
import string
|
||||
apply(self._pre_init, args)
|
||||
Security.__init__(self)
|
||||
self._wf.flush()
|
||||
line = self._rf.readline()
|
||||
challenge = string.atoi(string.strip(line))
|
||||
response = self._encode_challenge(challenge)
|
||||
line = repr(long(response))
|
||||
if line[-1] in 'Ll': line = line[:-1]
|
||||
self._wf.write(line + '\n')
|
||||
self._wf.flush()
|
||||
self._post_init()
|
||||
|
||||
class _stub:
|
||||
|
||||
"""Helper class for Client -- each instance serves as a method of the client."""
|
||||
|
||||
def __init__(self, client, name):
|
||||
self._client = client
|
||||
self._name = name
|
||||
|
||||
def __call__(self, *args):
|
||||
return self._client._vcall(self._name, args)
|
144
2.7/Python-2.7.16/Demo/pdist/cmdfw.py
Normal file
144
2.7/Python-2.7.16/Demo/pdist/cmdfw.py
Normal file
@ -0,0 +1,144 @@
|
||||
"Framework for command line interfaces like CVS. See class CmdFrameWork."
|
||||
|
||||
|
||||
class CommandFrameWork:
|
||||
|
||||
"""Framework class for command line interfaces like CVS.
|
||||
|
||||
The general command line structure is
|
||||
|
||||
command [flags] subcommand [subflags] [argument] ...
|
||||
|
||||
There's a class variable GlobalFlags which specifies the
|
||||
global flags options. Subcommands are defined by defining
|
||||
methods named do_<subcommand>. Flags for the subcommand are
|
||||
defined by defining class or instance variables named
|
||||
flags_<subcommand>. If there's no command, method default()
|
||||
is called. The __doc__ strings for the do_ methods are used
|
||||
for the usage message, printed after the general usage message
|
||||
which is the class variable UsageMessage. The class variable
|
||||
PostUsageMessage is printed after all the do_ methods' __doc__
|
||||
strings. The method's return value can be a suggested exit
|
||||
status. [XXX Need to rewrite this to clarify it.]
|
||||
|
||||
Common usage is to derive a class, instantiate it, and then call its
|
||||
run() method; by default this takes its arguments from sys.argv[1:].
|
||||
"""
|
||||
|
||||
UsageMessage = \
|
||||
"usage: (name)s [flags] subcommand [subflags] [argument] ..."
|
||||
|
||||
PostUsageMessage = None
|
||||
|
||||
GlobalFlags = ''
|
||||
|
||||
def __init__(self):
|
||||
"""Constructor, present for completeness."""
|
||||
pass
|
||||
|
||||
def run(self, args = None):
|
||||
"""Process flags, subcommand and options, then run it."""
|
||||
import getopt, sys
|
||||
if args is None: args = sys.argv[1:]
|
||||
try:
|
||||
opts, args = getopt.getopt(args, self.GlobalFlags)
|
||||
except getopt.error, msg:
|
||||
return self.usage(msg)
|
||||
self.options(opts)
|
||||
if not args:
|
||||
self.ready()
|
||||
return self.default()
|
||||
else:
|
||||
cmd = args[0]
|
||||
mname = 'do_' + cmd
|
||||
fname = 'flags_' + cmd
|
||||
try:
|
||||
method = getattr(self, mname)
|
||||
except AttributeError:
|
||||
return self.usage("command %r unknown" % (cmd,))
|
||||
try:
|
||||
flags = getattr(self, fname)
|
||||
except AttributeError:
|
||||
flags = ''
|
||||
try:
|
||||
opts, args = getopt.getopt(args[1:], flags)
|
||||
except getopt.error, msg:
|
||||
return self.usage(
|
||||
"subcommand %s: " % cmd + str(msg))
|
||||
self.ready()
|
||||
return method(opts, args)
|
||||
|
||||
def options(self, opts):
|
||||
"""Process the options retrieved by getopt.
|
||||
Override this if you have any options."""
|
||||
if opts:
|
||||
print "-"*40
|
||||
print "Options:"
|
||||
for o, a in opts:
|
||||
print 'option', o, 'value', repr(a)
|
||||
print "-"*40
|
||||
|
||||
def ready(self):
|
||||
"""Called just before calling the subcommand."""
|
||||
pass
|
||||
|
||||
def usage(self, msg = None):
|
||||
"""Print usage message. Return suitable exit code (2)."""
|
||||
if msg: print msg
|
||||
print self.UsageMessage % {'name': self.__class__.__name__}
|
||||
docstrings = {}
|
||||
c = self.__class__
|
||||
while 1:
|
||||
for name in dir(c):
|
||||
if name[:3] == 'do_':
|
||||
if docstrings.has_key(name):
|
||||
continue
|
||||
try:
|
||||
doc = getattr(c, name).__doc__
|
||||
except:
|
||||
doc = None
|
||||
if doc:
|
||||
docstrings[name] = doc
|
||||
if not c.__bases__:
|
||||
break
|
||||
c = c.__bases__[0]
|
||||
if docstrings:
|
||||
print "where subcommand can be:"
|
||||
names = docstrings.keys()
|
||||
names.sort()
|
||||
for name in names:
|
||||
print docstrings[name]
|
||||
if self.PostUsageMessage:
|
||||
print self.PostUsageMessage
|
||||
return 2
|
||||
|
||||
def default(self):
|
||||
"""Default method, called when no subcommand is given.
|
||||
You should always override this."""
|
||||
print "Nobody expects the Spanish Inquisition!"
|
||||
|
||||
|
||||
def test():
|
||||
"""Test script -- called when this module is run as a script."""
|
||||
import sys
|
||||
class Hello(CommandFrameWork):
|
||||
def do_hello(self, opts, args):
|
||||
"hello -- print 'hello world', needs no arguments"
|
||||
print "Hello, world"
|
||||
x = Hello()
|
||||
tests = [
|
||||
[],
|
||||
['hello'],
|
||||
['spam'],
|
||||
['-x'],
|
||||
['hello', '-x'],
|
||||
None,
|
||||
]
|
||||
for t in tests:
|
||||
print '-'*10, t, '-'*10
|
||||
sts = x.run(t)
|
||||
print "Exit status:", repr(sts)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
208
2.7/Python-2.7.16/Demo/pdist/cmptree.py
Normal file
208
2.7/Python-2.7.16/Demo/pdist/cmptree.py
Normal file
@ -0,0 +1,208 @@
|
||||
"""Compare local and remote dictionaries and transfer differing files -- like rdist."""
|
||||
|
||||
import sys
|
||||
from repr import repr
|
||||
import FSProxy
|
||||
import time
|
||||
import os
|
||||
|
||||
def main():
|
||||
pwd = os.getcwd()
|
||||
s = raw_input("chdir [%s] " % pwd)
|
||||
if s:
|
||||
os.chdir(s)
|
||||
pwd = os.getcwd()
|
||||
host = ask("host", 'voorn.cwi.nl')
|
||||
port = 4127
|
||||
verbose = 1
|
||||
mode = ''
|
||||
print """\
|
||||
Mode should be a string of characters, indicating what to do with differences.
|
||||
r - read different files to local file system
|
||||
w - write different files to remote file system
|
||||
c - create new files, either remote or local
|
||||
d - delete disappearing files, either remote or local
|
||||
"""
|
||||
s = raw_input("mode [%s] " % mode)
|
||||
if s: mode = s
|
||||
address = (host, port)
|
||||
t1 = time.time()
|
||||
local = FSProxy.FSProxyLocal()
|
||||
remote = FSProxy.FSProxyClient(address, verbose)
|
||||
compare(local, remote, mode)
|
||||
remote._close()
|
||||
local._close()
|
||||
t2 = time.time()
|
||||
dt = t2-t1
|
||||
mins, secs = divmod(dt, 60)
|
||||
print mins, "minutes and", round(secs), "seconds"
|
||||
raw_input("[Return to exit] ")
|
||||
|
||||
def ask(prompt, default):
|
||||
s = raw_input("%s [%s] " % (prompt, default))
|
||||
return s or default
|
||||
|
||||
def askint(prompt, default):
|
||||
s = raw_input("%s [%s] " % (prompt, str(default)))
|
||||
if s: return string.atoi(s)
|
||||
return default
|
||||
|
||||
def compare(local, remote, mode):
|
||||
print
|
||||
print "PWD =", repr(os.getcwd())
|
||||
sums_id = remote._send('sumlist')
|
||||
subdirs_id = remote._send('listsubdirs')
|
||||
remote._flush()
|
||||
print "calculating local sums ..."
|
||||
lsumdict = {}
|
||||
for name, info in local.sumlist():
|
||||
lsumdict[name] = info
|
||||
print "getting remote sums ..."
|
||||
sums = remote._recv(sums_id)
|
||||
print "got", len(sums)
|
||||
rsumdict = {}
|
||||
for name, rsum in sums:
|
||||
rsumdict[name] = rsum
|
||||
if not lsumdict.has_key(name):
|
||||
print repr(name), "only remote"
|
||||
if 'r' in mode and 'c' in mode:
|
||||
recvfile(local, remote, name)
|
||||
else:
|
||||
lsum = lsumdict[name]
|
||||
if lsum != rsum:
|
||||
print repr(name),
|
||||
rmtime = remote.mtime(name)
|
||||
lmtime = local.mtime(name)
|
||||
if rmtime > lmtime:
|
||||
print "remote newer",
|
||||
if 'r' in mode:
|
||||
recvfile(local, remote, name)
|
||||
elif lmtime > rmtime:
|
||||
print "local newer",
|
||||
if 'w' in mode:
|
||||
sendfile(local, remote, name)
|
||||
else:
|
||||
print "same mtime but different sum?!?!",
|
||||
print
|
||||
for name in lsumdict.keys():
|
||||
if not rsumdict.keys():
|
||||
print repr(name), "only locally",
|
||||
fl()
|
||||
if 'w' in mode and 'c' in mode:
|
||||
sendfile(local, remote, name)
|
||||
elif 'r' in mode and 'd' in mode:
|
||||
os.unlink(name)
|
||||
print "removed."
|
||||
print
|
||||
print "gettin subdirs ..."
|
||||
subdirs = remote._recv(subdirs_id)
|
||||
common = []
|
||||
for name in subdirs:
|
||||
if local.isdir(name):
|
||||
print "Common subdirectory", repr(name)
|
||||
common.append(name)
|
||||
else:
|
||||
print "Remote subdirectory", repr(name), "not found locally"
|
||||
if 'r' in mode and 'c' in mode:
|
||||
pr = "Create local subdirectory %s? [y] " % \
|
||||
repr(name)
|
||||
if 'y' in mode:
|
||||
ok = 'y'
|
||||
else:
|
||||
ok = ask(pr, "y")
|
||||
if ok[:1] in ('y', 'Y'):
|
||||
local.mkdir(name)
|
||||
print "Subdirectory %s made" % \
|
||||
repr(name)
|
||||
common.append(name)
|
||||
lsubdirs = local.listsubdirs()
|
||||
for name in lsubdirs:
|
||||
if name not in subdirs:
|
||||
print "Local subdirectory", repr(name), "not found remotely"
|
||||
for name in common:
|
||||
print "Entering subdirectory", repr(name)
|
||||
local.cd(name)
|
||||
remote.cd(name)
|
||||
compare(local, remote, mode)
|
||||
remote.back()
|
||||
local.back()
|
||||
|
||||
def sendfile(local, remote, name):
|
||||
try:
|
||||
remote.create(name)
|
||||
except (IOError, os.error), msg:
|
||||
print "cannot create:", msg
|
||||
return
|
||||
|
||||
print "sending ...",
|
||||
fl()
|
||||
|
||||
data = open(name).read()
|
||||
|
||||
t1 = time.time()
|
||||
|
||||
remote._send_noreply('write', name, data)
|
||||
remote._flush()
|
||||
|
||||
t2 = time.time()
|
||||
|
||||
dt = t2-t1
|
||||
print len(data), "bytes in", round(dt), "seconds",
|
||||
if dt:
|
||||
print "i.e.", round(len(data)/dt), "bytes/sec",
|
||||
print
|
||||
|
||||
def recvfile(local, remote, name):
|
||||
ok = 0
|
||||
try:
|
||||
rv = recvfile_real(local, remote, name)
|
||||
ok = 1
|
||||
return rv
|
||||
finally:
|
||||
if not ok:
|
||||
print "*** recvfile of %r failed, deleting" % (name,)
|
||||
local.delete(name)
|
||||
|
||||
def recvfile_real(local, remote, name):
|
||||
try:
|
||||
local.create(name)
|
||||
except (IOError, os.error), msg:
|
||||
print "cannot create:", msg
|
||||
return
|
||||
|
||||
print "receiving ...",
|
||||
fl()
|
||||
|
||||
f = open(name, 'w')
|
||||
t1 = time.time()
|
||||
|
||||
length = 4*1024
|
||||
offset = 0
|
||||
id = remote._send('read', name, offset, length)
|
||||
remote._flush()
|
||||
while 1:
|
||||
newoffset = offset + length
|
||||
newid = remote._send('read', name, newoffset, length)
|
||||
data = remote._recv(id)
|
||||
id = newid
|
||||
if not data: break
|
||||
f.seek(offset)
|
||||
f.write(data)
|
||||
offset = newoffset
|
||||
size = f.tell()
|
||||
|
||||
t2 = time.time()
|
||||
f.close()
|
||||
|
||||
dt = t2-t1
|
||||
print size, "bytes in", round(dt), "seconds",
|
||||
if dt:
|
||||
print "i.e.", size//dt, "bytes/sec",
|
||||
print
|
||||
remote._recv(id) # ignored
|
||||
|
||||
def fl():
|
||||
sys.stdout.flush()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
364
2.7/Python-2.7.16/Demo/pdist/cvslib.py
Normal file
364
2.7/Python-2.7.16/Demo/pdist/cvslib.py
Normal file
@ -0,0 +1,364 @@
|
||||
"""Utilities for CVS administration."""
|
||||
|
||||
import string
|
||||
import os
|
||||
import time
|
||||
import md5
|
||||
import fnmatch
|
||||
|
||||
if not hasattr(time, 'timezone'):
|
||||
time.timezone = 0
|
||||
|
||||
class File:
|
||||
|
||||
"""Represent a file's status.
|
||||
|
||||
Instance variables:
|
||||
|
||||
file -- the filename (no slashes), None if uninitialized
|
||||
lseen -- true if the data for the local file is up to date
|
||||
eseen -- true if the data from the CVS/Entries entry is up to date
|
||||
(this implies that the entry must be written back)
|
||||
rseen -- true if the data for the remote file is up to date
|
||||
proxy -- RCSProxy instance used to contact the server, or None
|
||||
|
||||
Note that lseen and rseen don't necessary mean that a local
|
||||
or remote file *exists* -- they indicate that we've checked it.
|
||||
However, eseen means that this instance corresponds to an
|
||||
entry in the CVS/Entries file.
|
||||
|
||||
If lseen is true:
|
||||
|
||||
lsum -- checksum of the local file, None if no local file
|
||||
lctime -- ctime of the local file, None if no local file
|
||||
lmtime -- mtime of the local file, None if no local file
|
||||
|
||||
If eseen is true:
|
||||
|
||||
erev -- revision, None if this is a no revision (not '0')
|
||||
enew -- true if this is an uncommitted added file
|
||||
edeleted -- true if this is an uncommitted removed file
|
||||
ectime -- ctime of last local file corresponding to erev
|
||||
emtime -- mtime of last local file corresponding to erev
|
||||
extra -- 5th string from CVS/Entries file
|
||||
|
||||
If rseen is true:
|
||||
|
||||
rrev -- revision of head, None if non-existent
|
||||
rsum -- checksum of that revision, Non if non-existent
|
||||
|
||||
If eseen and rseen are both true:
|
||||
|
||||
esum -- checksum of revision erev, None if no revision
|
||||
|
||||
Note
|
||||
"""
|
||||
|
||||
def __init__(self, file = None):
|
||||
if file and '/' in file:
|
||||
raise ValueError, "no slash allowed in file"
|
||||
self.file = file
|
||||
self.lseen = self.eseen = self.rseen = 0
|
||||
self.proxy = None
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.file, other.file)
|
||||
|
||||
def getlocal(self):
|
||||
try:
|
||||
self.lmtime, self.lctime = os.stat(self.file)[-2:]
|
||||
except os.error:
|
||||
self.lmtime = self.lctime = self.lsum = None
|
||||
else:
|
||||
self.lsum = md5.new(open(self.file).read()).digest()
|
||||
self.lseen = 1
|
||||
|
||||
def getentry(self, line):
|
||||
words = string.splitfields(line, '/')
|
||||
if self.file and words[1] != self.file:
|
||||
raise ValueError, "file name mismatch"
|
||||
self.file = words[1]
|
||||
self.erev = words[2]
|
||||
self.edeleted = 0
|
||||
self.enew = 0
|
||||
self.ectime = self.emtime = None
|
||||
if self.erev[:1] == '-':
|
||||
self.edeleted = 1
|
||||
self.erev = self.erev[1:]
|
||||
if self.erev == '0':
|
||||
self.erev = None
|
||||
self.enew = 1
|
||||
else:
|
||||
dates = words[3]
|
||||
self.ectime = unctime(dates[:24])
|
||||
self.emtime = unctime(dates[25:])
|
||||
self.extra = words[4]
|
||||
if self.rseen:
|
||||
self.getesum()
|
||||
self.eseen = 1
|
||||
|
||||
def getremote(self, proxy = None):
|
||||
if proxy:
|
||||
self.proxy = proxy
|
||||
try:
|
||||
self.rrev = self.proxy.head(self.file)
|
||||
except (os.error, IOError):
|
||||
self.rrev = None
|
||||
if self.rrev:
|
||||
self.rsum = self.proxy.sum(self.file)
|
||||
else:
|
||||
self.rsum = None
|
||||
if self.eseen:
|
||||
self.getesum()
|
||||
self.rseen = 1
|
||||
|
||||
def getesum(self):
|
||||
if self.erev == self.rrev:
|
||||
self.esum = self.rsum
|
||||
elif self.erev:
|
||||
name = (self.file, self.erev)
|
||||
self.esum = self.proxy.sum(name)
|
||||
else:
|
||||
self.esum = None
|
||||
|
||||
def putentry(self):
|
||||
"""Return a line suitable for inclusion in CVS/Entries.
|
||||
|
||||
The returned line is terminated by a newline.
|
||||
If no entry should be written for this file,
|
||||
return "".
|
||||
"""
|
||||
if not self.eseen:
|
||||
return ""
|
||||
|
||||
rev = self.erev or '0'
|
||||
if self.edeleted:
|
||||
rev = '-' + rev
|
||||
if self.enew:
|
||||
dates = 'Initial ' + self.file
|
||||
else:
|
||||
dates = gmctime(self.ectime) + ' ' + \
|
||||
gmctime(self.emtime)
|
||||
return "/%s/%s/%s/%s/\n" % (
|
||||
self.file,
|
||||
rev,
|
||||
dates,
|
||||
self.extra)
|
||||
|
||||
def report(self):
|
||||
print '-'*50
|
||||
def r(key, repr=repr, self=self):
|
||||
try:
|
||||
value = repr(getattr(self, key))
|
||||
except AttributeError:
|
||||
value = "?"
|
||||
print "%-15s:" % key, value
|
||||
r("file")
|
||||
if self.lseen:
|
||||
r("lsum", hexify)
|
||||
r("lctime", gmctime)
|
||||
r("lmtime", gmctime)
|
||||
if self.eseen:
|
||||
r("erev")
|
||||
r("enew")
|
||||
r("edeleted")
|
||||
r("ectime", gmctime)
|
||||
r("emtime", gmctime)
|
||||
if self.rseen:
|
||||
r("rrev")
|
||||
r("rsum", hexify)
|
||||
if self.eseen:
|
||||
r("esum", hexify)
|
||||
|
||||
|
||||
class CVS:
|
||||
|
||||
"""Represent the contents of a CVS admin file (and more).
|
||||
|
||||
Class variables:
|
||||
|
||||
FileClass -- the class to be instantiated for entries
|
||||
(this should be derived from class File above)
|
||||
IgnoreList -- shell patterns for local files to be ignored
|
||||
|
||||
Instance variables:
|
||||
|
||||
entries -- a dictionary containing File instances keyed by
|
||||
their file name
|
||||
proxy -- an RCSProxy instance, or None
|
||||
"""
|
||||
|
||||
FileClass = File
|
||||
|
||||
IgnoreList = ['.*', '@*', ',*', '*~', '*.o', '*.a', '*.so', '*.pyc']
|
||||
|
||||
def __init__(self):
|
||||
self.entries = {}
|
||||
self.proxy = None
|
||||
|
||||
def setproxy(self, proxy):
|
||||
if proxy is self.proxy:
|
||||
return
|
||||
self.proxy = proxy
|
||||
for e in self.entries.values():
|
||||
e.rseen = 0
|
||||
|
||||
def getentries(self):
|
||||
"""Read the contents of CVS/Entries"""
|
||||
self.entries = {}
|
||||
f = self.cvsopen("Entries")
|
||||
while 1:
|
||||
line = f.readline()
|
||||
if not line: break
|
||||
e = self.FileClass()
|
||||
e.getentry(line)
|
||||
self.entries[e.file] = e
|
||||
f.close()
|
||||
|
||||
def putentries(self):
|
||||
"""Write CVS/Entries back"""
|
||||
f = self.cvsopen("Entries", 'w')
|
||||
for e in self.values():
|
||||
f.write(e.putentry())
|
||||
f.close()
|
||||
|
||||
def getlocalfiles(self):
|
||||
list = self.entries.keys()
|
||||
addlist = os.listdir(os.curdir)
|
||||
for name in addlist:
|
||||
if name in list:
|
||||
continue
|
||||
if not self.ignored(name):
|
||||
list.append(name)
|
||||
list.sort()
|
||||
for file in list:
|
||||
try:
|
||||
e = self.entries[file]
|
||||
except KeyError:
|
||||
e = self.entries[file] = self.FileClass(file)
|
||||
e.getlocal()
|
||||
|
||||
def getremotefiles(self, proxy = None):
|
||||
if proxy:
|
||||
self.proxy = proxy
|
||||
if not self.proxy:
|
||||
raise RuntimeError, "no RCS proxy"
|
||||
addlist = self.proxy.listfiles()
|
||||
for file in addlist:
|
||||
try:
|
||||
e = self.entries[file]
|
||||
except KeyError:
|
||||
e = self.entries[file] = self.FileClass(file)
|
||||
e.getremote(self.proxy)
|
||||
|
||||
def report(self):
|
||||
for e in self.values():
|
||||
e.report()
|
||||
print '-'*50
|
||||
|
||||
def keys(self):
|
||||
keys = self.entries.keys()
|
||||
keys.sort()
|
||||
return keys
|
||||
|
||||
def values(self):
|
||||
def value(key, self=self):
|
||||
return self.entries[key]
|
||||
return map(value, self.keys())
|
||||
|
||||
def items(self):
|
||||
def item(key, self=self):
|
||||
return (key, self.entries[key])
|
||||
return map(item, self.keys())
|
||||
|
||||
def cvsexists(self, file):
|
||||
file = os.path.join("CVS", file)
|
||||
return os.path.exists(file)
|
||||
|
||||
def cvsopen(self, file, mode = 'r'):
|
||||
file = os.path.join("CVS", file)
|
||||
if 'r' not in mode:
|
||||
self.backup(file)
|
||||
return open(file, mode)
|
||||
|
||||
def backup(self, file):
|
||||
if os.path.isfile(file):
|
||||
bfile = file + '~'
|
||||
try: os.unlink(bfile)
|
||||
except os.error: pass
|
||||
os.rename(file, bfile)
|
||||
|
||||
def ignored(self, file):
|
||||
if os.path.isdir(file): return True
|
||||
for pat in self.IgnoreList:
|
||||
if fnmatch.fnmatch(file, pat): return True
|
||||
return False
|
||||
|
||||
|
||||
# hexify and unhexify are useful to print MD5 checksums in hex format
|
||||
|
||||
hexify_format = '%02x' * 16
|
||||
def hexify(sum):
|
||||
"Return a hex representation of a 16-byte string (e.g. an MD5 digest)"
|
||||
if sum is None:
|
||||
return "None"
|
||||
return hexify_format % tuple(map(ord, sum))
|
||||
|
||||
def unhexify(hexsum):
|
||||
"Return the original from a hexified string"
|
||||
if hexsum == "None":
|
||||
return None
|
||||
sum = ''
|
||||
for i in range(0, len(hexsum), 2):
|
||||
sum = sum + chr(string.atoi(hexsum[i:i+2], 16))
|
||||
return sum
|
||||
|
||||
|
||||
unctime_monthmap = {}
|
||||
def unctime(date):
|
||||
if date == "None": return None
|
||||
if not unctime_monthmap:
|
||||
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
|
||||
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
|
||||
i = 0
|
||||
for m in months:
|
||||
i = i+1
|
||||
unctime_monthmap[m] = i
|
||||
words = string.split(date) # Day Mon DD HH:MM:SS YEAR
|
||||
year = string.atoi(words[4])
|
||||
month = unctime_monthmap[words[1]]
|
||||
day = string.atoi(words[2])
|
||||
[hh, mm, ss] = map(string.atoi, string.splitfields(words[3], ':'))
|
||||
ss = ss - time.timezone
|
||||
return time.mktime((year, month, day, hh, mm, ss, 0, 0, 0))
|
||||
|
||||
def gmctime(t):
|
||||
if t is None: return "None"
|
||||
return time.asctime(time.gmtime(t))
|
||||
|
||||
def test_unctime():
|
||||
now = int(time.time())
|
||||
t = time.gmtime(now)
|
||||
at = time.asctime(t)
|
||||
print 'GMT', now, at
|
||||
print 'timezone', time.timezone
|
||||
print 'local', time.ctime(now)
|
||||
u = unctime(at)
|
||||
print 'unctime()', u
|
||||
gu = time.gmtime(u)
|
||||
print '->', gu
|
||||
print time.asctime(gu)
|
||||
|
||||
def test():
|
||||
x = CVS()
|
||||
x.getentries()
|
||||
x.getlocalfiles()
|
||||
## x.report()
|
||||
import rcsclient
|
||||
proxy = rcsclient.openrcsclient()
|
||||
x.getremotefiles(proxy)
|
||||
x.report()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test()
|
280
2.7/Python-2.7.16/Demo/pdist/cvslock.py
Normal file
280
2.7/Python-2.7.16/Demo/pdist/cvslock.py
Normal file
@ -0,0 +1,280 @@
|
||||
"""CVS locking algorithm.
|
||||
|
||||
CVS locking strategy
|
||||
====================
|
||||
|
||||
As reverse engineered from the CVS 1.3 sources (file lock.c):
|
||||
|
||||
- Locking is done on a per repository basis (but a process can hold
|
||||
write locks for multiple directories); all lock files are placed in
|
||||
the repository and have names beginning with "#cvs.".
|
||||
|
||||
- Before even attempting to lock, a file "#cvs.tfl.<pid>" is created
|
||||
(and removed again), to test that we can write the repository. [The
|
||||
algorithm can still be fooled (1) if the repository's mode is changed
|
||||
while attempting to lock; (2) if this file exists and is writable but
|
||||
the directory is not.]
|
||||
|
||||
- While creating the actual read/write lock files (which may exist for
|
||||
a long time), a "meta-lock" is held. The meta-lock is a directory
|
||||
named "#cvs.lock" in the repository. The meta-lock is also held while
|
||||
a write lock is held.
|
||||
|
||||
- To set a read lock:
|
||||
|
||||
- acquire the meta-lock
|
||||
- create the file "#cvs.rfl.<pid>"
|
||||
- release the meta-lock
|
||||
|
||||
- To set a write lock:
|
||||
|
||||
- acquire the meta-lock
|
||||
- check that there are no files called "#cvs.rfl.*"
|
||||
- if there are, release the meta-lock, sleep, try again
|
||||
- create the file "#cvs.wfl.<pid>"
|
||||
|
||||
- To release a write lock:
|
||||
|
||||
- remove the file "#cvs.wfl.<pid>"
|
||||
- rmdir the meta-lock
|
||||
|
||||
- To release a read lock:
|
||||
|
||||
- remove the file "#cvs.rfl.<pid>"
|
||||
|
||||
|
||||
Additional notes
|
||||
----------------
|
||||
|
||||
- A process should read-lock at most one repository at a time.
|
||||
|
||||
- A process may write-lock as many repositories as it wishes (to avoid
|
||||
deadlocks, I presume it should always lock them top-down in the
|
||||
directory hierarchy).
|
||||
|
||||
- A process should make sure it removes all its lock files and
|
||||
directories when it crashes.
|
||||
|
||||
- Limitation: one user id should not be committing files into the same
|
||||
repository at the same time.
|
||||
|
||||
|
||||
Turn this into Python code
|
||||
--------------------------
|
||||
|
||||
rl = ReadLock(repository, waittime)
|
||||
|
||||
wl = WriteLock(repository, waittime)
|
||||
|
||||
list = MultipleWriteLock([repository1, repository2, ...], waittime)
|
||||
|
||||
"""
|
||||
|
||||
|
||||
import os
|
||||
import time
|
||||
import stat
|
||||
import pwd
|
||||
|
||||
|
||||
# Default wait time
|
||||
DELAY = 10
|
||||
|
||||
|
||||
# XXX This should be the same on all Unix versions
|
||||
EEXIST = 17
|
||||
|
||||
|
||||
# Files used for locking (must match cvs.h in the CVS sources)
|
||||
CVSLCK = "#cvs.lck"
|
||||
CVSRFL = "#cvs.rfl."
|
||||
CVSWFL = "#cvs.wfl."
|
||||
|
||||
|
||||
class Error:
|
||||
|
||||
def __init__(self, msg):
|
||||
self.msg = msg
|
||||
|
||||
def __repr__(self):
|
||||
return repr(self.msg)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.msg)
|
||||
|
||||
|
||||
class Locked(Error):
|
||||
pass
|
||||
|
||||
|
||||
class Lock:
|
||||
|
||||
def __init__(self, repository = ".", delay = DELAY):
|
||||
self.repository = repository
|
||||
self.delay = delay
|
||||
self.lockdir = None
|
||||
self.lockfile = None
|
||||
pid = repr(os.getpid())
|
||||
self.cvslck = self.join(CVSLCK)
|
||||
self.cvsrfl = self.join(CVSRFL + pid)
|
||||
self.cvswfl = self.join(CVSWFL + pid)
|
||||
|
||||
def __del__(self):
|
||||
print "__del__"
|
||||
self.unlock()
|
||||
|
||||
def setlockdir(self):
|
||||
while 1:
|
||||
try:
|
||||
self.lockdir = self.cvslck
|
||||
os.mkdir(self.cvslck, 0777)
|
||||
return
|
||||
except os.error, msg:
|
||||
self.lockdir = None
|
||||
if msg[0] == EEXIST:
|
||||
try:
|
||||
st = os.stat(self.cvslck)
|
||||
except os.error:
|
||||
continue
|
||||
self.sleep(st)
|
||||
continue
|
||||
raise Error("failed to lock %s: %s" % (
|
||||
self.repository, msg))
|
||||
|
||||
def unlock(self):
|
||||
self.unlockfile()
|
||||
self.unlockdir()
|
||||
|
||||
def unlockfile(self):
|
||||
if self.lockfile:
|
||||
print "unlink", self.lockfile
|
||||
try:
|
||||
os.unlink(self.lockfile)
|
||||
except os.error:
|
||||
pass
|
||||
self.lockfile = None
|
||||
|
||||
def unlockdir(self):
|
||||
if self.lockdir:
|
||||
print "rmdir", self.lockdir
|
||||
try:
|
||||
os.rmdir(self.lockdir)
|
||||
except os.error:
|
||||
pass
|
||||
self.lockdir = None
|
||||
|
||||
def sleep(self, st):
|
||||
sleep(st, self.repository, self.delay)
|
||||
|
||||
def join(self, name):
|
||||
return os.path.join(self.repository, name)
|
||||
|
||||
|
||||
def sleep(st, repository, delay):
|
||||
if delay <= 0:
|
||||
raise Locked(st)
|
||||
uid = st[stat.ST_UID]
|
||||
try:
|
||||
pwent = pwd.getpwuid(uid)
|
||||
user = pwent[0]
|
||||
except KeyError:
|
||||
user = "uid %d" % uid
|
||||
print "[%s]" % time.ctime(time.time())[11:19],
|
||||
print "Waiting for %s's lock in" % user, repository
|
||||
time.sleep(delay)
|
||||
|
||||
|
||||
class ReadLock(Lock):
|
||||
|
||||
def __init__(self, repository, delay = DELAY):
|
||||
Lock.__init__(self, repository, delay)
|
||||
ok = 0
|
||||
try:
|
||||
self.setlockdir()
|
||||
self.lockfile = self.cvsrfl
|
||||
fp = open(self.lockfile, 'w')
|
||||
fp.close()
|
||||
ok = 1
|
||||
finally:
|
||||
if not ok:
|
||||
self.unlockfile()
|
||||
self.unlockdir()
|
||||
|
||||
|
||||
class WriteLock(Lock):
|
||||
|
||||
def __init__(self, repository, delay = DELAY):
|
||||
Lock.__init__(self, repository, delay)
|
||||
self.setlockdir()
|
||||
while 1:
|
||||
uid = self.readers_exist()
|
||||
if not uid:
|
||||
break
|
||||
self.unlockdir()
|
||||
self.sleep(uid)
|
||||
self.lockfile = self.cvswfl
|
||||
fp = open(self.lockfile, 'w')
|
||||
fp.close()
|
||||
|
||||
def readers_exist(self):
|
||||
n = len(CVSRFL)
|
||||
for name in os.listdir(self.repository):
|
||||
if name[:n] == CVSRFL:
|
||||
try:
|
||||
st = os.stat(self.join(name))
|
||||
except os.error:
|
||||
continue
|
||||
return st
|
||||
return None
|
||||
|
||||
|
||||
def MultipleWriteLock(repositories, delay = DELAY):
|
||||
while 1:
|
||||
locks = []
|
||||
for r in repositories:
|
||||
try:
|
||||
locks.append(WriteLock(r, 0))
|
||||
except Locked, instance:
|
||||
del locks
|
||||
break
|
||||
else:
|
||||
break
|
||||
sleep(instance.msg, r, delay)
|
||||
return list
|
||||
|
||||
|
||||
def test():
|
||||
import sys
|
||||
if sys.argv[1:]:
|
||||
repository = sys.argv[1]
|
||||
else:
|
||||
repository = "."
|
||||
rl = None
|
||||
wl = None
|
||||
try:
|
||||
print "attempting write lock ..."
|
||||
wl = WriteLock(repository)
|
||||
print "got it."
|
||||
wl.unlock()
|
||||
print "attempting read lock ..."
|
||||
rl = ReadLock(repository)
|
||||
print "got it."
|
||||
rl.unlock()
|
||||
finally:
|
||||
print [1]
|
||||
sys.exc_traceback = None
|
||||
print [2]
|
||||
if rl:
|
||||
rl.unlock()
|
||||
print [3]
|
||||
if wl:
|
||||
wl.unlock()
|
||||
print [4]
|
||||
rl = None
|
||||
print [5]
|
||||
wl = None
|
||||
print [6]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
19
2.7/Python-2.7.16/Demo/pdist/mac.py
Normal file
19
2.7/Python-2.7.16/Demo/pdist/mac.py
Normal file
@ -0,0 +1,19 @@
|
||||
import sys
|
||||
import string
|
||||
import rcvs
|
||||
|
||||
def main():
|
||||
while 1:
|
||||
try:
|
||||
line = raw_input('$ ')
|
||||
except EOFError:
|
||||
break
|
||||
words = string.split(line)
|
||||
if not words:
|
||||
continue
|
||||
if words[0] != 'rcvs':
|
||||
words.insert(0, 'rcvs')
|
||||
sys.argv = words
|
||||
rcvs.main()
|
||||
|
||||
main()
|
109
2.7/Python-2.7.16/Demo/pdist/makechangelog.py
Normal file
109
2.7/Python-2.7.16/Demo/pdist/makechangelog.py
Normal file
@ -0,0 +1,109 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"""Turn a pile of RCS log output into ChangeLog file entries.
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
import string
|
||||
import re
|
||||
import getopt
|
||||
import time
|
||||
|
||||
def main():
|
||||
args = sys.argv[1:]
|
||||
opts, args = getopt.getopt(args, 'p:')
|
||||
prefix = ''
|
||||
for o, a in opts:
|
||||
if p == '-p': prefix = a
|
||||
|
||||
f = sys.stdin
|
||||
allrevs = []
|
||||
while 1:
|
||||
file = getnextfile(f)
|
||||
if not file: break
|
||||
revs = []
|
||||
while 1:
|
||||
rev = getnextrev(f, file)
|
||||
if not rev:
|
||||
break
|
||||
revs.append(rev)
|
||||
if revs:
|
||||
allrevs[len(allrevs):] = revs
|
||||
allrevs.sort()
|
||||
allrevs.reverse()
|
||||
for rev in allrevs:
|
||||
formatrev(rev, prefix)
|
||||
|
||||
parsedateprog = re.compile(
|
||||
'^date: ([0-9]+)/([0-9]+)/([0-9]+) ' +
|
||||
'([0-9]+):([0-9]+):([0-9]+); author: ([^ ;]+)')
|
||||
|
||||
authormap = {
|
||||
'guido': 'Guido van Rossum <guido@cnri.reston.va.us>',
|
||||
'jack': 'Jack Jansen <jack@cwi.nl>',
|
||||
'sjoerd': 'Sjoerd Mullender <sjoerd@cwi.nl>',
|
||||
}
|
||||
|
||||
def formatrev(rev, prefix):
|
||||
dateline, file, revline, log = rev
|
||||
if parsedateprog.match(dateline) >= 0:
|
||||
fields = parsedateprog.group(1, 2, 3, 4, 5, 6)
|
||||
author = parsedateprog.group(7)
|
||||
if authormap.has_key(author): author = authormap[author]
|
||||
tfields = map(string.atoi, fields) + [0, 0, 0]
|
||||
tfields[5] = tfields[5] - time.timezone
|
||||
t = time.mktime(tuple(tfields))
|
||||
print time.ctime(t), '', author
|
||||
words = string.split(log)
|
||||
words[:0] = ['*', prefix + file + ':']
|
||||
maxcol = 72-8
|
||||
col = maxcol
|
||||
for word in words:
|
||||
if col > 0 and col + len(word) >= maxcol:
|
||||
print
|
||||
print '\t' + word,
|
||||
col = -1
|
||||
else:
|
||||
print word,
|
||||
col = col + 1 + len(word)
|
||||
print
|
||||
print
|
||||
|
||||
startprog = re.compile("^Working file: (.*)$")
|
||||
|
||||
def getnextfile(f):
|
||||
while 1:
|
||||
line = f.readline()
|
||||
if not line: return None
|
||||
if startprog.match(line) >= 0:
|
||||
file = startprog.group(1)
|
||||
# Skip until first revision
|
||||
while 1:
|
||||
line = f.readline()
|
||||
if not line: return None
|
||||
if line[:10] == '='*10: return None
|
||||
if line[:10] == '-'*10: break
|
||||
## print "Skipped", line,
|
||||
return file
|
||||
## else:
|
||||
## print "Ignored", line,
|
||||
|
||||
def getnextrev(f, file):
|
||||
# This is called when we are positioned just after a '---' separator
|
||||
revline = f.readline()
|
||||
dateline = f.readline()
|
||||
log = ''
|
||||
while 1:
|
||||
line = f.readline()
|
||||
if not line: break
|
||||
if line[:10] == '='*10:
|
||||
# Ignore the *last* log entry for each file since it
|
||||
# is the revision since which we are logging.
|
||||
return None
|
||||
if line[:10] == '-'*10: break
|
||||
log = log + line
|
||||
return dateline, file, revline, log
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
33
2.7/Python-2.7.16/Demo/pdist/rcsbump
Normal file
33
2.7/Python-2.7.16/Demo/pdist/rcsbump
Normal file
@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- python -*-
|
||||
#
|
||||
# guido's version, from rcsbump,v 1.2 1995/06/22 21:27:27 bwarsaw Exp
|
||||
#
|
||||
# Python script for bumping up an RCS major revision number.
|
||||
|
||||
import sys
|
||||
import re
|
||||
import rcslib
|
||||
import string
|
||||
|
||||
WITHLOCK = 1
|
||||
majorrev_re = re.compile('^[0-9]+')
|
||||
|
||||
dir = rcslib.RCS()
|
||||
|
||||
if sys.argv[1:]:
|
||||
files = sys.argv[1:]
|
||||
else:
|
||||
files = dir.listfiles()
|
||||
|
||||
for file in files:
|
||||
# get the major revnumber of the file
|
||||
headbranch = dir.info(file)['head']
|
||||
majorrev_re.match(headbranch)
|
||||
majorrev = string.atoi(majorrev_re.group(0)) + 1
|
||||
|
||||
if not dir.islocked(file):
|
||||
dir.checkout(file, WITHLOCK)
|
||||
|
||||
msg = "Bumping major revision number (to %d)" % majorrev
|
||||
dir.checkin((file, "%s.0" % majorrev), msg, "-f")
|
71
2.7/Python-2.7.16/Demo/pdist/rcsclient.py
Normal file
71
2.7/Python-2.7.16/Demo/pdist/rcsclient.py
Normal file
@ -0,0 +1,71 @@
|
||||
"""Customize this file to change the default client etc.
|
||||
|
||||
(In general, it is probably be better to make local operation the
|
||||
default and to require something like an RCSSERVER environment
|
||||
variable to enable remote operation.)
|
||||
|
||||
"""
|
||||
|
||||
import string
|
||||
import os
|
||||
|
||||
# These defaults don't belong here -- they should be taken from the
|
||||
# environment or from a hidden file in the current directory
|
||||
|
||||
HOST = 'voorn.cwi.nl'
|
||||
PORT = 4127
|
||||
VERBOSE = 1
|
||||
LOCAL = 0
|
||||
|
||||
import client
|
||||
|
||||
|
||||
class RCSProxyClient(client.SecureClient):
|
||||
|
||||
def __init__(self, address, verbose = client.VERBOSE):
|
||||
client.SecureClient.__init__(self, address, verbose)
|
||||
|
||||
|
||||
def openrcsclient(opts = []):
|
||||
"open an RCSProxy client based on a list of options returned by getopt"
|
||||
import RCSProxy
|
||||
host = HOST
|
||||
port = PORT
|
||||
verbose = VERBOSE
|
||||
local = LOCAL
|
||||
directory = None
|
||||
for o, a in opts:
|
||||
if o == '-h':
|
||||
host = a
|
||||
if ':' in host:
|
||||
i = string.find(host, ':')
|
||||
host, p = host[:i], host[i+1:]
|
||||
if p:
|
||||
port = string.atoi(p)
|
||||
if o == '-p':
|
||||
port = string.atoi(a)
|
||||
if o == '-d':
|
||||
directory = a
|
||||
if o == '-v':
|
||||
verbose = verbose + 1
|
||||
if o == '-q':
|
||||
verbose = 0
|
||||
if o == '-L':
|
||||
local = 1
|
||||
if local:
|
||||
import RCSProxy
|
||||
x = RCSProxy.RCSProxyLocal()
|
||||
else:
|
||||
address = (host, port)
|
||||
x = RCSProxyClient(address, verbose)
|
||||
if not directory:
|
||||
try:
|
||||
directory = open(os.path.join("CVS", "Repository")).readline()
|
||||
except IOError:
|
||||
pass
|
||||
else:
|
||||
if directory[-1] == '\n':
|
||||
directory = directory[:-1]
|
||||
if directory:
|
||||
x.cd(directory)
|
||||
return x
|
334
2.7/Python-2.7.16/Demo/pdist/rcslib.py
Normal file
334
2.7/Python-2.7.16/Demo/pdist/rcslib.py
Normal file
@ -0,0 +1,334 @@
|
||||
"""RCS interface module.
|
||||
|
||||
Defines the class RCS, which represents a directory with rcs version
|
||||
files and (possibly) corresponding work files.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
import fnmatch
|
||||
import os
|
||||
import re
|
||||
import string
|
||||
import tempfile
|
||||
|
||||
|
||||
class RCS:
|
||||
|
||||
"""RCS interface class (local filesystem version).
|
||||
|
||||
An instance of this class represents a directory with rcs version
|
||||
files and (possible) corresponding work files.
|
||||
|
||||
Methods provide access to most rcs operations such as
|
||||
checkin/checkout, access to the rcs metadata (revisions, logs,
|
||||
branches etc.) as well as some filesystem operations such as
|
||||
listing all rcs version files.
|
||||
|
||||
XXX BUGS / PROBLEMS
|
||||
|
||||
- The instance always represents the current directory so it's not
|
||||
very useful to have more than one instance around simultaneously
|
||||
|
||||
"""
|
||||
|
||||
# Characters allowed in work file names
|
||||
okchars = string.ascii_letters + string.digits + '-_=+'
|
||||
|
||||
def __init__(self):
|
||||
"""Constructor."""
|
||||
pass
|
||||
|
||||
def __del__(self):
|
||||
"""Destructor."""
|
||||
pass
|
||||
|
||||
# --- Informational methods about a single file/revision ---
|
||||
|
||||
def log(self, name_rev, otherflags = ''):
|
||||
"""Return the full log text for NAME_REV as a string.
|
||||
|
||||
Optional OTHERFLAGS are passed to rlog.
|
||||
|
||||
"""
|
||||
f = self._open(name_rev, 'rlog ' + otherflags)
|
||||
data = f.read()
|
||||
status = self._closepipe(f)
|
||||
if status:
|
||||
data = data + "%s: %s" % status
|
||||
elif data[-1] == '\n':
|
||||
data = data[:-1]
|
||||
return data
|
||||
|
||||
def head(self, name_rev):
|
||||
"""Return the head revision for NAME_REV"""
|
||||
dict = self.info(name_rev)
|
||||
return dict['head']
|
||||
|
||||
def info(self, name_rev):
|
||||
"""Return a dictionary of info (from rlog -h) for NAME_REV
|
||||
|
||||
The dictionary's keys are the keywords that rlog prints
|
||||
(e.g. 'head' and its values are the corresponding data
|
||||
(e.g. '1.3').
|
||||
|
||||
XXX symbolic names and locks are not returned
|
||||
|
||||
"""
|
||||
f = self._open(name_rev, 'rlog -h')
|
||||
dict = {}
|
||||
while 1:
|
||||
line = f.readline()
|
||||
if not line: break
|
||||
if line[0] == '\t':
|
||||
# XXX could be a lock or symbolic name
|
||||
# Anything else?
|
||||
continue
|
||||
i = string.find(line, ':')
|
||||
if i > 0:
|
||||
key, value = line[:i], string.strip(line[i+1:])
|
||||
dict[key] = value
|
||||
status = self._closepipe(f)
|
||||
if status:
|
||||
raise IOError, status
|
||||
return dict
|
||||
|
||||
# --- Methods that change files ---
|
||||
|
||||
def lock(self, name_rev):
|
||||
"""Set an rcs lock on NAME_REV."""
|
||||
name, rev = self.checkfile(name_rev)
|
||||
cmd = "rcs -l%s %s" % (rev, name)
|
||||
return self._system(cmd)
|
||||
|
||||
def unlock(self, name_rev):
|
||||
"""Clear an rcs lock on NAME_REV."""
|
||||
name, rev = self.checkfile(name_rev)
|
||||
cmd = "rcs -u%s %s" % (rev, name)
|
||||
return self._system(cmd)
|
||||
|
||||
def checkout(self, name_rev, withlock=0, otherflags=""):
|
||||
"""Check out NAME_REV to its work file.
|
||||
|
||||
If optional WITHLOCK is set, check out locked, else unlocked.
|
||||
|
||||
The optional OTHERFLAGS is passed to co without
|
||||
interpretation.
|
||||
|
||||
Any output from co goes to directly to stdout.
|
||||
|
||||
"""
|
||||
name, rev = self.checkfile(name_rev)
|
||||
if withlock: lockflag = "-l"
|
||||
else: lockflag = "-u"
|
||||
cmd = 'co %s%s %s %s' % (lockflag, rev, otherflags, name)
|
||||
return self._system(cmd)
|
||||
|
||||
def checkin(self, name_rev, message=None, otherflags=""):
|
||||
"""Check in NAME_REV from its work file.
|
||||
|
||||
The optional MESSAGE argument becomes the checkin message
|
||||
(default "<none>" if None); or the file description if this is
|
||||
a new file.
|
||||
|
||||
The optional OTHERFLAGS argument is passed to ci without
|
||||
interpretation.
|
||||
|
||||
Any output from ci goes to directly to stdout.
|
||||
|
||||
"""
|
||||
name, rev = self._unmangle(name_rev)
|
||||
new = not self.isvalid(name)
|
||||
if not message: message = "<none>"
|
||||
if message and message[-1] != '\n':
|
||||
message = message + '\n'
|
||||
lockflag = "-u"
|
||||
if new:
|
||||
f = tempfile.NamedTemporaryFile()
|
||||
f.write(message)
|
||||
f.flush()
|
||||
cmd = 'ci %s%s -t%s %s %s' % \
|
||||
(lockflag, rev, f.name, otherflags, name)
|
||||
else:
|
||||
message = re.sub(r'([\"$`])', r'\\\1', message)
|
||||
cmd = 'ci %s%s -m"%s" %s %s' % \
|
||||
(lockflag, rev, message, otherflags, name)
|
||||
return self._system(cmd)
|
||||
|
||||
# --- Exported support methods ---
|
||||
|
||||
def listfiles(self, pat = None):
|
||||
"""Return a list of all version files matching optional PATTERN."""
|
||||
files = os.listdir(os.curdir)
|
||||
files = filter(self._isrcs, files)
|
||||
if os.path.isdir('RCS'):
|
||||
files2 = os.listdir('RCS')
|
||||
files2 = filter(self._isrcs, files2)
|
||||
files = files + files2
|
||||
files = map(self.realname, files)
|
||||
return self._filter(files, pat)
|
||||
|
||||
def isvalid(self, name):
|
||||
"""Test whether NAME has a version file associated."""
|
||||
namev = self.rcsname(name)
|
||||
return (os.path.isfile(namev) or
|
||||
os.path.isfile(os.path.join('RCS', namev)))
|
||||
|
||||
def rcsname(self, name):
|
||||
"""Return the pathname of the version file for NAME.
|
||||
|
||||
The argument can be a work file name or a version file name.
|
||||
If the version file does not exist, the name of the version
|
||||
file that would be created by "ci" is returned.
|
||||
|
||||
"""
|
||||
if self._isrcs(name): namev = name
|
||||
else: namev = name + ',v'
|
||||
if os.path.isfile(namev): return namev
|
||||
namev = os.path.join('RCS', os.path.basename(namev))
|
||||
if os.path.isfile(namev): return namev
|
||||
if os.path.isdir('RCS'):
|
||||
return os.path.join('RCS', namev)
|
||||
else:
|
||||
return namev
|
||||
|
||||
def realname(self, namev):
|
||||
"""Return the pathname of the work file for NAME.
|
||||
|
||||
The argument can be a work file name or a version file name.
|
||||
If the work file does not exist, the name of the work file
|
||||
that would be created by "co" is returned.
|
||||
|
||||
"""
|
||||
if self._isrcs(namev): name = namev[:-2]
|
||||
else: name = namev
|
||||
if os.path.isfile(name): return name
|
||||
name = os.path.basename(name)
|
||||
return name
|
||||
|
||||
def islocked(self, name_rev):
|
||||
"""Test whether FILE (which must have a version file) is locked.
|
||||
|
||||
XXX This does not tell you which revision number is locked and
|
||||
ignores any revision you may pass in (by virtue of using rlog
|
||||
-L -R).
|
||||
|
||||
"""
|
||||
f = self._open(name_rev, 'rlog -L -R')
|
||||
line = f.readline()
|
||||
status = self._closepipe(f)
|
||||
if status:
|
||||
raise IOError, status
|
||||
if not line: return None
|
||||
if line[-1] == '\n':
|
||||
line = line[:-1]
|
||||
return self.realname(name_rev) == self.realname(line)
|
||||
|
||||
def checkfile(self, name_rev):
|
||||
"""Normalize NAME_REV into a (NAME, REV) tuple.
|
||||
|
||||
Raise an exception if there is no corresponding version file.
|
||||
|
||||
"""
|
||||
name, rev = self._unmangle(name_rev)
|
||||
if not self.isvalid(name):
|
||||
raise os.error, 'not an rcs file %r' % (name,)
|
||||
return name, rev
|
||||
|
||||
# --- Internal methods ---
|
||||
|
||||
def _open(self, name_rev, cmd = 'co -p', rflag = '-r'):
|
||||
"""INTERNAL: open a read pipe to NAME_REV using optional COMMAND.
|
||||
|
||||
Optional FLAG is used to indicate the revision (default -r).
|
||||
|
||||
Default COMMAND is "co -p".
|
||||
|
||||
Return a file object connected by a pipe to the command's
|
||||
output.
|
||||
|
||||
"""
|
||||
name, rev = self.checkfile(name_rev)
|
||||
namev = self.rcsname(name)
|
||||
if rev:
|
||||
cmd = cmd + ' ' + rflag + rev
|
||||
return os.popen("%s %r" % (cmd, namev))
|
||||
|
||||
def _unmangle(self, name_rev):
|
||||
"""INTERNAL: Normalize NAME_REV argument to (NAME, REV) tuple.
|
||||
|
||||
Raise an exception if NAME contains invalid characters.
|
||||
|
||||
A NAME_REV argument is either NAME string (implying REV='') or
|
||||
a tuple of the form (NAME, REV).
|
||||
|
||||
"""
|
||||
if type(name_rev) == type(''):
|
||||
name_rev = name, rev = name_rev, ''
|
||||
else:
|
||||
name, rev = name_rev
|
||||
for c in rev:
|
||||
if c not in self.okchars:
|
||||
raise ValueError, "bad char in rev"
|
||||
return name_rev
|
||||
|
||||
def _closepipe(self, f):
|
||||
"""INTERNAL: Close PIPE and print its exit status if nonzero."""
|
||||
sts = f.close()
|
||||
if not sts: return None
|
||||
detail, reason = divmod(sts, 256)
|
||||
if reason == 0: return 'exit', detail # Exit status
|
||||
signal = reason&0x7F
|
||||
if signal == 0x7F:
|
||||
code = 'stopped'
|
||||
signal = detail
|
||||
else:
|
||||
code = 'killed'
|
||||
if reason&0x80:
|
||||
code = code + '(coredump)'
|
||||
return code, signal
|
||||
|
||||
def _system(self, cmd):
|
||||
"""INTERNAL: run COMMAND in a subshell.
|
||||
|
||||
Standard input for the command is taken from /dev/null.
|
||||
|
||||
Raise IOError when the exit status is not zero.
|
||||
|
||||
Return whatever the calling method should return; normally
|
||||
None.
|
||||
|
||||
A derived class may override this method and redefine it to
|
||||
capture stdout/stderr of the command and return it.
|
||||
|
||||
"""
|
||||
cmd = cmd + " </dev/null"
|
||||
sts = os.system(cmd)
|
||||
if sts: raise IOError, "command exit status %d" % sts
|
||||
|
||||
def _filter(self, files, pat = None):
|
||||
"""INTERNAL: Return a sorted copy of the given list of FILES.
|
||||
|
||||
If a second PATTERN argument is given, only files matching it
|
||||
are kept. No check for valid filenames is made.
|
||||
|
||||
"""
|
||||
if pat:
|
||||
def keep(name, pat = pat):
|
||||
return fnmatch.fnmatch(name, pat)
|
||||
files = filter(keep, files)
|
||||
else:
|
||||
files = files[:]
|
||||
files.sort()
|
||||
return files
|
||||
|
||||
def _remove(self, fn):
|
||||
"""INTERNAL: remove FILE without complaints."""
|
||||
try:
|
||||
os.unlink(fn)
|
||||
except os.error:
|
||||
pass
|
||||
|
||||
def _isrcs(self, name):
|
||||
"""INTERNAL: Test whether NAME ends in ',v'."""
|
||||
return name[-2:] == ',v'
|
8
2.7/Python-2.7.16/Demo/pdist/rcvs
Normal file
8
2.7/Python-2.7.16/Demo/pdist/rcvs
Normal file
@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import addpack
|
||||
addpack.addpack('/home/guido/src/python/Demo/pdist')
|
||||
|
||||
import rcvs
|
||||
|
||||
rcvs.main()
|
477
2.7/Python-2.7.16/Demo/pdist/rcvs.py
Normal file
477
2.7/Python-2.7.16/Demo/pdist/rcvs.py
Normal file
@ -0,0 +1,477 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"""Remote CVS -- command line interface"""
|
||||
|
||||
# XXX To do:
|
||||
#
|
||||
# Bugs:
|
||||
# - if the remote file is deleted, "rcvs update" will fail
|
||||
#
|
||||
# Functionality:
|
||||
# - cvs rm
|
||||
# - descend into directories (alraedy done for update)
|
||||
# - conflict resolution
|
||||
# - other relevant commands?
|
||||
# - branches
|
||||
#
|
||||
# - Finesses:
|
||||
# - retain file mode's x bits
|
||||
# - complain when "nothing known about filename"
|
||||
# - edit log message the way CVS lets you edit it
|
||||
# - cvs diff -rREVA -rREVB
|
||||
# - send mail the way CVS sends it
|
||||
#
|
||||
# Performance:
|
||||
# - cache remote checksums (for every revision ever seen!)
|
||||
# - translate symbolic revisions to numeric revisions
|
||||
#
|
||||
# Reliability:
|
||||
# - remote locking
|
||||
#
|
||||
# Security:
|
||||
# - Authenticated RPC?
|
||||
|
||||
|
||||
from cvslib import CVS, File
|
||||
import md5
|
||||
import os
|
||||
import string
|
||||
import sys
|
||||
from cmdfw import CommandFrameWork
|
||||
|
||||
|
||||
DEF_LOCAL = 1 # Default -l
|
||||
|
||||
|
||||
class MyFile(File):
|
||||
|
||||
def action(self):
|
||||
"""Return a code indicating the update status of this file.
|
||||
|
||||
The possible return values are:
|
||||
|
||||
'=' -- everything's fine
|
||||
'0' -- file doesn't exist anywhere
|
||||
'?' -- exists locally only
|
||||
'A' -- new locally
|
||||
'R' -- deleted locally
|
||||
'U' -- changed remotely, no changes locally
|
||||
(includes new remotely or deleted remotely)
|
||||
'M' -- changed locally, no changes remotely
|
||||
'C' -- conflict: changed locally as well as remotely
|
||||
(includes cases where the file has been added
|
||||
or removed locally and remotely)
|
||||
'D' -- deleted remotely
|
||||
'N' -- new remotely
|
||||
'r' -- get rid of entry
|
||||
'c' -- create entry
|
||||
'u' -- update entry
|
||||
|
||||
(and probably others :-)
|
||||
"""
|
||||
if not self.lseen:
|
||||
self.getlocal()
|
||||
if not self.rseen:
|
||||
self.getremote()
|
||||
if not self.eseen:
|
||||
if not self.lsum:
|
||||
if not self.rsum: return '0' # Never heard of
|
||||
else:
|
||||
return 'N' # New remotely
|
||||
else: # self.lsum
|
||||
if not self.rsum: return '?' # Local only
|
||||
# Local and remote, but no entry
|
||||
if self.lsum == self.rsum:
|
||||
return 'c' # Restore entry only
|
||||
else: return 'C' # Real conflict
|
||||
else: # self.eseen
|
||||
if not self.lsum:
|
||||
if self.edeleted:
|
||||
if self.rsum: return 'R' # Removed
|
||||
else: return 'r' # Get rid of entry
|
||||
else: # not self.edeleted
|
||||
if self.rsum:
|
||||
print "warning:",
|
||||
print self.file,
|
||||
print "was lost"
|
||||
return 'U'
|
||||
else: return 'r' # Get rid of entry
|
||||
else: # self.lsum
|
||||
if not self.rsum:
|
||||
if self.enew: return 'A' # New locally
|
||||
else: return 'D' # Deleted remotely
|
||||
else: # self.rsum
|
||||
if self.enew:
|
||||
if self.lsum == self.rsum:
|
||||
return 'u'
|
||||
else:
|
||||
return 'C'
|
||||
if self.lsum == self.esum:
|
||||
if self.esum == self.rsum:
|
||||
return '='
|
||||
else:
|
||||
return 'U'
|
||||
elif self.esum == self.rsum:
|
||||
return 'M'
|
||||
elif self.lsum == self.rsum:
|
||||
return 'u'
|
||||
else:
|
||||
return 'C'
|
||||
|
||||
def update(self):
|
||||
code = self.action()
|
||||
if code == '=': return
|
||||
print code, self.file
|
||||
if code in ('U', 'N'):
|
||||
self.get()
|
||||
elif code == 'C':
|
||||
print "%s: conflict resolution not yet implemented" % \
|
||||
self.file
|
||||
elif code == 'D':
|
||||
remove(self.file)
|
||||
self.eseen = 0
|
||||
elif code == 'r':
|
||||
self.eseen = 0
|
||||
elif code in ('c', 'u'):
|
||||
self.eseen = 1
|
||||
self.erev = self.rrev
|
||||
self.enew = 0
|
||||
self.edeleted = 0
|
||||
self.esum = self.rsum
|
||||
self.emtime, self.ectime = os.stat(self.file)[-2:]
|
||||
self.extra = ''
|
||||
|
||||
def commit(self, message = ""):
|
||||
code = self.action()
|
||||
if code in ('A', 'M'):
|
||||
self.put(message)
|
||||
return 1
|
||||
elif code == 'R':
|
||||
print "%s: committing removes not yet implemented" % \
|
||||
self.file
|
||||
elif code == 'C':
|
||||
print "%s: conflict resolution not yet implemented" % \
|
||||
self.file
|
||||
|
||||
def diff(self, opts = []):
|
||||
self.action() # To update lseen, rseen
|
||||
flags = ''
|
||||
rev = self.rrev
|
||||
# XXX should support two rev options too!
|
||||
for o, a in opts:
|
||||
if o == '-r':
|
||||
rev = a
|
||||
else:
|
||||
flags = flags + ' ' + o + a
|
||||
if rev == self.rrev and self.lsum == self.rsum:
|
||||
return
|
||||
flags = flags[1:]
|
||||
fn = self.file
|
||||
data = self.proxy.get((fn, rev))
|
||||
sum = md5.new(data).digest()
|
||||
if self.lsum == sum:
|
||||
return
|
||||
import tempfile
|
||||
tf = tempfile.NamedTemporaryFile()
|
||||
tf.write(data)
|
||||
tf.flush()
|
||||
print 'diff %s -r%s %s' % (flags, rev, fn)
|
||||
sts = os.system('diff %s %s %s' % (flags, tf.name, fn))
|
||||
if sts:
|
||||
print '='*70
|
||||
|
||||
def commitcheck(self):
|
||||
return self.action() != 'C'
|
||||
|
||||
def put(self, message = ""):
|
||||
print "Checking in", self.file, "..."
|
||||
data = open(self.file).read()
|
||||
if not self.enew:
|
||||
self.proxy.lock(self.file)
|
||||
messages = self.proxy.put(self.file, data, message)
|
||||
if messages:
|
||||
print messages
|
||||
self.setentry(self.proxy.head(self.file), self.lsum)
|
||||
|
||||
def get(self):
|
||||
data = self.proxy.get(self.file)
|
||||
f = open(self.file, 'w')
|
||||
f.write(data)
|
||||
f.close()
|
||||
self.setentry(self.rrev, self.rsum)
|
||||
|
||||
def log(self, otherflags):
|
||||
print self.proxy.log(self.file, otherflags)
|
||||
|
||||
def add(self):
|
||||
self.eseen = 0 # While we're hacking...
|
||||
self.esum = self.lsum
|
||||
self.emtime, self.ectime = 0, 0
|
||||
self.erev = ''
|
||||
self.enew = 1
|
||||
self.edeleted = 0
|
||||
self.eseen = 1 # Done
|
||||
self.extra = ''
|
||||
|
||||
def setentry(self, erev, esum):
|
||||
self.eseen = 0 # While we're hacking...
|
||||
self.esum = esum
|
||||
self.emtime, self.ectime = os.stat(self.file)[-2:]
|
||||
self.erev = erev
|
||||
self.enew = 0
|
||||
self.edeleted = 0
|
||||
self.eseen = 1 # Done
|
||||
self.extra = ''
|
||||
|
||||
|
||||
SENDMAIL = "/usr/lib/sendmail -t"
|
||||
MAILFORM = """To: %s
|
||||
Subject: CVS changes: %s
|
||||
|
||||
...Message from rcvs...
|
||||
|
||||
Committed files:
|
||||
%s
|
||||
|
||||
Log message:
|
||||
%s
|
||||
"""
|
||||
|
||||
|
||||
class RCVS(CVS):
|
||||
|
||||
FileClass = MyFile
|
||||
|
||||
def __init__(self):
|
||||
CVS.__init__(self)
|
||||
|
||||
def update(self, files):
|
||||
for e in self.whichentries(files, 1):
|
||||
e.update()
|
||||
|
||||
def commit(self, files, message = ""):
|
||||
list = self.whichentries(files)
|
||||
if not list: return
|
||||
ok = 1
|
||||
for e in list:
|
||||
if not e.commitcheck():
|
||||
ok = 0
|
||||
if not ok:
|
||||
print "correct above errors first"
|
||||
return
|
||||
if not message:
|
||||
message = raw_input("One-liner: ")
|
||||
committed = []
|
||||
for e in list:
|
||||
if e.commit(message):
|
||||
committed.append(e.file)
|
||||
self.mailinfo(committed, message)
|
||||
|
||||
def mailinfo(self, files, message = ""):
|
||||
towhom = "sjoerd@cwi.nl, jack@cwi.nl" # XXX
|
||||
mailtext = MAILFORM % (towhom, string.join(files),
|
||||
string.join(files), message)
|
||||
print '-'*70
|
||||
print mailtext
|
||||
print '-'*70
|
||||
ok = raw_input("OK to mail to %s? " % towhom)
|
||||
if string.lower(string.strip(ok)) in ('y', 'ye', 'yes'):
|
||||
p = os.popen(SENDMAIL, "w")
|
||||
p.write(mailtext)
|
||||
sts = p.close()
|
||||
if sts:
|
||||
print "Sendmail exit status %s" % str(sts)
|
||||
else:
|
||||
print "Mail sent."
|
||||
else:
|
||||
print "No mail sent."
|
||||
|
||||
def report(self, files):
|
||||
for e in self.whichentries(files):
|
||||
e.report()
|
||||
|
||||
def diff(self, files, opts):
|
||||
for e in self.whichentries(files):
|
||||
e.diff(opts)
|
||||
|
||||
def add(self, files):
|
||||
if not files:
|
||||
raise RuntimeError, "'cvs add' needs at least one file"
|
||||
list = []
|
||||
for e in self.whichentries(files, 1):
|
||||
e.add()
|
||||
|
||||
def rm(self, files):
|
||||
if not files:
|
||||
raise RuntimeError, "'cvs rm' needs at least one file"
|
||||
raise RuntimeError, "'cvs rm' not yet imlemented"
|
||||
|
||||
def log(self, files, opts):
|
||||
flags = ''
|
||||
for o, a in opts:
|
||||
flags = flags + ' ' + o + a
|
||||
for e in self.whichentries(files):
|
||||
e.log(flags)
|
||||
|
||||
def whichentries(self, files, localfilestoo = 0):
|
||||
if files:
|
||||
list = []
|
||||
for file in files:
|
||||
if self.entries.has_key(file):
|
||||
e = self.entries[file]
|
||||
else:
|
||||
e = self.FileClass(file)
|
||||
self.entries[file] = e
|
||||
list.append(e)
|
||||
else:
|
||||
list = self.entries.values()
|
||||
for file in self.proxy.listfiles():
|
||||
if self.entries.has_key(file):
|
||||
continue
|
||||
e = self.FileClass(file)
|
||||
self.entries[file] = e
|
||||
list.append(e)
|
||||
if localfilestoo:
|
||||
for file in os.listdir(os.curdir):
|
||||
if not self.entries.has_key(file) \
|
||||
and not self.ignored(file):
|
||||
e = self.FileClass(file)
|
||||
self.entries[file] = e
|
||||
list.append(e)
|
||||
list.sort()
|
||||
if self.proxy:
|
||||
for e in list:
|
||||
if e.proxy is None:
|
||||
e.proxy = self.proxy
|
||||
return list
|
||||
|
||||
|
||||
class rcvs(CommandFrameWork):
|
||||
|
||||
GlobalFlags = 'd:h:p:qvL'
|
||||
UsageMessage = \
|
||||
"usage: rcvs [-d directory] [-h host] [-p port] [-q] [-v] [subcommand arg ...]"
|
||||
PostUsageMessage = \
|
||||
"If no subcommand is given, the status of all files is listed"
|
||||
|
||||
def __init__(self):
|
||||
"""Constructor."""
|
||||
CommandFrameWork.__init__(self)
|
||||
self.proxy = None
|
||||
self.cvs = RCVS()
|
||||
|
||||
def close(self):
|
||||
if self.proxy:
|
||||
self.proxy._close()
|
||||
self.proxy = None
|
||||
|
||||
def recurse(self):
|
||||
self.close()
|
||||
names = os.listdir(os.curdir)
|
||||
for name in names:
|
||||
if name == os.curdir or name == os.pardir:
|
||||
continue
|
||||
if name == "CVS":
|
||||
continue
|
||||
if not os.path.isdir(name):
|
||||
continue
|
||||
if os.path.islink(name):
|
||||
continue
|
||||
print "--- entering subdirectory", name, "---"
|
||||
os.chdir(name)
|
||||
try:
|
||||
if os.path.isdir("CVS"):
|
||||
self.__class__().run()
|
||||
else:
|
||||
self.recurse()
|
||||
finally:
|
||||
os.chdir(os.pardir)
|
||||
print "--- left subdirectory", name, "---"
|
||||
|
||||
def options(self, opts):
|
||||
self.opts = opts
|
||||
|
||||
def ready(self):
|
||||
import rcsclient
|
||||
self.proxy = rcsclient.openrcsclient(self.opts)
|
||||
self.cvs.setproxy(self.proxy)
|
||||
self.cvs.getentries()
|
||||
|
||||
def default(self):
|
||||
self.cvs.report([])
|
||||
|
||||
def do_report(self, opts, files):
|
||||
self.cvs.report(files)
|
||||
|
||||
def do_update(self, opts, files):
|
||||
"""update [-l] [-R] [file] ..."""
|
||||
local = DEF_LOCAL
|
||||
for o, a in opts:
|
||||
if o == '-l': local = 1
|
||||
if o == '-R': local = 0
|
||||
self.cvs.update(files)
|
||||
self.cvs.putentries()
|
||||
if not local and not files:
|
||||
self.recurse()
|
||||
flags_update = '-lR'
|
||||
do_up = do_update
|
||||
flags_up = flags_update
|
||||
|
||||
def do_commit(self, opts, files):
|
||||
"""commit [-m message] [file] ..."""
|
||||
message = ""
|
||||
for o, a in opts:
|
||||
if o == '-m': message = a
|
||||
self.cvs.commit(files, message)
|
||||
self.cvs.putentries()
|
||||
flags_commit = 'm:'
|
||||
do_com = do_commit
|
||||
flags_com = flags_commit
|
||||
|
||||
def do_diff(self, opts, files):
|
||||
"""diff [difflags] [file] ..."""
|
||||
self.cvs.diff(files, opts)
|
||||
flags_diff = 'cbitwcefhnlr:sD:S:'
|
||||
do_dif = do_diff
|
||||
flags_dif = flags_diff
|
||||
|
||||
def do_add(self, opts, files):
|
||||
"""add file ..."""
|
||||
if not files:
|
||||
print "'rcvs add' requires at least one file"
|
||||
return
|
||||
self.cvs.add(files)
|
||||
self.cvs.putentries()
|
||||
|
||||
def do_remove(self, opts, files):
|
||||
"""remove file ..."""
|
||||
if not files:
|
||||
print "'rcvs remove' requires at least one file"
|
||||
return
|
||||
self.cvs.remove(files)
|
||||
self.cvs.putentries()
|
||||
do_rm = do_remove
|
||||
|
||||
def do_log(self, opts, files):
|
||||
"""log [rlog-options] [file] ..."""
|
||||
self.cvs.log(files, opts)
|
||||
flags_log = 'bhLNRtd:s:V:r:'
|
||||
|
||||
|
||||
def remove(fn):
|
||||
try:
|
||||
os.unlink(fn)
|
||||
except os.error:
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
r = rcvs()
|
||||
try:
|
||||
r.run()
|
||||
finally:
|
||||
r.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
8
2.7/Python-2.7.16/Demo/pdist/rrcs
Normal file
8
2.7/Python-2.7.16/Demo/pdist/rrcs
Normal file
@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import addpack
|
||||
addpack.addpack('/home/guido/src/python/Demo/pdist')
|
||||
|
||||
import rrcs
|
||||
|
||||
rrcs.main()
|
160
2.7/Python-2.7.16/Demo/pdist/rrcs.py
Normal file
160
2.7/Python-2.7.16/Demo/pdist/rrcs.py
Normal file
@ -0,0 +1,160 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"Remote RCS -- command line interface"
|
||||
|
||||
import sys
|
||||
import os
|
||||
import getopt
|
||||
import string
|
||||
import md5
|
||||
import tempfile
|
||||
from rcsclient import openrcsclient
|
||||
|
||||
def main():
|
||||
sys.stdout = sys.stderr
|
||||
try:
|
||||
opts, rest = getopt.getopt(sys.argv[1:], 'h:p:d:qvL')
|
||||
if not rest:
|
||||
cmd = 'head'
|
||||
else:
|
||||
cmd, rest = rest[0], rest[1:]
|
||||
if not commands.has_key(cmd):
|
||||
raise getopt.error, "unknown command"
|
||||
coptset, func = commands[cmd]
|
||||
copts, files = getopt.getopt(rest, coptset)
|
||||
except getopt.error, msg:
|
||||
print msg
|
||||
print "usage: rrcs [options] command [options] [file] ..."
|
||||
print "where command can be:"
|
||||
print " ci|put # checkin the given files"
|
||||
print " co|get # checkout"
|
||||
print " info # print header info"
|
||||
print " head # print revision of head branch"
|
||||
print " list # list filename if valid"
|
||||
print " log # print full log"
|
||||
print " diff # diff rcs file and work file"
|
||||
print "if no files are given, all remote rcs files are assumed"
|
||||
sys.exit(2)
|
||||
x = openrcsclient(opts)
|
||||
if not files:
|
||||
files = x.listfiles()
|
||||
for fn in files:
|
||||
try:
|
||||
func(x, copts, fn)
|
||||
except (IOError, os.error), msg:
|
||||
print "%s: %s" % (fn, msg)
|
||||
|
||||
def checkin(x, copts, fn):
|
||||
f = open(fn)
|
||||
data = f.read()
|
||||
f.close()
|
||||
new = not x.isvalid(fn)
|
||||
if not new and same(x, copts, fn, data):
|
||||
print "%s: unchanged since last checkin" % fn
|
||||
return
|
||||
print "Checking in", fn, "..."
|
||||
message = asklogmessage(new)
|
||||
messages = x.put(fn, data, message)
|
||||
if messages:
|
||||
print messages
|
||||
|
||||
def checkout(x, copts, fn):
|
||||
data = x.get(fn)
|
||||
f = open(fn, 'w')
|
||||
f.write(data)
|
||||
f.close()
|
||||
|
||||
def lock(x, copts, fn):
|
||||
x.lock(fn)
|
||||
|
||||
def unlock(x, copts, fn):
|
||||
x.unlock(fn)
|
||||
|
||||
def info(x, copts, fn):
|
||||
dict = x.info(fn)
|
||||
keys = dict.keys()
|
||||
keys.sort()
|
||||
for key in keys:
|
||||
print key + ':', dict[key]
|
||||
print '='*70
|
||||
|
||||
def head(x, copts, fn):
|
||||
head = x.head(fn)
|
||||
print fn, head
|
||||
|
||||
def list(x, copts, fn):
|
||||
if x.isvalid(fn):
|
||||
print fn
|
||||
|
||||
def log(x, copts, fn):
|
||||
flags = ''
|
||||
for o, a in copts:
|
||||
flags = flags + ' ' + o + a
|
||||
flags = flags[1:]
|
||||
messages = x.log(fn, flags)
|
||||
print messages
|
||||
|
||||
def diff(x, copts, fn):
|
||||
if same(x, copts, fn):
|
||||
return
|
||||
flags = ''
|
||||
for o, a in copts:
|
||||
flags = flags + ' ' + o + a
|
||||
flags = flags[1:]
|
||||
data = x.get(fn)
|
||||
tf = tempfile.NamedTemporaryFile()
|
||||
tf.write(data)
|
||||
tf.flush()
|
||||
print 'diff %s -r%s %s' % (flags, x.head(fn), fn)
|
||||
sts = os.system('diff %s %s %s' % (flags, tf.name, fn))
|
||||
if sts:
|
||||
print '='*70
|
||||
|
||||
def same(x, copts, fn, data = None):
|
||||
if data is None:
|
||||
f = open(fn)
|
||||
data = f.read()
|
||||
f.close()
|
||||
lsum = md5.new(data).digest()
|
||||
rsum = x.sum(fn)
|
||||
return lsum == rsum
|
||||
|
||||
def asklogmessage(new):
|
||||
if new:
|
||||
print "enter description,",
|
||||
else:
|
||||
print "enter log message,",
|
||||
print "terminate with single '.' or end of file:"
|
||||
if new:
|
||||
print "NOTE: This is NOT the log message!"
|
||||
message = ""
|
||||
while 1:
|
||||
sys.stderr.write(">> ")
|
||||
sys.stderr.flush()
|
||||
line = sys.stdin.readline()
|
||||
if not line or line == '.\n': break
|
||||
message = message + line
|
||||
return message
|
||||
|
||||
def remove(fn):
|
||||
try:
|
||||
os.unlink(fn)
|
||||
except os.error:
|
||||
pass
|
||||
|
||||
commands = {
|
||||
'ci': ('', checkin),
|
||||
'put': ('', checkin),
|
||||
'co': ('', checkout),
|
||||
'get': ('', checkout),
|
||||
'info': ('', info),
|
||||
'head': ('', head),
|
||||
'list': ('', list),
|
||||
'lock': ('', lock),
|
||||
'unlock': ('', unlock),
|
||||
'log': ('bhLRtd:l:r:s:w:V:', log),
|
||||
'diff': ('c', diff),
|
||||
}
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
33
2.7/Python-2.7.16/Demo/pdist/security.py
Normal file
33
2.7/Python-2.7.16/Demo/pdist/security.py
Normal file
@ -0,0 +1,33 @@
|
||||
class Security:
|
||||
|
||||
def __init__(self):
|
||||
import os
|
||||
env = os.environ
|
||||
if env.has_key('PYTHON_KEYFILE'):
|
||||
keyfile = env['PYTHON_KEYFILE']
|
||||
else:
|
||||
keyfile = '.python_keyfile'
|
||||
if env.has_key('HOME'):
|
||||
keyfile = os.path.join(env['HOME'], keyfile)
|
||||
if not os.path.exists(keyfile):
|
||||
import sys
|
||||
for dir in sys.path:
|
||||
kf = os.path.join(dir, keyfile)
|
||||
if os.path.exists(kf):
|
||||
keyfile = kf
|
||||
break
|
||||
try:
|
||||
self._key = eval(open(keyfile).readline())
|
||||
except IOError:
|
||||
raise IOError, "python keyfile %s: cannot open" % keyfile
|
||||
|
||||
def _generate_challenge(self):
|
||||
import random
|
||||
return random.randint(100, 100000)
|
||||
|
||||
def _compare_challenge_response(self, challenge, response):
|
||||
return self._encode_challenge(challenge) == response
|
||||
|
||||
def _encode_challenge(self, challenge):
|
||||
p, m = self._key
|
||||
return pow(long(challenge), p, m)
|
145
2.7/Python-2.7.16/Demo/pdist/server.py
Normal file
145
2.7/Python-2.7.16/Demo/pdist/server.py
Normal file
@ -0,0 +1,145 @@
|
||||
"""RPC Server module."""
|
||||
|
||||
import sys
|
||||
import socket
|
||||
import pickle
|
||||
from fnmatch import fnmatch
|
||||
from repr import repr
|
||||
|
||||
|
||||
# Default verbosity (0 = silent, 1 = print connections, 2 = print requests too)
|
||||
VERBOSE = 1
|
||||
|
||||
|
||||
class Server:
|
||||
|
||||
"""RPC Server class. Derive a class to implement a particular service."""
|
||||
|
||||
def __init__(self, address, verbose = VERBOSE):
|
||||
if type(address) == type(0):
|
||||
address = ('', address)
|
||||
self._address = address
|
||||
self._verbose = verbose
|
||||
self._socket = None
|
||||
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self._socket.bind(address)
|
||||
self._socket.listen(1)
|
||||
self._listening = 1
|
||||
|
||||
def _setverbose(self, verbose):
|
||||
self._verbose = verbose
|
||||
|
||||
def __del__(self):
|
||||
self._close()
|
||||
|
||||
def _close(self):
|
||||
self._listening = 0
|
||||
if self._socket:
|
||||
self._socket.close()
|
||||
self._socket = None
|
||||
|
||||
def _serverloop(self):
|
||||
while self._listening:
|
||||
self._serve()
|
||||
|
||||
def _serve(self):
|
||||
if self._verbose: print "Wait for connection ..."
|
||||
conn, address = self._socket.accept()
|
||||
if self._verbose: print "Accepted connection from %s" % repr(address)
|
||||
if not self._verify(conn, address):
|
||||
print "*** Connection from %s refused" % repr(address)
|
||||
conn.close()
|
||||
return
|
||||
rf = conn.makefile('r')
|
||||
wf = conn.makefile('w')
|
||||
ok = 1
|
||||
while ok:
|
||||
wf.flush()
|
||||
if self._verbose > 1: print "Wait for next request ..."
|
||||
ok = self._dorequest(rf, wf)
|
||||
|
||||
_valid = ['192.16.201.*', '192.16.197.*', '132.151.1.*', '129.6.64.*']
|
||||
|
||||
def _verify(self, conn, address):
|
||||
host, port = address
|
||||
for pat in self._valid:
|
||||
if fnmatch(host, pat): return 1
|
||||
return 0
|
||||
|
||||
def _dorequest(self, rf, wf):
|
||||
rp = pickle.Unpickler(rf)
|
||||
try:
|
||||
request = rp.load()
|
||||
except EOFError:
|
||||
return 0
|
||||
if self._verbose > 1: print "Got request: %s" % repr(request)
|
||||
try:
|
||||
methodname, args, id = request
|
||||
if '.' in methodname:
|
||||
reply = (None, self._special(methodname, args), id)
|
||||
elif methodname[0] == '_':
|
||||
raise NameError, "illegal method name %s" % repr(methodname)
|
||||
else:
|
||||
method = getattr(self, methodname)
|
||||
reply = (None, apply(method, args), id)
|
||||
except:
|
||||
reply = (sys.exc_type, sys.exc_value, id)
|
||||
if id < 0 and reply[:2] == (None, None):
|
||||
if self._verbose > 1: print "Suppress reply"
|
||||
return 1
|
||||
if self._verbose > 1: print "Send reply: %s" % repr(reply)
|
||||
wp = pickle.Pickler(wf)
|
||||
wp.dump(reply)
|
||||
return 1
|
||||
|
||||
def _special(self, methodname, args):
|
||||
if methodname == '.methods':
|
||||
if not hasattr(self, '_methods'):
|
||||
self._methods = tuple(self._listmethods())
|
||||
return self._methods
|
||||
raise NameError, "unrecognized special method name %s" % repr(methodname)
|
||||
|
||||
def _listmethods(self, cl=None):
|
||||
if not cl: cl = self.__class__
|
||||
names = cl.__dict__.keys()
|
||||
names = filter(lambda x: x[0] != '_', names)
|
||||
names.sort()
|
||||
for base in cl.__bases__:
|
||||
basenames = self._listmethods(base)
|
||||
basenames = filter(lambda x, names=names: x not in names, basenames)
|
||||
names[len(names):] = basenames
|
||||
return names
|
||||
|
||||
|
||||
from security import Security
|
||||
|
||||
|
||||
class SecureServer(Server, Security):
|
||||
|
||||
def __init__(self, *args):
|
||||
apply(Server.__init__, (self,) + args)
|
||||
Security.__init__(self)
|
||||
|
||||
def _verify(self, conn, address):
|
||||
import string
|
||||
challenge = self._generate_challenge()
|
||||
conn.send("%d\n" % challenge)
|
||||
response = ""
|
||||
while "\n" not in response and len(response) < 100:
|
||||
data = conn.recv(100)
|
||||
if not data:
|
||||
break
|
||||
response = response + data
|
||||
try:
|
||||
response = string.atol(string.strip(response))
|
||||
except string.atol_error:
|
||||
if self._verbose > 0:
|
||||
print "Invalid response syntax", repr(response)
|
||||
return 0
|
||||
if not self._compare_challenge_response(challenge, response):
|
||||
if self._verbose > 0:
|
||||
print "Invalid response value", repr(response)
|
||||
return 0
|
||||
if self._verbose > 1:
|
||||
print "Response matches challenge. Go ahead!"
|
||||
return 1
|
24
2.7/Python-2.7.16/Demo/pdist/sumtree.py
Normal file
24
2.7/Python-2.7.16/Demo/pdist/sumtree.py
Normal file
@ -0,0 +1,24 @@
|
||||
import time
|
||||
import FSProxy
|
||||
|
||||
def main():
|
||||
t1 = time.time()
|
||||
#proxy = FSProxy.FSProxyClient(('voorn.cwi.nl', 4127))
|
||||
proxy = FSProxy.FSProxyLocal()
|
||||
sumtree(proxy)
|
||||
proxy._close()
|
||||
t2 = time.time()
|
||||
print t2-t1, "seconds"
|
||||
raw_input("[Return to exit] ")
|
||||
|
||||
def sumtree(proxy):
|
||||
print "PWD =", proxy.pwd()
|
||||
files = proxy.listfiles()
|
||||
proxy.infolist(files)
|
||||
subdirs = proxy.listsubdirs()
|
||||
for name in subdirs:
|
||||
proxy.cd(name)
|
||||
sumtree(proxy)
|
||||
proxy.back()
|
||||
|
||||
main()
|
57
2.7/Python-2.7.16/Demo/pysvr/Makefile
Normal file
57
2.7/Python-2.7.16/Demo/pysvr/Makefile
Normal file
@ -0,0 +1,57 @@
|
||||
# Makefile for 'pysvr' application embedding Python.
|
||||
# Tailored for Python 1.5a3 or later.
|
||||
# Some details are specific for Solaris or CNRI.
|
||||
# Also see ## comments for tailoring.
|
||||
|
||||
# Which C compiler
|
||||
CC=gcc
|
||||
##PURIFY=/usr/local/pure/purify
|
||||
LINKCC=$(PURIFY) $(CC)
|
||||
|
||||
# Optimization preferences
|
||||
OPT=-g
|
||||
|
||||
# Which Python version we're using
|
||||
VER=2.2
|
||||
|
||||
# Expressions using the above definitions
|
||||
PYVER=python$(VER)
|
||||
|
||||
# Use these defs when compiling against installed Python
|
||||
##INST=/usr/local
|
||||
##PYC=$(INST)/lib/$(PYVER)/config
|
||||
##PYINCL=-I$(INST)/include/$(PYVER) -I$(PYC)
|
||||
##PYLIBS=$(PYC)/lib$(PYVER).a
|
||||
|
||||
# Use these defs when compiling against built Python
|
||||
PLAT=linux
|
||||
PYINCL=-I../../Include -I../../$(PLAT)
|
||||
PYLIBS=../../$(PLAT)/lib$(PYVER).a
|
||||
|
||||
# Libraries to link with -- very installation dependent
|
||||
# (See LIBS= in Modules/Makefile in build tree)
|
||||
RLLIBS=-lreadline -ltermcap
|
||||
OTHERLIBS=-lnsl -lpthread -ldl -lm -ldb -lutil
|
||||
|
||||
# Compilation and link flags -- no need to change normally
|
||||
CFLAGS=$(OPT)
|
||||
CPPFLAGS=$(PYINCL)
|
||||
LIBS=$(PYLIBS) $(RLLIBS) $(OTHERLIBS)
|
||||
|
||||
# Default port for the pysvr application
|
||||
PORT=4000
|
||||
|
||||
# Default target
|
||||
all: pysvr
|
||||
|
||||
# Target to build pysvr
|
||||
pysvr: pysvr.o $(PYOBJS) $(PYLIBS)
|
||||
$(LINKCC) pysvr.o $(LIBS) -o pysvr
|
||||
|
||||
# Target to build and run pysvr
|
||||
run: pysvr
|
||||
pysvr $(PORT)
|
||||
|
||||
# Target to clean up the directory
|
||||
clean:
|
||||
-rm -f pysvr *.o *~ core
|
9
2.7/Python-2.7.16/Demo/pysvr/README
Normal file
9
2.7/Python-2.7.16/Demo/pysvr/README
Normal file
@ -0,0 +1,9 @@
|
||||
This is an example of a multi-threaded C application embedding a
|
||||
Python interpreter.
|
||||
|
||||
The particular application is a multi-threaded telnet-like server that
|
||||
provides you with a Python prompt (instead of a shell prompt).
|
||||
|
||||
The file pysvr.py is a prototype in Python.
|
||||
|
||||
THIS APPLICATION IS NOT SECURE -- ONLY USE IT FOR TESTING!
|
370
2.7/Python-2.7.16/Demo/pysvr/pysvr.c
Normal file
370
2.7/Python-2.7.16/Demo/pysvr/pysvr.c
Normal file
@ -0,0 +1,370 @@
|
||||
/* A multi-threaded telnet-like server that gives a Python prompt.
|
||||
|
||||
Usage: pysvr [port]
|
||||
|
||||
For security reasons, it only accepts requests from the current host.
|
||||
This can still be insecure, but restricts violations from people who
|
||||
can log in on your machine. Use with caution!
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <getopt.h>
|
||||
|
||||
/* XXX Umpfh.
|
||||
Python.h defines a typedef destructor, which conflicts with pthread.h.
|
||||
So Python.h must be included after pthread.h. */
|
||||
|
||||
#include "Python.h"
|
||||
|
||||
extern int Py_VerboseFlag;
|
||||
|
||||
#ifndef PORT
|
||||
#define PORT 4000
|
||||
#endif
|
||||
|
||||
struct workorder {
|
||||
int conn;
|
||||
struct sockaddr_in addr;
|
||||
};
|
||||
|
||||
/* Forward */
|
||||
static void init_python(void);
|
||||
static void usage(void);
|
||||
static void oprogname(void);
|
||||
static void main_thread(int);
|
||||
static void create_thread(int, struct sockaddr_in *);
|
||||
static void *service_thread(struct workorder *);
|
||||
static void run_interpreter(FILE *, FILE *);
|
||||
static int run_command(char *, PyObject *);
|
||||
static void ps(void);
|
||||
|
||||
static char *progname = "pysvr";
|
||||
|
||||
static PyThreadState *gtstate;
|
||||
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int port = PORT;
|
||||
int c;
|
||||
|
||||
if (argc > 0 && argv[0] != NULL && argv[0][0] != '\0')
|
||||
progname = argv[0];
|
||||
|
||||
while ((c = getopt(argc, argv, "v")) != EOF) {
|
||||
switch (c) {
|
||||
case 'v':
|
||||
Py_VerboseFlag++;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc) {
|
||||
if (optind+1 < argc) {
|
||||
oprogname();
|
||||
fprintf(stderr, "too many arguments\n");
|
||||
usage();
|
||||
}
|
||||
port = atoi(argv[optind]);
|
||||
if (port <= 0) {
|
||||
fprintf(stderr, "bad port (%s)\n", argv[optind]);
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
main_thread(port);
|
||||
|
||||
fprintf(stderr, "Bye.\n");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static char usage_line[] = "usage: %s [port]\n";
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, usage_line, progname);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
static void
|
||||
main_thread(int port)
|
||||
{
|
||||
int sock, conn, size, i;
|
||||
struct sockaddr_in addr, clientaddr;
|
||||
|
||||
sock = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0) {
|
||||
oprogname();
|
||||
perror("can't create socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef SO_REUSEADDR
|
||||
i = 1;
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &i, sizeof i);
|
||||
#endif
|
||||
|
||||
memset((char *)&addr, '\0', sizeof addr);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
addr.sin_addr.s_addr = 0L;
|
||||
if (bind(sock, (struct sockaddr *)&addr, sizeof addr) < 0) {
|
||||
oprogname();
|
||||
perror("can't bind socket to address");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (listen(sock, 5) < 0) {
|
||||
oprogname();
|
||||
perror("can't listen on socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Listening on port %d...\n", port);
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
size = sizeof clientaddr;
|
||||
memset((char *) &clientaddr, '\0', size);
|
||||
conn = accept(sock, (struct sockaddr *) &clientaddr, &size);
|
||||
if (conn < 0) {
|
||||
oprogname();
|
||||
perror("can't accept connection from socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
size = sizeof addr;
|
||||
memset((char *) &addr, '\0', size);
|
||||
if (getsockname(conn, (struct sockaddr *)&addr, &size) < 0) {
|
||||
oprogname();
|
||||
perror("can't get socket name of connection");
|
||||
exit(1);
|
||||
}
|
||||
if (clientaddr.sin_addr.s_addr != addr.sin_addr.s_addr) {
|
||||
oprogname();
|
||||
perror("connection from non-local host refused");
|
||||
fprintf(stderr, "(addr=%lx, clientaddr=%lx)\n",
|
||||
ntohl(addr.sin_addr.s_addr),
|
||||
ntohl(clientaddr.sin_addr.s_addr));
|
||||
close(conn);
|
||||
continue;
|
||||
}
|
||||
if (i == 4) {
|
||||
close(conn);
|
||||
break;
|
||||
}
|
||||
create_thread(conn, &clientaddr);
|
||||
}
|
||||
|
||||
close(sock);
|
||||
|
||||
if (gtstate) {
|
||||
PyEval_AcquireThread(gtstate);
|
||||
gtstate = NULL;
|
||||
Py_Finalize();
|
||||
/* And a second time, just because we can. */
|
||||
Py_Finalize(); /* This should be harmless. */
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void
|
||||
create_thread(int conn, struct sockaddr_in *addr)
|
||||
{
|
||||
struct workorder *work;
|
||||
pthread_t tdata;
|
||||
|
||||
work = malloc(sizeof(struct workorder));
|
||||
if (work == NULL) {
|
||||
oprogname();
|
||||
fprintf(stderr, "out of memory for thread.\n");
|
||||
close(conn);
|
||||
return;
|
||||
}
|
||||
work->conn = conn;
|
||||
work->addr = *addr;
|
||||
|
||||
init_python();
|
||||
|
||||
if (pthread_create(&tdata, NULL, (void *)service_thread, work) < 0) {
|
||||
oprogname();
|
||||
perror("can't create new thread");
|
||||
close(conn);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pthread_detach(tdata) < 0) {
|
||||
oprogname();
|
||||
perror("can't detach from thread");
|
||||
}
|
||||
}
|
||||
|
||||
static PyThreadState *the_tstate;
|
||||
static PyInterpreterState *the_interp;
|
||||
static PyObject *the_builtins;
|
||||
|
||||
static void
|
||||
init_python(void)
|
||||
{
|
||||
if (gtstate)
|
||||
return;
|
||||
Py_Initialize(); /* Initialize the interpreter */
|
||||
PyEval_InitThreads(); /* Create (and acquire) the interpreter lock */
|
||||
gtstate = PyEval_SaveThread(); /* Release the thread state */
|
||||
}
|
||||
|
||||
static void *
|
||||
service_thread(struct workorder *work)
|
||||
{
|
||||
FILE *input, *output;
|
||||
|
||||
fprintf(stderr, "Start thread for connection %d.\n", work->conn);
|
||||
|
||||
ps();
|
||||
|
||||
input = fdopen(work->conn, "r");
|
||||
if (input == NULL) {
|
||||
oprogname();
|
||||
perror("can't create input stream");
|
||||
goto done;
|
||||
}
|
||||
|
||||
output = fdopen(work->conn, "w");
|
||||
if (output == NULL) {
|
||||
oprogname();
|
||||
perror("can't create output stream");
|
||||
fclose(input);
|
||||
goto done;
|
||||
}
|
||||
|
||||
setvbuf(input, NULL, _IONBF, 0);
|
||||
setvbuf(output, NULL, _IONBF, 0);
|
||||
|
||||
run_interpreter(input, output);
|
||||
|
||||
fclose(input);
|
||||
fclose(output);
|
||||
|
||||
done:
|
||||
fprintf(stderr, "End thread for connection %d.\n", work->conn);
|
||||
close(work->conn);
|
||||
free(work);
|
||||
}
|
||||
|
||||
static void
|
||||
oprogname(void)
|
||||
{
|
||||
int save = errno;
|
||||
fprintf(stderr, "%s: ", progname);
|
||||
errno = save;
|
||||
}
|
||||
|
||||
static void
|
||||
run_interpreter(FILE *input, FILE *output)
|
||||
{
|
||||
PyThreadState *tstate;
|
||||
PyObject *new_stdin, *new_stdout;
|
||||
PyObject *mainmod, *globals;
|
||||
char buffer[1000];
|
||||
char *p, *q;
|
||||
int n, end;
|
||||
|
||||
PyEval_AcquireLock();
|
||||
tstate = Py_NewInterpreter();
|
||||
if (tstate == NULL) {
|
||||
fprintf(output, "Sorry -- can't create an interpreter\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mainmod = PyImport_AddModule("__main__");
|
||||
globals = PyModule_GetDict(mainmod);
|
||||
Py_INCREF(globals);
|
||||
|
||||
new_stdin = PyFile_FromFile(input, "<socket-in>", "r", NULL);
|
||||
new_stdout = PyFile_FromFile(output, "<socket-out>", "w", NULL);
|
||||
|
||||
PySys_SetObject("stdin", new_stdin);
|
||||
PySys_SetObject("stdout", new_stdout);
|
||||
PySys_SetObject("stderr", new_stdout);
|
||||
|
||||
for (n = 1; !PyErr_Occurred(); n++) {
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
fprintf(output, "%d> ", n);
|
||||
p = fgets(buffer, sizeof buffer, input);
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
if (p == NULL)
|
||||
break;
|
||||
if (p[0] == '\377' && p[1] == '\354')
|
||||
break;
|
||||
|
||||
q = strrchr(p, '\r');
|
||||
if (q && q[1] == '\n' && q[2] == '\0') {
|
||||
*q++ = '\n';
|
||||
*q++ = '\0';
|
||||
}
|
||||
|
||||
while (*p && isspace(*p))
|
||||
p++;
|
||||
if (p[0] == '#' || p[0] == '\0')
|
||||
continue;
|
||||
|
||||
end = run_command(buffer, globals);
|
||||
if (end < 0)
|
||||
PyErr_Print();
|
||||
|
||||
if (end)
|
||||
break;
|
||||
}
|
||||
|
||||
Py_XDECREF(globals);
|
||||
Py_XDECREF(new_stdin);
|
||||
Py_XDECREF(new_stdout);
|
||||
|
||||
Py_EndInterpreter(tstate);
|
||||
PyEval_ReleaseLock();
|
||||
|
||||
fprintf(output, "Goodbye!\n");
|
||||
}
|
||||
|
||||
static int
|
||||
run_command(char *buffer, PyObject *globals)
|
||||
{
|
||||
PyObject *m, *d, *v;
|
||||
fprintf(stderr, "run_command: %s", buffer);
|
||||
if (strchr(buffer, '\n') == NULL)
|
||||
fprintf(stderr, "\n");
|
||||
v = PyRun_String(buffer, Py_single_input, globals, globals);
|
||||
if (v == NULL) {
|
||||
if (PyErr_Occurred() == PyExc_SystemExit) {
|
||||
PyErr_Clear();
|
||||
return 1;
|
||||
}
|
||||
PyErr_Print();
|
||||
return 0;
|
||||
}
|
||||
Py_DECREF(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ps(void)
|
||||
{
|
||||
char buffer[100];
|
||||
PyOS_snprintf(buffer, sizeof(buffer),
|
||||
"ps -l -p %d </dev/null | sed 1d\n", getpid());
|
||||
system(buffer);
|
||||
}
|
124
2.7/Python-2.7.16/Demo/pysvr/pysvr.py
Normal file
124
2.7/Python-2.7.16/Demo/pysvr/pysvr.py
Normal file
@ -0,0 +1,124 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"""A multi-threaded telnet-like server that gives a Python prompt.
|
||||
|
||||
This is really a prototype for the same thing in C.
|
||||
|
||||
Usage: pysvr.py [port]
|
||||
|
||||
For security reasons, it only accepts requests from the current host.
|
||||
This can still be insecure, but restricts violations from people who
|
||||
can log in on your machine. Use with caution!
|
||||
|
||||
"""
|
||||
|
||||
import sys, os, string, getopt, thread, socket, traceback
|
||||
|
||||
PORT = 4000 # Default port
|
||||
|
||||
def main():
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "")
|
||||
if len(args) > 1:
|
||||
raise getopt.error, "Too many arguments."
|
||||
except getopt.error, msg:
|
||||
usage(msg)
|
||||
for o, a in opts:
|
||||
pass
|
||||
if args:
|
||||
try:
|
||||
port = string.atoi(args[0])
|
||||
except ValueError, msg:
|
||||
usage(msg)
|
||||
else:
|
||||
port = PORT
|
||||
main_thread(port)
|
||||
|
||||
def usage(msg=None):
|
||||
sys.stdout = sys.stderr
|
||||
if msg:
|
||||
print msg
|
||||
print "\n", __doc__,
|
||||
sys.exit(2)
|
||||
|
||||
def main_thread(port):
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.bind(("", port))
|
||||
sock.listen(5)
|
||||
print "Listening on port", port, "..."
|
||||
while 1:
|
||||
(conn, addr) = sock.accept()
|
||||
if addr[0] != conn.getsockname()[0]:
|
||||
conn.close()
|
||||
print "Refusing connection from non-local host", addr[0], "."
|
||||
continue
|
||||
thread.start_new_thread(service_thread, (conn, addr))
|
||||
del conn, addr
|
||||
|
||||
def service_thread(conn, addr):
|
||||
(caddr, cport) = addr
|
||||
print "Thread %s has connection from %s.\n" % (str(thread.get_ident()),
|
||||
caddr),
|
||||
stdin = conn.makefile("r")
|
||||
stdout = conn.makefile("w", 0)
|
||||
run_interpreter(stdin, stdout)
|
||||
print "Thread %s is done.\n" % str(thread.get_ident()),
|
||||
|
||||
def run_interpreter(stdin, stdout):
|
||||
globals = {}
|
||||
try:
|
||||
str(sys.ps1)
|
||||
except:
|
||||
sys.ps1 = ">>> "
|
||||
source = ""
|
||||
while 1:
|
||||
stdout.write(sys.ps1)
|
||||
line = stdin.readline()
|
||||
if line[:2] == '\377\354':
|
||||
line = ""
|
||||
if not line and not source:
|
||||
break
|
||||
if line[-2:] == '\r\n':
|
||||
line = line[:-2] + '\n'
|
||||
source = source + line
|
||||
try:
|
||||
code = compile_command(source)
|
||||
except SyntaxError, err:
|
||||
source = ""
|
||||
traceback.print_exception(SyntaxError, err, None, file=stdout)
|
||||
continue
|
||||
if not code:
|
||||
continue
|
||||
source = ""
|
||||
try:
|
||||
run_command(code, stdin, stdout, globals)
|
||||
except SystemExit, how:
|
||||
if how:
|
||||
try:
|
||||
how = str(how)
|
||||
except:
|
||||
how = ""
|
||||
stdout.write("Exit %s\n" % how)
|
||||
break
|
||||
stdout.write("\nGoodbye.\n")
|
||||
|
||||
def run_command(code, stdin, stdout, globals):
|
||||
save = sys.stdin, sys.stdout, sys.stderr
|
||||
try:
|
||||
sys.stdout = sys.stderr = stdout
|
||||
sys.stdin = stdin
|
||||
try:
|
||||
exec code in globals
|
||||
except SystemExit, how:
|
||||
raise SystemExit, how, sys.exc_info()[2]
|
||||
except:
|
||||
type, value, tb = sys.exc_info()
|
||||
if tb: tb = tb.tb_next
|
||||
traceback.print_exception(type, value, tb)
|
||||
del tb
|
||||
finally:
|
||||
sys.stdin, sys.stdout, sys.stderr = save
|
||||
|
||||
from code import compile_command
|
||||
|
||||
main()
|
10
2.7/Python-2.7.16/Demo/rpc/MANIFEST
Normal file
10
2.7/Python-2.7.16/Demo/rpc/MANIFEST
Normal file
@ -0,0 +1,10 @@
|
||||
File Name Archive # Description
|
||||
-----------------------------------------------------------
|
||||
MANIFEST 1 This shipping list
|
||||
README 1
|
||||
T.py 1
|
||||
mountclient.py 1
|
||||
nfsclient.py 1
|
||||
rpc.py 1
|
||||
test 1
|
||||
xdr.py 1
|
31
2.7/Python-2.7.16/Demo/rpc/README
Normal file
31
2.7/Python-2.7.16/Demo/rpc/README
Normal file
@ -0,0 +1,31 @@
|
||||
This is a Python interface to Sun RPC, designed and implemented mostly
|
||||
by reading the Internet RFCs about the subject.
|
||||
|
||||
*** NOTE: xdr.py has evolved into the standard module xdrlib.py ***
|
||||
|
||||
There are two library modules, xdr.py and rpc.py, and several example
|
||||
clients: mountclient.py, nfsclient.py, and rnusersclient.py,
|
||||
implementing the NFS Mount protocol, (part of) the NFS protocol, and
|
||||
the "rnusers" protocol (used by rusers(1)), respectively. The latter
|
||||
demonstrates the use of broadcast via the Port mapper's CALLIT
|
||||
procedure.
|
||||
|
||||
There is also a way to create servers in Python.
|
||||
|
||||
To test the nfs client, run it from the shell with something like this:
|
||||
|
||||
python -c 'import nfsclient; nfsclient.test()' [hostname [filesystemname]]
|
||||
|
||||
When called without a filesystemname, it lists the filesystems at the
|
||||
host; default host is the local machine.
|
||||
|
||||
Other clients are tested similarly.
|
||||
|
||||
For hostname, use e.g. wuarchive.wustl.edu or gatekeeper.dec.com (two
|
||||
hosts that are known to export NFS filesystems with little restrictions).
|
||||
|
||||
There are now two different RPC compilers:
|
||||
|
||||
1) Wim Lewis rpcgen.py found on http://www.omnigroup.com/~wiml/soft/stale-index.html#python.
|
||||
|
||||
2) Peter Åstrands rpcgen.py, which is part of "pynfs" (http://www.cendio.se/~peter/pynfs/).
|
22
2.7/Python-2.7.16/Demo/rpc/T.py
Normal file
22
2.7/Python-2.7.16/Demo/rpc/T.py
Normal file
@ -0,0 +1,22 @@
|
||||
# Simple interface to report execution times of program fragments.
|
||||
# Call TSTART() to reset the timer, TSTOP(...) to report times.
|
||||
|
||||
import sys, os, time
|
||||
|
||||
def TSTART():
|
||||
global t0, t1
|
||||
u, s, cu, cs = os.times()
|
||||
t0 = u+cu, s+cs, time.time()
|
||||
|
||||
def TSTOP(*label):
|
||||
global t0, t1
|
||||
u, s, cu, cs = os.times()
|
||||
t1 = u+cu, s+cs, time.time()
|
||||
tt = []
|
||||
for i in range(3):
|
||||
tt.append(t1[i] - t0[i])
|
||||
[u, s, r] = tt
|
||||
msg = ''
|
||||
for x in label: msg = msg + (x + ' ')
|
||||
msg = msg + '%r user, %r sys, %r real\n' % (u, s, r)
|
||||
sys.stderr.write(msg)
|
202
2.7/Python-2.7.16/Demo/rpc/mountclient.py
Normal file
202
2.7/Python-2.7.16/Demo/rpc/mountclient.py
Normal file
@ -0,0 +1,202 @@
|
||||
# Mount RPC client -- RFC 1094 (NFS), Appendix A
|
||||
|
||||
# This module demonstrates how to write your own RPC client in Python.
|
||||
# When this example was written, there was no RPC compiler for
|
||||
# Python. Without such a compiler, you must first create classes
|
||||
# derived from Packer and Unpacker to handle the data types for the
|
||||
# server you want to interface to. You then write the client class.
|
||||
# If you want to support both the TCP and the UDP version of a
|
||||
# protocol, use multiple inheritance as shown below.
|
||||
|
||||
|
||||
import rpc
|
||||
from rpc import Packer, Unpacker, TCPClient, UDPClient
|
||||
|
||||
|
||||
# Program number and version for the mount protocol
|
||||
MOUNTPROG = 100005
|
||||
MOUNTVERS = 1
|
||||
|
||||
# Size of the 'fhandle' opaque structure
|
||||
FHSIZE = 32
|
||||
|
||||
|
||||
# Packer derived class for Mount protocol clients.
|
||||
# The only thing we need to pack beyond basic types is an 'fhandle'
|
||||
|
||||
class MountPacker(Packer):
|
||||
|
||||
def pack_fhandle(self, fhandle):
|
||||
self.pack_fopaque(FHSIZE, fhandle)
|
||||
|
||||
|
||||
# Unpacker derived class for Mount protocol clients.
|
||||
# The important types we need to unpack are fhandle, fhstatus,
|
||||
# mountlist and exportlist; mountstruct, exportstruct and groups are
|
||||
# used to unpack components of mountlist and exportlist and the
|
||||
# corresponding functions are passed as function argument to the
|
||||
# generic unpack_list function.
|
||||
|
||||
class MountUnpacker(Unpacker):
|
||||
|
||||
def unpack_fhandle(self):
|
||||
return self.unpack_fopaque(FHSIZE)
|
||||
|
||||
def unpack_fhstatus(self):
|
||||
status = self.unpack_uint()
|
||||
if status == 0:
|
||||
fh = self.unpack_fhandle()
|
||||
else:
|
||||
fh = None
|
||||
return status, fh
|
||||
|
||||
def unpack_mountlist(self):
|
||||
return self.unpack_list(self.unpack_mountstruct)
|
||||
|
||||
def unpack_mountstruct(self):
|
||||
hostname = self.unpack_string()
|
||||
directory = self.unpack_string()
|
||||
return (hostname, directory)
|
||||
|
||||
def unpack_exportlist(self):
|
||||
return self.unpack_list(self.unpack_exportstruct)
|
||||
|
||||
def unpack_exportstruct(self):
|
||||
filesys = self.unpack_string()
|
||||
groups = self.unpack_groups()
|
||||
return (filesys, groups)
|
||||
|
||||
def unpack_groups(self):
|
||||
return self.unpack_list(self.unpack_string)
|
||||
|
||||
|
||||
# These are the procedures specific to the Mount client class.
|
||||
# Think of this as a derived class of either TCPClient or UDPClient.
|
||||
|
||||
class PartialMountClient:
|
||||
|
||||
# This method is called by Client.__init__ to initialize
|
||||
# self.packer and self.unpacker
|
||||
def addpackers(self):
|
||||
self.packer = MountPacker()
|
||||
self.unpacker = MountUnpacker('')
|
||||
|
||||
# This method is called by Client.__init__ to bind the socket
|
||||
# to a particular network interface and port. We use the
|
||||
# default network interface, but if we're running as root,
|
||||
# we want to bind to a reserved port
|
||||
def bindsocket(self):
|
||||
import os
|
||||
try:
|
||||
uid = os.getuid()
|
||||
except AttributeError:
|
||||
uid = 1
|
||||
if uid == 0:
|
||||
port = rpc.bindresvport(self.sock, '')
|
||||
# 'port' is not used
|
||||
else:
|
||||
self.sock.bind(('', 0))
|
||||
|
||||
# This function is called to cough up a suitable
|
||||
# authentication object for a call to procedure 'proc'.
|
||||
def mkcred(self):
|
||||
if self.cred is None:
|
||||
self.cred = rpc.AUTH_UNIX, rpc.make_auth_unix_default()
|
||||
return self.cred
|
||||
|
||||
# The methods Mnt, Dump etc. each implement one Remote
|
||||
# Procedure Call. This is done by calling self.make_call()
|
||||
# with as arguments:
|
||||
#
|
||||
# - the procedure number
|
||||
# - the arguments (or None)
|
||||
# - the "packer" function for the arguments (or None)
|
||||
# - the "unpacker" function for the return value (or None)
|
||||
#
|
||||
# The packer and unpacker function, if not None, *must* be
|
||||
# methods of self.packer and self.unpacker, respectively.
|
||||
# A value of None means that there are no arguments or is no
|
||||
# return value, respectively.
|
||||
#
|
||||
# The return value from make_call() is the return value from
|
||||
# the remote procedure call, as unpacked by the "unpacker"
|
||||
# function, or None if the unpacker function is None.
|
||||
#
|
||||
# (Even if you expect a result of None, you should still
|
||||
# return the return value from make_call(), since this may be
|
||||
# needed by a broadcasting version of the class.)
|
||||
#
|
||||
# If the call fails, make_call() raises an exception
|
||||
# (this includes time-outs and invalid results).
|
||||
#
|
||||
# Note that (at least with the UDP protocol) there is no
|
||||
# guarantee that a call is executed at most once. When you do
|
||||
# get a reply, you know it has been executed at least once;
|
||||
# when you don't get a reply, you know nothing.
|
||||
|
||||
def Mnt(self, directory):
|
||||
return self.make_call(1, directory, \
|
||||
self.packer.pack_string, \
|
||||
self.unpacker.unpack_fhstatus)
|
||||
|
||||
def Dump(self):
|
||||
return self.make_call(2, None, \
|
||||
None, self.unpacker.unpack_mountlist)
|
||||
|
||||
def Umnt(self, directory):
|
||||
return self.make_call(3, directory, \
|
||||
self.packer.pack_string, None)
|
||||
|
||||
def Umntall(self):
|
||||
return self.make_call(4, None, None, None)
|
||||
|
||||
def Export(self):
|
||||
return self.make_call(5, None, \
|
||||
None, self.unpacker.unpack_exportlist)
|
||||
|
||||
|
||||
# We turn the partial Mount client into a full one for either protocol
|
||||
# by use of multiple inheritance. (In general, when class C has base
|
||||
# classes B1...Bn, if x is an instance of class C, methods of x are
|
||||
# searched first in C, then in B1, then in B2, ..., finally in Bn.)
|
||||
|
||||
class TCPMountClient(PartialMountClient, TCPClient):
|
||||
|
||||
def __init__(self, host):
|
||||
TCPClient.__init__(self, host, MOUNTPROG, MOUNTVERS)
|
||||
|
||||
|
||||
class UDPMountClient(PartialMountClient, UDPClient):
|
||||
|
||||
def __init__(self, host):
|
||||
UDPClient.__init__(self, host, MOUNTPROG, MOUNTVERS)
|
||||
|
||||
|
||||
# A little test program for the Mount client. This takes a host as
|
||||
# command line argument (default the local machine), prints its export
|
||||
# list, and attempts to mount and unmount each exported files system.
|
||||
# An optional first argument of -t or -u specifies the protocol to use
|
||||
# (TCP or UDP), default is UDP.
|
||||
|
||||
def test():
|
||||
import sys
|
||||
if sys.argv[1:] and sys.argv[1] == '-t':
|
||||
C = TCPMountClient
|
||||
del sys.argv[1]
|
||||
elif sys.argv[1:] and sys.argv[1] == '-u':
|
||||
C = UDPMountClient
|
||||
del sys.argv[1]
|
||||
else:
|
||||
C = UDPMountClient
|
||||
if sys.argv[1:]: host = sys.argv[1]
|
||||
else: host = ''
|
||||
mcl = C(host)
|
||||
list = mcl.Export()
|
||||
for item in list:
|
||||
print item
|
||||
try:
|
||||
mcl.Mnt(item[0])
|
||||
except:
|
||||
print 'Sorry'
|
||||
continue
|
||||
mcl.Umnt(item[0])
|
201
2.7/Python-2.7.16/Demo/rpc/nfsclient.py
Normal file
201
2.7/Python-2.7.16/Demo/rpc/nfsclient.py
Normal file
@ -0,0 +1,201 @@
|
||||
# NFS RPC client -- RFC 1094
|
||||
|
||||
# XXX This is not yet complete.
|
||||
# XXX Only GETATTR, SETTTR, LOOKUP and READDIR are supported.
|
||||
|
||||
# (See mountclient.py for some hints on how to write RPC clients in
|
||||
# Python in general)
|
||||
|
||||
import rpc
|
||||
from rpc import UDPClient, TCPClient
|
||||
from mountclient import FHSIZE, MountPacker, MountUnpacker
|
||||
|
||||
NFS_PROGRAM = 100003
|
||||
NFS_VERSION = 2
|
||||
|
||||
# enum stat
|
||||
NFS_OK = 0
|
||||
# (...many error values...)
|
||||
|
||||
# enum ftype
|
||||
NFNON = 0
|
||||
NFREG = 1
|
||||
NFDIR = 2
|
||||
NFBLK = 3
|
||||
NFCHR = 4
|
||||
NFLNK = 5
|
||||
|
||||
|
||||
class NFSPacker(MountPacker):
|
||||
|
||||
def pack_sattrargs(self, sa):
|
||||
file, attributes = sa
|
||||
self.pack_fhandle(file)
|
||||
self.pack_sattr(attributes)
|
||||
|
||||
def pack_sattr(self, sa):
|
||||
mode, uid, gid, size, atime, mtime = sa
|
||||
self.pack_uint(mode)
|
||||
self.pack_uint(uid)
|
||||
self.pack_uint(gid)
|
||||
self.pack_uint(size)
|
||||
self.pack_timeval(atime)
|
||||
self.pack_timeval(mtime)
|
||||
|
||||
def pack_diropargs(self, da):
|
||||
dir, name = da
|
||||
self.pack_fhandle(dir)
|
||||
self.pack_string(name)
|
||||
|
||||
def pack_readdirargs(self, ra):
|
||||
dir, cookie, count = ra
|
||||
self.pack_fhandle(dir)
|
||||
self.pack_uint(cookie)
|
||||
self.pack_uint(count)
|
||||
|
||||
def pack_timeval(self, tv):
|
||||
secs, usecs = tv
|
||||
self.pack_uint(secs)
|
||||
self.pack_uint(usecs)
|
||||
|
||||
|
||||
class NFSUnpacker(MountUnpacker):
|
||||
|
||||
def unpack_readdirres(self):
|
||||
status = self.unpack_enum()
|
||||
if status == NFS_OK:
|
||||
entries = self.unpack_list(self.unpack_entry)
|
||||
eof = self.unpack_bool()
|
||||
rest = (entries, eof)
|
||||
else:
|
||||
rest = None
|
||||
return (status, rest)
|
||||
|
||||
def unpack_entry(self):
|
||||
fileid = self.unpack_uint()
|
||||
name = self.unpack_string()
|
||||
cookie = self.unpack_uint()
|
||||
return (fileid, name, cookie)
|
||||
|
||||
def unpack_diropres(self):
|
||||
status = self.unpack_enum()
|
||||
if status == NFS_OK:
|
||||
fh = self.unpack_fhandle()
|
||||
fa = self.unpack_fattr()
|
||||
rest = (fh, fa)
|
||||
else:
|
||||
rest = None
|
||||
return (status, rest)
|
||||
|
||||
def unpack_attrstat(self):
|
||||
status = self.unpack_enum()
|
||||
if status == NFS_OK:
|
||||
attributes = self.unpack_fattr()
|
||||
else:
|
||||
attributes = None
|
||||
return status, attributes
|
||||
|
||||
def unpack_fattr(self):
|
||||
type = self.unpack_enum()
|
||||
mode = self.unpack_uint()
|
||||
nlink = self.unpack_uint()
|
||||
uid = self.unpack_uint()
|
||||
gid = self.unpack_uint()
|
||||
size = self.unpack_uint()
|
||||
blocksize = self.unpack_uint()
|
||||
rdev = self.unpack_uint()
|
||||
blocks = self.unpack_uint()
|
||||
fsid = self.unpack_uint()
|
||||
fileid = self.unpack_uint()
|
||||
atime = self.unpack_timeval()
|
||||
mtime = self.unpack_timeval()
|
||||
ctime = self.unpack_timeval()
|
||||
return (type, mode, nlink, uid, gid, size, blocksize, \
|
||||
rdev, blocks, fsid, fileid, atime, mtime, ctime)
|
||||
|
||||
def unpack_timeval(self):
|
||||
secs = self.unpack_uint()
|
||||
usecs = self.unpack_uint()
|
||||
return (secs, usecs)
|
||||
|
||||
|
||||
class NFSClient(UDPClient):
|
||||
|
||||
def __init__(self, host):
|
||||
UDPClient.__init__(self, host, NFS_PROGRAM, NFS_VERSION)
|
||||
|
||||
def addpackers(self):
|
||||
self.packer = NFSPacker()
|
||||
self.unpacker = NFSUnpacker('')
|
||||
|
||||
def mkcred(self):
|
||||
if self.cred is None:
|
||||
self.cred = rpc.AUTH_UNIX, rpc.make_auth_unix_default()
|
||||
return self.cred
|
||||
|
||||
def Getattr(self, fh):
|
||||
return self.make_call(1, fh, \
|
||||
self.packer.pack_fhandle, \
|
||||
self.unpacker.unpack_attrstat)
|
||||
|
||||
def Setattr(self, sa):
|
||||
return self.make_call(2, sa, \
|
||||
self.packer.pack_sattrargs, \
|
||||
self.unpacker.unpack_attrstat)
|
||||
|
||||
# Root() is obsolete
|
||||
|
||||
def Lookup(self, da):
|
||||
return self.make_call(4, da, \
|
||||
self.packer.pack_diropargs, \
|
||||
self.unpacker.unpack_diropres)
|
||||
|
||||
# ...
|
||||
|
||||
def Readdir(self, ra):
|
||||
return self.make_call(16, ra, \
|
||||
self.packer.pack_readdirargs, \
|
||||
self.unpacker.unpack_readdirres)
|
||||
|
||||
# Shorthand to get the entire contents of a directory
|
||||
def Listdir(self, dir):
|
||||
list = []
|
||||
ra = (dir, 0, 2000)
|
||||
while 1:
|
||||
(status, rest) = self.Readdir(ra)
|
||||
if status <> NFS_OK:
|
||||
break
|
||||
entries, eof = rest
|
||||
last_cookie = None
|
||||
for fileid, name, cookie in entries:
|
||||
list.append((fileid, name))
|
||||
last_cookie = cookie
|
||||
if eof or last_cookie is None:
|
||||
break
|
||||
ra = (ra[0], last_cookie, ra[2])
|
||||
return list
|
||||
|
||||
|
||||
def test():
|
||||
import sys
|
||||
if sys.argv[1:]: host = sys.argv[1]
|
||||
else: host = ''
|
||||
if sys.argv[2:]: filesys = sys.argv[2]
|
||||
else: filesys = None
|
||||
from mountclient import UDPMountClient, TCPMountClient
|
||||
mcl = TCPMountClient(host)
|
||||
if filesys is None:
|
||||
list = mcl.Export()
|
||||
for item in list:
|
||||
print item
|
||||
return
|
||||
sf = mcl.Mnt(filesys)
|
||||
print sf
|
||||
fh = sf[1]
|
||||
if fh:
|
||||
ncl = NFSClient(host)
|
||||
attrstat = ncl.Getattr(fh)
|
||||
print attrstat
|
||||
list = ncl.Listdir(fh)
|
||||
for item in list: print item
|
||||
mcl.Umnt(filesys)
|
98
2.7/Python-2.7.16/Demo/rpc/rnusersclient.py
Normal file
98
2.7/Python-2.7.16/Demo/rpc/rnusersclient.py
Normal file
@ -0,0 +1,98 @@
|
||||
# Remote nusers client interface
|
||||
|
||||
import rpc
|
||||
from rpc import Packer, Unpacker, UDPClient, BroadcastUDPClient
|
||||
|
||||
|
||||
class RnusersPacker(Packer):
|
||||
def pack_utmp(self, ui):
|
||||
ut_line, ut_name, ut_host, ut_time = utmp
|
||||
self.pack_string(ut_line)
|
||||
self.pack_string(ut_name)
|
||||
self.pack_string(ut_host)
|
||||
self.pack_int(ut_time)
|
||||
def pack_utmpidle(self, ui):
|
||||
ui_itmp, ui_idle = ui
|
||||
self.pack_utmp(ui_utmp)
|
||||
self.pack_uint(ui_idle)
|
||||
def pack_utmpidlearr(self, list):
|
||||
self.pack_array(list, self.pack_itmpidle)
|
||||
|
||||
|
||||
class RnusersUnpacker(Unpacker):
|
||||
def unpack_utmp(self):
|
||||
ut_line = self.unpack_string()
|
||||
ut_name = self.unpack_string()
|
||||
ut_host = self.unpack_string()
|
||||
ut_time = self.unpack_int()
|
||||
return ut_line, ut_name, ut_host, ut_time
|
||||
def unpack_utmpidle(self):
|
||||
ui_utmp = self.unpack_utmp()
|
||||
ui_idle = self.unpack_uint()
|
||||
return ui_utmp, ui_idle
|
||||
def unpack_utmpidlearr(self):
|
||||
return self.unpack_array(self.unpack_utmpidle)
|
||||
|
||||
|
||||
class PartialRnusersClient:
|
||||
|
||||
def addpackers(self):
|
||||
self.packer = RnusersPacker()
|
||||
self.unpacker = RnusersUnpacker('')
|
||||
|
||||
def Num(self):
|
||||
return self.make_call(1, None, None, self.unpacker.unpack_int)
|
||||
|
||||
def Names(self):
|
||||
return self.make_call(2, None, \
|
||||
None, self.unpacker.unpack_utmpidlearr)
|
||||
|
||||
def Allnames(self):
|
||||
return self.make_call(3, None, \
|
||||
None, self.unpacker.unpack_utmpidlearr)
|
||||
|
||||
|
||||
class RnusersClient(PartialRnusersClient, UDPClient):
|
||||
|
||||
def __init__(self, host):
|
||||
UDPClient.__init__(self, host, 100002, 2)
|
||||
|
||||
|
||||
class BroadcastRnusersClient(PartialRnusersClient, BroadcastUDPClient):
|
||||
|
||||
def __init__(self, bcastaddr):
|
||||
BroadcastUDPClient.__init__(self, bcastaddr, 100002, 2)
|
||||
|
||||
|
||||
def test():
|
||||
import sys
|
||||
if not sys.argv[1:]:
|
||||
testbcast()
|
||||
return
|
||||
else:
|
||||
host = sys.argv[1]
|
||||
c = RnusersClient(host)
|
||||
list = c.Names()
|
||||
for (line, name, host, time), idle in list:
|
||||
line = strip0(line)
|
||||
name = strip0(name)
|
||||
host = strip0(host)
|
||||
print "%r %r %r %s %s" % (name, host, line, time, idle)
|
||||
|
||||
def testbcast():
|
||||
c = BroadcastRnusersClient('<broadcast>')
|
||||
def listit(list, fromaddr):
|
||||
host, port = fromaddr
|
||||
print host + '\t:',
|
||||
for (line, name, host, time), idle in list:
|
||||
print strip0(name),
|
||||
print
|
||||
c.set_reply_handler(listit)
|
||||
all = c.Names()
|
||||
print 'Total Count:', len(all)
|
||||
|
||||
def strip0(s):
|
||||
while s and s[-1] == '\0': s = s[:-1]
|
||||
return s
|
||||
|
||||
test()
|
893
2.7/Python-2.7.16/Demo/rpc/rpc.py
Normal file
893
2.7/Python-2.7.16/Demo/rpc/rpc.py
Normal file
@ -0,0 +1,893 @@
|
||||
# Sun RPC version 2 -- RFC1057.
|
||||
|
||||
# XXX There should be separate exceptions for the various reasons why
|
||||
# XXX an RPC can fail, rather than using RuntimeError for everything
|
||||
|
||||
# XXX Need to use class based exceptions rather than string exceptions
|
||||
|
||||
# XXX The UDP version of the protocol resends requests when it does
|
||||
# XXX not receive a timely reply -- use only for idempotent calls!
|
||||
|
||||
# XXX There is no provision for call timeout on TCP connections
|
||||
|
||||
import xdr
|
||||
import socket
|
||||
import os
|
||||
|
||||
RPCVERSION = 2
|
||||
|
||||
CALL = 0
|
||||
REPLY = 1
|
||||
|
||||
AUTH_NULL = 0
|
||||
AUTH_UNIX = 1
|
||||
AUTH_SHORT = 2
|
||||
AUTH_DES = 3
|
||||
|
||||
MSG_ACCEPTED = 0
|
||||
MSG_DENIED = 1
|
||||
|
||||
SUCCESS = 0 # RPC executed successfully
|
||||
PROG_UNAVAIL = 1 # remote hasn't exported program
|
||||
PROG_MISMATCH = 2 # remote can't support version #
|
||||
PROC_UNAVAIL = 3 # program can't support procedure
|
||||
GARBAGE_ARGS = 4 # procedure can't decode params
|
||||
|
||||
RPC_MISMATCH = 0 # RPC version number != 2
|
||||
AUTH_ERROR = 1 # remote can't authenticate caller
|
||||
|
||||
AUTH_BADCRED = 1 # bad credentials (seal broken)
|
||||
AUTH_REJECTEDCRED = 2 # client must begin new session
|
||||
AUTH_BADVERF = 3 # bad verifier (seal broken)
|
||||
AUTH_REJECTEDVERF = 4 # verifier expired or replayed
|
||||
AUTH_TOOWEAK = 5 # rejected for security reasons
|
||||
|
||||
|
||||
class Packer(xdr.Packer):
|
||||
|
||||
def pack_auth(self, auth):
|
||||
flavor, stuff = auth
|
||||
self.pack_enum(flavor)
|
||||
self.pack_opaque(stuff)
|
||||
|
||||
def pack_auth_unix(self, stamp, machinename, uid, gid, gids):
|
||||
self.pack_uint(stamp)
|
||||
self.pack_string(machinename)
|
||||
self.pack_uint(uid)
|
||||
self.pack_uint(gid)
|
||||
self.pack_uint(len(gids))
|
||||
for i in gids:
|
||||
self.pack_uint(i)
|
||||
|
||||
def pack_callheader(self, xid, prog, vers, proc, cred, verf):
|
||||
self.pack_uint(xid)
|
||||
self.pack_enum(CALL)
|
||||
self.pack_uint(RPCVERSION)
|
||||
self.pack_uint(prog)
|
||||
self.pack_uint(vers)
|
||||
self.pack_uint(proc)
|
||||
self.pack_auth(cred)
|
||||
self.pack_auth(verf)
|
||||
# Caller must add procedure-specific part of call
|
||||
|
||||
def pack_replyheader(self, xid, verf):
|
||||
self.pack_uint(xid)
|
||||
self.pack_enum(REPLY)
|
||||
self.pack_uint(MSG_ACCEPTED)
|
||||
self.pack_auth(verf)
|
||||
self.pack_enum(SUCCESS)
|
||||
# Caller must add procedure-specific part of reply
|
||||
|
||||
|
||||
# Exceptions
|
||||
class BadRPCFormat(Exception): pass
|
||||
class BadRPCVersion(Exception): pass
|
||||
class GarbageArgs(Exception): pass
|
||||
|
||||
class Unpacker(xdr.Unpacker):
|
||||
|
||||
def unpack_auth(self):
|
||||
flavor = self.unpack_enum()
|
||||
stuff = self.unpack_opaque()
|
||||
return (flavor, stuff)
|
||||
|
||||
def unpack_callheader(self):
|
||||
xid = self.unpack_uint()
|
||||
temp = self.unpack_enum()
|
||||
if temp != CALL:
|
||||
raise BadRPCFormat, 'no CALL but %r' % (temp,)
|
||||
temp = self.unpack_uint()
|
||||
if temp != RPCVERSION:
|
||||
raise BadRPCVersion, 'bad RPC version %r' % (temp,)
|
||||
prog = self.unpack_uint()
|
||||
vers = self.unpack_uint()
|
||||
proc = self.unpack_uint()
|
||||
cred = self.unpack_auth()
|
||||
verf = self.unpack_auth()
|
||||
return xid, prog, vers, proc, cred, verf
|
||||
# Caller must add procedure-specific part of call
|
||||
|
||||
def unpack_replyheader(self):
|
||||
xid = self.unpack_uint()
|
||||
mtype = self.unpack_enum()
|
||||
if mtype != REPLY:
|
||||
raise RuntimeError, 'no REPLY but %r' % (mtype,)
|
||||
stat = self.unpack_enum()
|
||||
if stat == MSG_DENIED:
|
||||
stat = self.unpack_enum()
|
||||
if stat == RPC_MISMATCH:
|
||||
low = self.unpack_uint()
|
||||
high = self.unpack_uint()
|
||||
raise RuntimeError, \
|
||||
'MSG_DENIED: RPC_MISMATCH: %r' % ((low, high),)
|
||||
if stat == AUTH_ERROR:
|
||||
stat = self.unpack_uint()
|
||||
raise RuntimeError, \
|
||||
'MSG_DENIED: AUTH_ERROR: %r' % (stat,)
|
||||
raise RuntimeError, 'MSG_DENIED: %r' % (stat,)
|
||||
if stat != MSG_ACCEPTED:
|
||||
raise RuntimeError, \
|
||||
'Neither MSG_DENIED nor MSG_ACCEPTED: %r' % (stat,)
|
||||
verf = self.unpack_auth()
|
||||
stat = self.unpack_enum()
|
||||
if stat == PROG_UNAVAIL:
|
||||
raise RuntimeError, 'call failed: PROG_UNAVAIL'
|
||||
if stat == PROG_MISMATCH:
|
||||
low = self.unpack_uint()
|
||||
high = self.unpack_uint()
|
||||
raise RuntimeError, \
|
||||
'call failed: PROG_MISMATCH: %r' % ((low, high),)
|
||||
if stat == PROC_UNAVAIL:
|
||||
raise RuntimeError, 'call failed: PROC_UNAVAIL'
|
||||
if stat == GARBAGE_ARGS:
|
||||
raise RuntimeError, 'call failed: GARBAGE_ARGS'
|
||||
if stat != SUCCESS:
|
||||
raise RuntimeError, 'call failed: %r' % (stat,)
|
||||
return xid, verf
|
||||
# Caller must get procedure-specific part of reply
|
||||
|
||||
|
||||
# Subroutines to create opaque authentication objects
|
||||
|
||||
def make_auth_null():
|
||||
return ''
|
||||
|
||||
def make_auth_unix(seed, host, uid, gid, groups):
|
||||
p = Packer()
|
||||
p.pack_auth_unix(seed, host, uid, gid, groups)
|
||||
return p.get_buf()
|
||||
|
||||
def make_auth_unix_default():
|
||||
try:
|
||||
from os import getuid, getgid
|
||||
uid = getuid()
|
||||
gid = getgid()
|
||||
except ImportError:
|
||||
uid = gid = 0
|
||||
import time
|
||||
return make_auth_unix(int(time.time()-unix_epoch()), \
|
||||
socket.gethostname(), uid, gid, [])
|
||||
|
||||
_unix_epoch = -1
|
||||
def unix_epoch():
|
||||
"""Very painful calculation of when the Unix Epoch is.
|
||||
|
||||
This is defined as the return value of time.time() on Jan 1st,
|
||||
1970, 00:00:00 GMT.
|
||||
|
||||
On a Unix system, this should always return 0.0. On a Mac, the
|
||||
calculations are needed -- and hard because of integer overflow
|
||||
and other limitations.
|
||||
|
||||
"""
|
||||
global _unix_epoch
|
||||
if _unix_epoch >= 0: return _unix_epoch
|
||||
import time
|
||||
now = time.time()
|
||||
localt = time.localtime(now) # (y, m, d, hh, mm, ss, ..., ..., ...)
|
||||
gmt = time.gmtime(now)
|
||||
offset = time.mktime(localt) - time.mktime(gmt)
|
||||
y, m, d, hh, mm, ss = 1970, 1, 1, 0, 0, 0
|
||||
offset, ss = divmod(ss + offset, 60)
|
||||
offset, mm = divmod(mm + offset, 60)
|
||||
offset, hh = divmod(hh + offset, 24)
|
||||
d = d + offset
|
||||
_unix_epoch = time.mktime((y, m, d, hh, mm, ss, 0, 0, 0))
|
||||
print "Unix epoch:", time.ctime(_unix_epoch)
|
||||
return _unix_epoch
|
||||
|
||||
|
||||
# Common base class for clients
|
||||
|
||||
class Client:
|
||||
|
||||
def __init__(self, host, prog, vers, port):
|
||||
self.host = host
|
||||
self.prog = prog
|
||||
self.vers = vers
|
||||
self.port = port
|
||||
self.makesocket() # Assigns to self.sock
|
||||
self.bindsocket()
|
||||
self.connsocket()
|
||||
self.lastxid = 0 # XXX should be more random?
|
||||
self.addpackers()
|
||||
self.cred = None
|
||||
self.verf = None
|
||||
|
||||
def close(self):
|
||||
self.sock.close()
|
||||
|
||||
def makesocket(self):
|
||||
# This MUST be overridden
|
||||
raise RuntimeError, 'makesocket not defined'
|
||||
|
||||
def connsocket(self):
|
||||
# Override this if you don't want/need a connection
|
||||
self.sock.connect((self.host, self.port))
|
||||
|
||||
def bindsocket(self):
|
||||
# Override this to bind to a different port (e.g. reserved)
|
||||
self.sock.bind(('', 0))
|
||||
|
||||
def addpackers(self):
|
||||
# Override this to use derived classes from Packer/Unpacker
|
||||
self.packer = Packer()
|
||||
self.unpacker = Unpacker('')
|
||||
|
||||
def make_call(self, proc, args, pack_func, unpack_func):
|
||||
# Don't normally override this (but see Broadcast)
|
||||
if pack_func is None and args is not None:
|
||||
raise TypeError, 'non-null args with null pack_func'
|
||||
self.start_call(proc)
|
||||
if pack_func:
|
||||
pack_func(args)
|
||||
self.do_call()
|
||||
if unpack_func:
|
||||
result = unpack_func()
|
||||
else:
|
||||
result = None
|
||||
self.unpacker.done()
|
||||
return result
|
||||
|
||||
def start_call(self, proc):
|
||||
# Don't override this
|
||||
self.lastxid = xid = self.lastxid + 1
|
||||
cred = self.mkcred()
|
||||
verf = self.mkverf()
|
||||
p = self.packer
|
||||
p.reset()
|
||||
p.pack_callheader(xid, self.prog, self.vers, proc, cred, verf)
|
||||
|
||||
def do_call(self):
|
||||
# This MUST be overridden
|
||||
raise RuntimeError, 'do_call not defined'
|
||||
|
||||
def mkcred(self):
|
||||
# Override this to use more powerful credentials
|
||||
if self.cred is None:
|
||||
self.cred = (AUTH_NULL, make_auth_null())
|
||||
return self.cred
|
||||
|
||||
def mkverf(self):
|
||||
# Override this to use a more powerful verifier
|
||||
if self.verf is None:
|
||||
self.verf = (AUTH_NULL, make_auth_null())
|
||||
return self.verf
|
||||
|
||||
def call_0(self): # Procedure 0 is always like this
|
||||
return self.make_call(0, None, None, None)
|
||||
|
||||
|
||||
# Record-Marking standard support
|
||||
|
||||
def sendfrag(sock, last, frag):
|
||||
x = len(frag)
|
||||
if last: x = x | 0x80000000L
|
||||
header = (chr(int(x>>24 & 0xff)) + chr(int(x>>16 & 0xff)) + \
|
||||
chr(int(x>>8 & 0xff)) + chr(int(x & 0xff)))
|
||||
sock.send(header + frag)
|
||||
|
||||
def sendrecord(sock, record):
|
||||
sendfrag(sock, 1, record)
|
||||
|
||||
def recvfrag(sock):
|
||||
header = sock.recv(4)
|
||||
if len(header) < 4:
|
||||
raise EOFError
|
||||
x = long(ord(header[0]))<<24 | ord(header[1])<<16 | \
|
||||
ord(header[2])<<8 | ord(header[3])
|
||||
last = ((x & 0x80000000) != 0)
|
||||
n = int(x & 0x7fffffff)
|
||||
frag = ''
|
||||
while n > 0:
|
||||
buf = sock.recv(n)
|
||||
if not buf: raise EOFError
|
||||
n = n - len(buf)
|
||||
frag = frag + buf
|
||||
return last, frag
|
||||
|
||||
def recvrecord(sock):
|
||||
record = ''
|
||||
last = 0
|
||||
while not last:
|
||||
last, frag = recvfrag(sock)
|
||||
record = record + frag
|
||||
return record
|
||||
|
||||
|
||||
# Try to bind to a reserved port (must be root)
|
||||
|
||||
last_resv_port_tried = None
|
||||
def bindresvport(sock, host):
|
||||
global last_resv_port_tried
|
||||
FIRST, LAST = 600, 1024 # Range of ports to try
|
||||
if last_resv_port_tried is None:
|
||||
import os
|
||||
last_resv_port_tried = FIRST + os.getpid() % (LAST-FIRST)
|
||||
for i in range(last_resv_port_tried, LAST) + \
|
||||
range(FIRST, last_resv_port_tried):
|
||||
last_resv_port_tried = i
|
||||
try:
|
||||
sock.bind((host, i))
|
||||
return last_resv_port_tried
|
||||
except socket.error, (errno, msg):
|
||||
if errno != 114:
|
||||
raise socket.error, (errno, msg)
|
||||
raise RuntimeError, 'can\'t assign reserved port'
|
||||
|
||||
|
||||
# Client using TCP to a specific port
|
||||
|
||||
class RawTCPClient(Client):
|
||||
|
||||
def makesocket(self):
|
||||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
|
||||
def do_call(self):
|
||||
call = self.packer.get_buf()
|
||||
sendrecord(self.sock, call)
|
||||
reply = recvrecord(self.sock)
|
||||
u = self.unpacker
|
||||
u.reset(reply)
|
||||
xid, verf = u.unpack_replyheader()
|
||||
if xid != self.lastxid:
|
||||
# Can't really happen since this is TCP...
|
||||
raise RuntimeError, 'wrong xid in reply %r instead of %r' % (
|
||||
xid, self.lastxid)
|
||||
|
||||
|
||||
# Client using UDP to a specific port
|
||||
|
||||
class RawUDPClient(Client):
|
||||
|
||||
def makesocket(self):
|
||||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
|
||||
def do_call(self):
|
||||
call = self.packer.get_buf()
|
||||
self.sock.send(call)
|
||||
try:
|
||||
from select import select
|
||||
except ImportError:
|
||||
print 'WARNING: select not found, RPC may hang'
|
||||
select = None
|
||||
BUFSIZE = 8192 # Max UDP buffer size
|
||||
timeout = 1
|
||||
count = 5
|
||||
while 1:
|
||||
r, w, x = [self.sock], [], []
|
||||
if select:
|
||||
r, w, x = select(r, w, x, timeout)
|
||||
if self.sock not in r:
|
||||
count = count - 1
|
||||
if count < 0: raise RuntimeError, 'timeout'
|
||||
if timeout < 25: timeout = timeout *2
|
||||
## print 'RESEND', timeout, count
|
||||
self.sock.send(call)
|
||||
continue
|
||||
reply = self.sock.recv(BUFSIZE)
|
||||
u = self.unpacker
|
||||
u.reset(reply)
|
||||
xid, verf = u.unpack_replyheader()
|
||||
if xid != self.lastxid:
|
||||
## print 'BAD xid'
|
||||
continue
|
||||
break
|
||||
|
||||
|
||||
# Client using UDP broadcast to a specific port
|
||||
|
||||
class RawBroadcastUDPClient(RawUDPClient):
|
||||
|
||||
def __init__(self, bcastaddr, prog, vers, port):
|
||||
RawUDPClient.__init__(self, bcastaddr, prog, vers, port)
|
||||
self.reply_handler = None
|
||||
self.timeout = 30
|
||||
|
||||
def connsocket(self):
|
||||
# Don't connect -- use sendto
|
||||
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
||||
|
||||
def set_reply_handler(self, reply_handler):
|
||||
self.reply_handler = reply_handler
|
||||
|
||||
def set_timeout(self, timeout):
|
||||
self.timeout = timeout # Use None for infinite timeout
|
||||
|
||||
def make_call(self, proc, args, pack_func, unpack_func):
|
||||
if pack_func is None and args is not None:
|
||||
raise TypeError, 'non-null args with null pack_func'
|
||||
self.start_call(proc)
|
||||
if pack_func:
|
||||
pack_func(args)
|
||||
call = self.packer.get_buf()
|
||||
self.sock.sendto(call, (self.host, self.port))
|
||||
try:
|
||||
from select import select
|
||||
except ImportError:
|
||||
print 'WARNING: select not found, broadcast will hang'
|
||||
select = None
|
||||
BUFSIZE = 8192 # Max UDP buffer size (for reply)
|
||||
replies = []
|
||||
if unpack_func is None:
|
||||
def dummy(): pass
|
||||
unpack_func = dummy
|
||||
while 1:
|
||||
r, w, x = [self.sock], [], []
|
||||
if select:
|
||||
if self.timeout is None:
|
||||
r, w, x = select(r, w, x)
|
||||
else:
|
||||
r, w, x = select(r, w, x, self.timeout)
|
||||
if self.sock not in r:
|
||||
break
|
||||
reply, fromaddr = self.sock.recvfrom(BUFSIZE)
|
||||
u = self.unpacker
|
||||
u.reset(reply)
|
||||
xid, verf = u.unpack_replyheader()
|
||||
if xid != self.lastxid:
|
||||
## print 'BAD xid'
|
||||
continue
|
||||
reply = unpack_func()
|
||||
self.unpacker.done()
|
||||
replies.append((reply, fromaddr))
|
||||
if self.reply_handler:
|
||||
self.reply_handler(reply, fromaddr)
|
||||
return replies
|
||||
|
||||
|
||||
# Port mapper interface
|
||||
|
||||
# Program number, version and (fixed!) port number
|
||||
PMAP_PROG = 100000
|
||||
PMAP_VERS = 2
|
||||
PMAP_PORT = 111
|
||||
|
||||
# Procedure numbers
|
||||
PMAPPROC_NULL = 0 # (void) -> void
|
||||
PMAPPROC_SET = 1 # (mapping) -> bool
|
||||
PMAPPROC_UNSET = 2 # (mapping) -> bool
|
||||
PMAPPROC_GETPORT = 3 # (mapping) -> unsigned int
|
||||
PMAPPROC_DUMP = 4 # (void) -> pmaplist
|
||||
PMAPPROC_CALLIT = 5 # (call_args) -> call_result
|
||||
|
||||
# A mapping is (prog, vers, prot, port) and prot is one of:
|
||||
|
||||
IPPROTO_TCP = 6
|
||||
IPPROTO_UDP = 17
|
||||
|
||||
# A pmaplist is a variable-length list of mappings, as follows:
|
||||
# either (1, mapping, pmaplist) or (0).
|
||||
|
||||
# A call_args is (prog, vers, proc, args) where args is opaque;
|
||||
# a call_result is (port, res) where res is opaque.
|
||||
|
||||
|
||||
class PortMapperPacker(Packer):
|
||||
|
||||
def pack_mapping(self, mapping):
|
||||
prog, vers, prot, port = mapping
|
||||
self.pack_uint(prog)
|
||||
self.pack_uint(vers)
|
||||
self.pack_uint(prot)
|
||||
self.pack_uint(port)
|
||||
|
||||
def pack_pmaplist(self, list):
|
||||
self.pack_list(list, self.pack_mapping)
|
||||
|
||||
def pack_call_args(self, ca):
|
||||
prog, vers, proc, args = ca
|
||||
self.pack_uint(prog)
|
||||
self.pack_uint(vers)
|
||||
self.pack_uint(proc)
|
||||
self.pack_opaque(args)
|
||||
|
||||
|
||||
class PortMapperUnpacker(Unpacker):
|
||||
|
||||
def unpack_mapping(self):
|
||||
prog = self.unpack_uint()
|
||||
vers = self.unpack_uint()
|
||||
prot = self.unpack_uint()
|
||||
port = self.unpack_uint()
|
||||
return prog, vers, prot, port
|
||||
|
||||
def unpack_pmaplist(self):
|
||||
return self.unpack_list(self.unpack_mapping)
|
||||
|
||||
def unpack_call_result(self):
|
||||
port = self.unpack_uint()
|
||||
res = self.unpack_opaque()
|
||||
return port, res
|
||||
|
||||
|
||||
class PartialPortMapperClient:
|
||||
|
||||
def addpackers(self):
|
||||
self.packer = PortMapperPacker()
|
||||
self.unpacker = PortMapperUnpacker('')
|
||||
|
||||
def Set(self, mapping):
|
||||
return self.make_call(PMAPPROC_SET, mapping, \
|
||||
self.packer.pack_mapping, \
|
||||
self.unpacker.unpack_uint)
|
||||
|
||||
def Unset(self, mapping):
|
||||
return self.make_call(PMAPPROC_UNSET, mapping, \
|
||||
self.packer.pack_mapping, \
|
||||
self.unpacker.unpack_uint)
|
||||
|
||||
def Getport(self, mapping):
|
||||
return self.make_call(PMAPPROC_GETPORT, mapping, \
|
||||
self.packer.pack_mapping, \
|
||||
self.unpacker.unpack_uint)
|
||||
|
||||
def Dump(self):
|
||||
return self.make_call(PMAPPROC_DUMP, None, \
|
||||
None, \
|
||||
self.unpacker.unpack_pmaplist)
|
||||
|
||||
def Callit(self, ca):
|
||||
return self.make_call(PMAPPROC_CALLIT, ca, \
|
||||
self.packer.pack_call_args, \
|
||||
self.unpacker.unpack_call_result)
|
||||
|
||||
|
||||
class TCPPortMapperClient(PartialPortMapperClient, RawTCPClient):
|
||||
|
||||
def __init__(self, host):
|
||||
RawTCPClient.__init__(self, \
|
||||
host, PMAP_PROG, PMAP_VERS, PMAP_PORT)
|
||||
|
||||
|
||||
class UDPPortMapperClient(PartialPortMapperClient, RawUDPClient):
|
||||
|
||||
def __init__(self, host):
|
||||
RawUDPClient.__init__(self, \
|
||||
host, PMAP_PROG, PMAP_VERS, PMAP_PORT)
|
||||
|
||||
|
||||
class BroadcastUDPPortMapperClient(PartialPortMapperClient, \
|
||||
RawBroadcastUDPClient):
|
||||
|
||||
def __init__(self, bcastaddr):
|
||||
RawBroadcastUDPClient.__init__(self, \
|
||||
bcastaddr, PMAP_PROG, PMAP_VERS, PMAP_PORT)
|
||||
|
||||
|
||||
# Generic clients that find their server through the Port mapper
|
||||
|
||||
class TCPClient(RawTCPClient):
|
||||
|
||||
def __init__(self, host, prog, vers):
|
||||
pmap = TCPPortMapperClient(host)
|
||||
port = pmap.Getport((prog, vers, IPPROTO_TCP, 0))
|
||||
pmap.close()
|
||||
if port == 0:
|
||||
raise RuntimeError, 'program not registered'
|
||||
RawTCPClient.__init__(self, host, prog, vers, port)
|
||||
|
||||
|
||||
class UDPClient(RawUDPClient):
|
||||
|
||||
def __init__(self, host, prog, vers):
|
||||
pmap = UDPPortMapperClient(host)
|
||||
port = pmap.Getport((prog, vers, IPPROTO_UDP, 0))
|
||||
pmap.close()
|
||||
if port == 0:
|
||||
raise RuntimeError, 'program not registered'
|
||||
RawUDPClient.__init__(self, host, prog, vers, port)
|
||||
|
||||
|
||||
class BroadcastUDPClient(Client):
|
||||
|
||||
def __init__(self, bcastaddr, prog, vers):
|
||||
self.pmap = BroadcastUDPPortMapperClient(bcastaddr)
|
||||
self.pmap.set_reply_handler(self.my_reply_handler)
|
||||
self.prog = prog
|
||||
self.vers = vers
|
||||
self.user_reply_handler = None
|
||||
self.addpackers()
|
||||
|
||||
def close(self):
|
||||
self.pmap.close()
|
||||
|
||||
def set_reply_handler(self, reply_handler):
|
||||
self.user_reply_handler = reply_handler
|
||||
|
||||
def set_timeout(self, timeout):
|
||||
self.pmap.set_timeout(timeout)
|
||||
|
||||
def my_reply_handler(self, reply, fromaddr):
|
||||
port, res = reply
|
||||
self.unpacker.reset(res)
|
||||
result = self.unpack_func()
|
||||
self.unpacker.done()
|
||||
self.replies.append((result, fromaddr))
|
||||
if self.user_reply_handler is not None:
|
||||
self.user_reply_handler(result, fromaddr)
|
||||
|
||||
def make_call(self, proc, args, pack_func, unpack_func):
|
||||
self.packer.reset()
|
||||
if pack_func:
|
||||
pack_func(args)
|
||||
if unpack_func is None:
|
||||
def dummy(): pass
|
||||
self.unpack_func = dummy
|
||||
else:
|
||||
self.unpack_func = unpack_func
|
||||
self.replies = []
|
||||
packed_args = self.packer.get_buf()
|
||||
dummy_replies = self.pmap.Callit( \
|
||||
(self.prog, self.vers, proc, packed_args))
|
||||
return self.replies
|
||||
|
||||
|
||||
# Server classes
|
||||
|
||||
# These are not symmetric to the Client classes
|
||||
# XXX No attempt is made to provide authorization hooks yet
|
||||
|
||||
class Server:
|
||||
|
||||
def __init__(self, host, prog, vers, port):
|
||||
self.host = host # Should normally be '' for default interface
|
||||
self.prog = prog
|
||||
self.vers = vers
|
||||
self.port = port # Should normally be 0 for random port
|
||||
self.makesocket() # Assigns to self.sock and self.prot
|
||||
self.bindsocket()
|
||||
self.host, self.port = self.sock.getsockname()
|
||||
self.addpackers()
|
||||
|
||||
def register(self):
|
||||
mapping = self.prog, self.vers, self.prot, self.port
|
||||
p = TCPPortMapperClient(self.host)
|
||||
if not p.Set(mapping):
|
||||
raise RuntimeError, 'register failed'
|
||||
|
||||
def unregister(self):
|
||||
mapping = self.prog, self.vers, self.prot, self.port
|
||||
p = TCPPortMapperClient(self.host)
|
||||
if not p.Unset(mapping):
|
||||
raise RuntimeError, 'unregister failed'
|
||||
|
||||
def handle(self, call):
|
||||
# Don't use unpack_header but parse the header piecewise
|
||||
# XXX I have no idea if I am using the right error responses!
|
||||
self.unpacker.reset(call)
|
||||
self.packer.reset()
|
||||
xid = self.unpacker.unpack_uint()
|
||||
self.packer.pack_uint(xid)
|
||||
temp = self.unpacker.unpack_enum()
|
||||
if temp != CALL:
|
||||
return None # Not worthy of a reply
|
||||
self.packer.pack_uint(REPLY)
|
||||
temp = self.unpacker.unpack_uint()
|
||||
if temp != RPCVERSION:
|
||||
self.packer.pack_uint(MSG_DENIED)
|
||||
self.packer.pack_uint(RPC_MISMATCH)
|
||||
self.packer.pack_uint(RPCVERSION)
|
||||
self.packer.pack_uint(RPCVERSION)
|
||||
return self.packer.get_buf()
|
||||
self.packer.pack_uint(MSG_ACCEPTED)
|
||||
self.packer.pack_auth((AUTH_NULL, make_auth_null()))
|
||||
prog = self.unpacker.unpack_uint()
|
||||
if prog != self.prog:
|
||||
self.packer.pack_uint(PROG_UNAVAIL)
|
||||
return self.packer.get_buf()
|
||||
vers = self.unpacker.unpack_uint()
|
||||
if vers != self.vers:
|
||||
self.packer.pack_uint(PROG_MISMATCH)
|
||||
self.packer.pack_uint(self.vers)
|
||||
self.packer.pack_uint(self.vers)
|
||||
return self.packer.get_buf()
|
||||
proc = self.unpacker.unpack_uint()
|
||||
methname = 'handle_' + repr(proc)
|
||||
try:
|
||||
meth = getattr(self, methname)
|
||||
except AttributeError:
|
||||
self.packer.pack_uint(PROC_UNAVAIL)
|
||||
return self.packer.get_buf()
|
||||
cred = self.unpacker.unpack_auth()
|
||||
verf = self.unpacker.unpack_auth()
|
||||
try:
|
||||
meth() # Unpack args, call turn_around(), pack reply
|
||||
except (EOFError, GarbageArgs):
|
||||
# Too few or too many arguments
|
||||
self.packer.reset()
|
||||
self.packer.pack_uint(xid)
|
||||
self.packer.pack_uint(REPLY)
|
||||
self.packer.pack_uint(MSG_ACCEPTED)
|
||||
self.packer.pack_auth((AUTH_NULL, make_auth_null()))
|
||||
self.packer.pack_uint(GARBAGE_ARGS)
|
||||
return self.packer.get_buf()
|
||||
|
||||
def turn_around(self):
|
||||
try:
|
||||
self.unpacker.done()
|
||||
except RuntimeError:
|
||||
raise GarbageArgs
|
||||
self.packer.pack_uint(SUCCESS)
|
||||
|
||||
def handle_0(self): # Handle NULL message
|
||||
self.turn_around()
|
||||
|
||||
def makesocket(self):
|
||||
# This MUST be overridden
|
||||
raise RuntimeError, 'makesocket not defined'
|
||||
|
||||
def bindsocket(self):
|
||||
# Override this to bind to a different port (e.g. reserved)
|
||||
self.sock.bind((self.host, self.port))
|
||||
|
||||
def addpackers(self):
|
||||
# Override this to use derived classes from Packer/Unpacker
|
||||
self.packer = Packer()
|
||||
self.unpacker = Unpacker('')
|
||||
|
||||
|
||||
class TCPServer(Server):
|
||||
|
||||
def makesocket(self):
|
||||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.prot = IPPROTO_TCP
|
||||
|
||||
def loop(self):
|
||||
self.sock.listen(0)
|
||||
while 1:
|
||||
self.session(self.sock.accept())
|
||||
|
||||
def session(self, connection):
|
||||
sock, (host, port) = connection
|
||||
while 1:
|
||||
try:
|
||||
call = recvrecord(sock)
|
||||
except EOFError:
|
||||
break
|
||||
except socket.error, msg:
|
||||
print 'socket error:', msg
|
||||
break
|
||||
reply = self.handle(call)
|
||||
if reply is not None:
|
||||
sendrecord(sock, reply)
|
||||
|
||||
def forkingloop(self):
|
||||
# Like loop but uses forksession()
|
||||
self.sock.listen(0)
|
||||
while 1:
|
||||
self.forksession(self.sock.accept())
|
||||
|
||||
def forksession(self, connection):
|
||||
# Like session but forks off a subprocess
|
||||
import os
|
||||
# Wait for deceased children
|
||||
try:
|
||||
while 1:
|
||||
pid, sts = os.waitpid(0, 1)
|
||||
except os.error:
|
||||
pass
|
||||
pid = None
|
||||
try:
|
||||
pid = os.fork()
|
||||
if pid: # Parent
|
||||
connection[0].close()
|
||||
return
|
||||
# Child
|
||||
self.session(connection)
|
||||
finally:
|
||||
# Make sure we don't fall through in the parent
|
||||
if pid == 0:
|
||||
os._exit(0)
|
||||
|
||||
|
||||
class UDPServer(Server):
|
||||
|
||||
def makesocket(self):
|
||||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
self.prot = IPPROTO_UDP
|
||||
|
||||
def loop(self):
|
||||
while 1:
|
||||
self.session()
|
||||
|
||||
def session(self):
|
||||
call, host_port = self.sock.recvfrom(8192)
|
||||
reply = self.handle(call)
|
||||
if reply is not None:
|
||||
self.sock.sendto(reply, host_port)
|
||||
|
||||
|
||||
# Simple test program -- dump local portmapper status
|
||||
|
||||
def test():
|
||||
pmap = UDPPortMapperClient('')
|
||||
list = pmap.Dump()
|
||||
list.sort()
|
||||
for prog, vers, prot, port in list:
|
||||
print prog, vers,
|
||||
if prot == IPPROTO_TCP: print 'tcp',
|
||||
elif prot == IPPROTO_UDP: print 'udp',
|
||||
else: print prot,
|
||||
print port
|
||||
|
||||
|
||||
# Test program for broadcast operation -- dump everybody's portmapper status
|
||||
|
||||
def testbcast():
|
||||
import sys
|
||||
if sys.argv[1:]:
|
||||
bcastaddr = sys.argv[1]
|
||||
else:
|
||||
bcastaddr = '<broadcast>'
|
||||
def rh(reply, fromaddr):
|
||||
host, port = fromaddr
|
||||
print host + '\t' + repr(reply)
|
||||
pmap = BroadcastUDPPortMapperClient(bcastaddr)
|
||||
pmap.set_reply_handler(rh)
|
||||
pmap.set_timeout(5)
|
||||
replies = pmap.Getport((100002, 1, IPPROTO_UDP, 0))
|
||||
|
||||
|
||||
# Test program for server, with corresponding client
|
||||
# On machine A: python -c 'import rpc; rpc.testsvr()'
|
||||
# On machine B: python -c 'import rpc; rpc.testclt()' A
|
||||
# (A may be == B)
|
||||
|
||||
def testsvr():
|
||||
# Simple test class -- proc 1 doubles its string argument as reply
|
||||
class S(UDPServer):
|
||||
def handle_1(self):
|
||||
arg = self.unpacker.unpack_string()
|
||||
self.turn_around()
|
||||
print 'RPC function 1 called, arg', repr(arg)
|
||||
self.packer.pack_string(arg + arg)
|
||||
#
|
||||
s = S('', 0x20000000, 1, 0)
|
||||
try:
|
||||
s.unregister()
|
||||
except RuntimeError, msg:
|
||||
print 'RuntimeError:', msg, '(ignored)'
|
||||
s.register()
|
||||
print 'Service started...'
|
||||
try:
|
||||
s.loop()
|
||||
finally:
|
||||
s.unregister()
|
||||
print 'Service interrupted.'
|
||||
|
||||
|
||||
def testclt():
|
||||
import sys
|
||||
if sys.argv[1:]: host = sys.argv[1]
|
||||
else: host = ''
|
||||
# Client for above server
|
||||
class C(UDPClient):
|
||||
def call_1(self, arg):
|
||||
return self.make_call(1, arg, \
|
||||
self.packer.pack_string, \
|
||||
self.unpacker.unpack_string)
|
||||
c = C(host, 0x20000000, 1)
|
||||
print 'making call...'
|
||||
reply = c.call_1('hello, world, ')
|
||||
print 'call returned', repr(reply)
|
24
2.7/Python-2.7.16/Demo/rpc/test
Normal file
24
2.7/Python-2.7.16/Demo/rpc/test
Normal file
@ -0,0 +1,24 @@
|
||||
: ${PYTHON=python}
|
||||
: ${SERVER=charon.cwi.nl}
|
||||
|
||||
set -xe
|
||||
|
||||
$PYTHON -c 'from rpc import test; test()'
|
||||
$PYTHON -c 'from rpc import test; test()' ${SERVER}
|
||||
|
||||
$PYTHON -c 'from rpc import testsvr; testsvr()' &
|
||||
PID=$!
|
||||
sleep 2
|
||||
$PYTHON -c 'from rpc import testclt; testclt()'
|
||||
kill -2 $PID
|
||||
|
||||
$PYTHON -c 'from mountclient import test; test()'
|
||||
$PYTHON -c 'from mountclient import test; test()' gatekeeper.dec.com
|
||||
|
||||
$PYTHON -c 'from nfsclient import test; test()'
|
||||
$PYTHON -c 'from nfsclient import test; test()' gatekeeper.dec.com
|
||||
$PYTHON -c 'from nfsclient import test; test()' gatekeeper.dec.com /archive
|
||||
|
||||
$PYTHON -c 'from rnusersclient import test; test()' ''
|
||||
|
||||
$PYTHON -c 'from rpc import testbcast; testbcast()'
|
200
2.7/Python-2.7.16/Demo/rpc/xdr.py
Normal file
200
2.7/Python-2.7.16/Demo/rpc/xdr.py
Normal file
@ -0,0 +1,200 @@
|
||||
# Implement (a subset of) Sun XDR -- RFC1014.
|
||||
|
||||
|
||||
try:
|
||||
import struct
|
||||
except ImportError:
|
||||
struct = None
|
||||
|
||||
|
||||
Long = type(0L)
|
||||
|
||||
|
||||
class Packer:
|
||||
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
|
||||
def reset(self):
|
||||
self.buf = ''
|
||||
|
||||
def get_buf(self):
|
||||
return self.buf
|
||||
|
||||
def pack_uint(self, x):
|
||||
self.buf = self.buf + \
|
||||
(chr(int(x>>24 & 0xff)) + chr(int(x>>16 & 0xff)) + \
|
||||
chr(int(x>>8 & 0xff)) + chr(int(x & 0xff)))
|
||||
if struct and struct.pack('l', 1) == '\0\0\0\1':
|
||||
def pack_uint(self, x):
|
||||
if type(x) == Long:
|
||||
x = int((x + 0x80000000L) % 0x100000000L \
|
||||
- 0x80000000L)
|
||||
self.buf = self.buf + struct.pack('l', x)
|
||||
|
||||
pack_int = pack_uint
|
||||
|
||||
pack_enum = pack_int
|
||||
|
||||
def pack_bool(self, x):
|
||||
if x: self.buf = self.buf + '\0\0\0\1'
|
||||
else: self.buf = self.buf + '\0\0\0\0'
|
||||
|
||||
def pack_uhyper(self, x):
|
||||
self.pack_uint(int(x>>32 & 0xffffffff))
|
||||
self.pack_uint(int(x & 0xffffffff))
|
||||
|
||||
pack_hyper = pack_uhyper
|
||||
|
||||
def pack_float(self, x):
|
||||
# XXX
|
||||
self.buf = self.buf + struct.pack('f', x)
|
||||
|
||||
def pack_double(self, x):
|
||||
# XXX
|
||||
self.buf = self.buf + struct.pack('d', x)
|
||||
|
||||
def pack_fstring(self, n, s):
|
||||
if n < 0:
|
||||
raise ValueError, 'fstring size must be nonnegative'
|
||||
n = ((n + 3)//4)*4
|
||||
data = s[:n]
|
||||
data = data + (n - len(data)) * '\0'
|
||||
self.buf = self.buf + data
|
||||
|
||||
pack_fopaque = pack_fstring
|
||||
|
||||
def pack_string(self, s):
|
||||
n = len(s)
|
||||
self.pack_uint(n)
|
||||
self.pack_fstring(n, s)
|
||||
|
||||
pack_opaque = pack_string
|
||||
|
||||
def pack_list(self, list, pack_item):
|
||||
for item in list:
|
||||
self.pack_uint(1)
|
||||
pack_item(item)
|
||||
self.pack_uint(0)
|
||||
|
||||
def pack_farray(self, n, list, pack_item):
|
||||
if len(list) <> n:
|
||||
raise ValueError, 'wrong array size'
|
||||
for item in list:
|
||||
pack_item(item)
|
||||
|
||||
def pack_array(self, list, pack_item):
|
||||
n = len(list)
|
||||
self.pack_uint(n)
|
||||
self.pack_farray(n, list, pack_item)
|
||||
|
||||
|
||||
class Unpacker:
|
||||
|
||||
def __init__(self, data):
|
||||
self.reset(data)
|
||||
|
||||
def reset(self, data):
|
||||
self.buf = data
|
||||
self.pos = 0
|
||||
|
||||
def done(self):
|
||||
if self.pos < len(self.buf):
|
||||
raise RuntimeError, 'unextracted data remains'
|
||||
|
||||
def unpack_uint(self):
|
||||
i = self.pos
|
||||
self.pos = j = i+4
|
||||
data = self.buf[i:j]
|
||||
if len(data) < 4:
|
||||
raise EOFError
|
||||
x = long(ord(data[0]))<<24 | ord(data[1])<<16 | \
|
||||
ord(data[2])<<8 | ord(data[3])
|
||||
# Return a Python long only if the value is not representable
|
||||
# as a nonnegative Python int
|
||||
if x < 0x80000000L: x = int(x)
|
||||
return x
|
||||
if struct and struct.unpack('l', '\0\0\0\1') == 1:
|
||||
def unpack_uint(self):
|
||||
i = self.pos
|
||||
self.pos = j = i+4
|
||||
data = self.buf[i:j]
|
||||
if len(data) < 4:
|
||||
raise EOFError
|
||||
return struct.unpack('l', data)
|
||||
|
||||
def unpack_int(self):
|
||||
x = self.unpack_uint()
|
||||
if x >= 0x80000000L: x = x - 0x100000000L
|
||||
return int(x)
|
||||
|
||||
unpack_enum = unpack_int
|
||||
|
||||
unpack_bool = unpack_int
|
||||
|
||||
def unpack_uhyper(self):
|
||||
hi = self.unpack_uint()
|
||||
lo = self.unpack_uint()
|
||||
return long(hi)<<32 | lo
|
||||
|
||||
def unpack_hyper(self):
|
||||
x = self.unpack_uhyper()
|
||||
if x >= 0x8000000000000000L: x = x - 0x10000000000000000L
|
||||
return x
|
||||
|
||||
def unpack_float(self):
|
||||
# XXX
|
||||
i = self.pos
|
||||
self.pos = j = i+4
|
||||
data = self.buf[i:j]
|
||||
if len(data) < 4:
|
||||
raise EOFError
|
||||
return struct.unpack('f', data)[0]
|
||||
|
||||
def unpack_double(self):
|
||||
# XXX
|
||||
i = self.pos
|
||||
self.pos = j = i+8
|
||||
data = self.buf[i:j]
|
||||
if len(data) < 8:
|
||||
raise EOFError
|
||||
return struct.unpack('d', data)[0]
|
||||
|
||||
def unpack_fstring(self, n):
|
||||
if n < 0:
|
||||
raise ValueError, 'fstring size must be nonnegative'
|
||||
i = self.pos
|
||||
j = i + (n+3)//4*4
|
||||
if j > len(self.buf):
|
||||
raise EOFError
|
||||
self.pos = j
|
||||
return self.buf[i:i+n]
|
||||
|
||||
unpack_fopaque = unpack_fstring
|
||||
|
||||
def unpack_string(self):
|
||||
n = self.unpack_uint()
|
||||
return self.unpack_fstring(n)
|
||||
|
||||
unpack_opaque = unpack_string
|
||||
|
||||
def unpack_list(self, unpack_item):
|
||||
list = []
|
||||
while 1:
|
||||
x = self.unpack_uint()
|
||||
if x == 0: break
|
||||
if x <> 1:
|
||||
raise RuntimeError, '0 or 1 expected, got %r' % (x, )
|
||||
item = unpack_item()
|
||||
list.append(item)
|
||||
return list
|
||||
|
||||
def unpack_farray(self, n, unpack_item):
|
||||
list = []
|
||||
for i in range(n):
|
||||
list.append(unpack_item())
|
||||
return list
|
||||
|
||||
def unpack_array(self, unpack_item):
|
||||
n = self.unpack_uint()
|
||||
return self.unpack_farray(n, unpack_item)
|
22
2.7/Python-2.7.16/Demo/scripts/README
Normal file
22
2.7/Python-2.7.16/Demo/scripts/README
Normal file
@ -0,0 +1,22 @@
|
||||
This directory contains a collection of executable Python scripts.
|
||||
|
||||
See also the Tools/scripts directory!
|
||||
|
||||
beer.py Print the classic 'bottles of beer' list
|
||||
eqfix.py Fix .py files to use the correct equality test operator
|
||||
fact.py Factorize numbers
|
||||
find-uname.py Search for Unicode characters using regexps
|
||||
from.py Summarize mailbox
|
||||
lpwatch.py Watch BSD line printer queues
|
||||
makedir.py Like mkdir -p
|
||||
markov.py Markov chain simulation of words or characters
|
||||
mboxconvert.py Convert MH or MMDF mailboxes to unix mailbox format
|
||||
morse.py Produce morse code (audible or on AIFF file)
|
||||
newslist.py List all newsgroups on a NNTP server as HTML pages
|
||||
pi.py Print all digits of pi -- given enough time and memory
|
||||
pp.py Emulate some Perl command line options
|
||||
primes.py Print prime numbers
|
||||
queens.py Dijkstra's solution to Wirth's "N Queens problem"
|
||||
script.py Equivalent to BSD script(1) -- by Steen Lumholt
|
||||
unbirthday.py Print unbirthday count
|
||||
update.py Update a bunch of files according to a script.
|
20
2.7/Python-2.7.16/Demo/scripts/beer.py
Normal file
20
2.7/Python-2.7.16/Demo/scripts/beer.py
Normal file
@ -0,0 +1,20 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# By GvR, demystified after a version by Fredrik Lundh.
|
||||
|
||||
import sys
|
||||
|
||||
n = 100
|
||||
if sys.argv[1:]:
|
||||
n = int(sys.argv[1])
|
||||
|
||||
def bottle(n):
|
||||
if n == 0: return "no more bottles of beer"
|
||||
if n == 1: return "one bottle of beer"
|
||||
return str(n) + " bottles of beer"
|
||||
|
||||
for i in range(n, 0, -1):
|
||||
print bottle(i), "on the wall,"
|
||||
print bottle(i) + "."
|
||||
print "Take one down, pass it around,"
|
||||
print bottle(i-1), "on the wall."
|
198
2.7/Python-2.7.16/Demo/scripts/eqfix.py
Normal file
198
2.7/Python-2.7.16/Demo/scripts/eqfix.py
Normal file
@ -0,0 +1,198 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# Fix Python source files to use the new equality test operator, i.e.,
|
||||
# if x = y: ...
|
||||
# is changed to
|
||||
# if x == y: ...
|
||||
# The script correctly tokenizes the Python program to reliably
|
||||
# distinguish between assignments and equality tests.
|
||||
#
|
||||
# Command line arguments are files or directories to be processed.
|
||||
# Directories are searched recursively for files whose name looks
|
||||
# like a python module.
|
||||
# Symbolic links are always ignored (except as explicit directory
|
||||
# arguments). Of course, the original file is kept as a back-up
|
||||
# (with a "~" attached to its name).
|
||||
# It complains about binaries (files containing null bytes)
|
||||
# and about files that are ostensibly not Python files: if the first
|
||||
# line starts with '#!' and does not contain the string 'python'.
|
||||
#
|
||||
# Changes made are reported to stdout in a diff-like format.
|
||||
#
|
||||
# Undoubtedly you can do this using find and sed or perl, but this is
|
||||
# a nice example of Python code that recurses down a directory tree
|
||||
# and uses regular expressions. Also note several subtleties like
|
||||
# preserving the file's mode and avoiding to even write a temp file
|
||||
# when no changes are needed for a file.
|
||||
#
|
||||
# NB: by changing only the function fixline() you can turn this
|
||||
# into a program for a different change to Python programs...
|
||||
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
from stat import *
|
||||
import string
|
||||
|
||||
err = sys.stderr.write
|
||||
dbg = err
|
||||
rep = sys.stdout.write
|
||||
|
||||
def main():
|
||||
bad = 0
|
||||
if not sys.argv[1:]: # No arguments
|
||||
err('usage: ' + sys.argv[0] + ' file-or-directory ...\n')
|
||||
sys.exit(2)
|
||||
for arg in sys.argv[1:]:
|
||||
if os.path.isdir(arg):
|
||||
if recursedown(arg): bad = 1
|
||||
elif os.path.islink(arg):
|
||||
err(arg + ': will not process symbolic links\n')
|
||||
bad = 1
|
||||
else:
|
||||
if fix(arg): bad = 1
|
||||
sys.exit(bad)
|
||||
|
||||
ispythonprog = re.compile('^[a-zA-Z0-9_]+\.py$')
|
||||
def ispython(name):
|
||||
return ispythonprog.match(name) >= 0
|
||||
|
||||
def recursedown(dirname):
|
||||
dbg('recursedown(%r)\n' % (dirname,))
|
||||
bad = 0
|
||||
try:
|
||||
names = os.listdir(dirname)
|
||||
except os.error, msg:
|
||||
err('%s: cannot list directory: %r\n' % (dirname, msg))
|
||||
return 1
|
||||
names.sort()
|
||||
subdirs = []
|
||||
for name in names:
|
||||
if name in (os.curdir, os.pardir): continue
|
||||
fullname = os.path.join(dirname, name)
|
||||
if os.path.islink(fullname): pass
|
||||
elif os.path.isdir(fullname):
|
||||
subdirs.append(fullname)
|
||||
elif ispython(name):
|
||||
if fix(fullname): bad = 1
|
||||
for fullname in subdirs:
|
||||
if recursedown(fullname): bad = 1
|
||||
return bad
|
||||
|
||||
def fix(filename):
|
||||
## dbg('fix(%r)\n' % (dirname,))
|
||||
try:
|
||||
f = open(filename, 'r')
|
||||
except IOError, msg:
|
||||
err('%s: cannot open: %r\n' % (filename, msg))
|
||||
return 1
|
||||
head, tail = os.path.split(filename)
|
||||
tempname = os.path.join(head, '@' + tail)
|
||||
g = None
|
||||
# If we find a match, we rewind the file and start over but
|
||||
# now copy everything to a temp file.
|
||||
lineno = 0
|
||||
while 1:
|
||||
line = f.readline()
|
||||
if not line: break
|
||||
lineno = lineno + 1
|
||||
if g is None and '\0' in line:
|
||||
# Check for binary files
|
||||
err(filename + ': contains null bytes; not fixed\n')
|
||||
f.close()
|
||||
return 1
|
||||
if lineno == 1 and g is None and line[:2] == '#!':
|
||||
# Check for non-Python scripts
|
||||
words = string.split(line[2:])
|
||||
if words and re.search('[pP]ython', words[0]) < 0:
|
||||
msg = filename + ': ' + words[0]
|
||||
msg = msg + ' script; not fixed\n'
|
||||
err(msg)
|
||||
f.close()
|
||||
return 1
|
||||
while line[-2:] == '\\\n':
|
||||
nextline = f.readline()
|
||||
if not nextline: break
|
||||
line = line + nextline
|
||||
lineno = lineno + 1
|
||||
newline = fixline(line)
|
||||
if newline != line:
|
||||
if g is None:
|
||||
try:
|
||||
g = open(tempname, 'w')
|
||||
except IOError, msg:
|
||||
f.close()
|
||||
err('%s: cannot create: %r\n' % (tempname, msg))
|
||||
return 1
|
||||
f.seek(0)
|
||||
lineno = 0
|
||||
rep(filename + ':\n')
|
||||
continue # restart from the beginning
|
||||
rep(repr(lineno) + '\n')
|
||||
rep('< ' + line)
|
||||
rep('> ' + newline)
|
||||
if g is not None:
|
||||
g.write(newline)
|
||||
|
||||
# End of file
|
||||
f.close()
|
||||
if not g: return 0 # No changes
|
||||
|
||||
# Finishing touch -- move files
|
||||
|
||||
# First copy the file's mode to the temp file
|
||||
try:
|
||||
statbuf = os.stat(filename)
|
||||
os.chmod(tempname, statbuf[ST_MODE] & 07777)
|
||||
except os.error, msg:
|
||||
err('%s: warning: chmod failed (%r)\n' % (tempname, msg))
|
||||
# Then make a backup of the original file as filename~
|
||||
try:
|
||||
os.rename(filename, filename + '~')
|
||||
except os.error, msg:
|
||||
err('%s: warning: backup failed (%r)\n' % (filename, msg))
|
||||
# Now move the temp file to the original file
|
||||
try:
|
||||
os.rename(tempname, filename)
|
||||
except os.error, msg:
|
||||
err('%s: rename failed (%r)\n' % (filename, msg))
|
||||
return 1
|
||||
# Return succes
|
||||
return 0
|
||||
|
||||
|
||||
from tokenize import tokenprog
|
||||
|
||||
match = {'if':':', 'elif':':', 'while':':', 'return':'\n', \
|
||||
'(':')', '[':']', '{':'}', '`':'`'}
|
||||
|
||||
def fixline(line):
|
||||
# Quick check for easy case
|
||||
if '=' not in line: return line
|
||||
|
||||
i, n = 0, len(line)
|
||||
stack = []
|
||||
while i < n:
|
||||
j = tokenprog.match(line, i)
|
||||
if j < 0:
|
||||
# A bad token; forget about the rest of this line
|
||||
print '(Syntax error:)'
|
||||
print line,
|
||||
return line
|
||||
a, b = tokenprog.regs[3] # Location of the token proper
|
||||
token = line[a:b]
|
||||
i = i+j
|
||||
if stack and token == stack[-1]:
|
||||
del stack[-1]
|
||||
elif match.has_key(token):
|
||||
stack.append(match[token])
|
||||
elif token == '=' and stack:
|
||||
line = line[:a] + '==' + line[b:]
|
||||
i, n = a + len('=='), len(line)
|
||||
elif token == '==' and not stack:
|
||||
print '(Warning: \'==\' at top level:)'
|
||||
print line,
|
||||
return line
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
49
2.7/Python-2.7.16/Demo/scripts/fact.py
Normal file
49
2.7/Python-2.7.16/Demo/scripts/fact.py
Normal file
@ -0,0 +1,49 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# Factorize numbers.
|
||||
# The algorithm is not efficient, but easy to understand.
|
||||
# If there are large factors, it will take forever to find them,
|
||||
# because we try all odd numbers between 3 and sqrt(n)...
|
||||
|
||||
import sys
|
||||
from math import sqrt
|
||||
|
||||
def fact(n):
|
||||
if n < 1:
|
||||
raise ValueError('fact() argument should be >= 1')
|
||||
if n == 1:
|
||||
return [] # special case
|
||||
res = []
|
||||
# Treat even factors special, so we can use i += 2 later
|
||||
while n % 2 == 0:
|
||||
res.append(2)
|
||||
n //= 2
|
||||
# Try odd numbers up to sqrt(n)
|
||||
limit = sqrt(n+1)
|
||||
i = 3
|
||||
while i <= limit:
|
||||
if n % i == 0:
|
||||
res.append(i)
|
||||
n //= i
|
||||
limit = sqrt(n+1)
|
||||
else:
|
||||
i += 2
|
||||
if n != 1:
|
||||
res.append(n)
|
||||
return res
|
||||
|
||||
def main():
|
||||
if len(sys.argv) > 1:
|
||||
source = sys.argv[1:]
|
||||
else:
|
||||
source = iter(raw_input, '')
|
||||
for arg in source:
|
||||
try:
|
||||
n = int(arg)
|
||||
except ValueError:
|
||||
print arg, 'is not an integer'
|
||||
else:
|
||||
print n, fact(n)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
40
2.7/Python-2.7.16/Demo/scripts/find-uname.py
Normal file
40
2.7/Python-2.7.16/Demo/scripts/find-uname.py
Normal file
@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
For each argument on the command line, look for it in the set of all Unicode
|
||||
names. Arguments are treated as case-insensitive regular expressions, e.g.:
|
||||
|
||||
% find-uname 'small letter a$' 'horizontal line'
|
||||
*** small letter a$ matches ***
|
||||
LATIN SMALL LETTER A (97)
|
||||
COMBINING LATIN SMALL LETTER A (867)
|
||||
CYRILLIC SMALL LETTER A (1072)
|
||||
PARENTHESIZED LATIN SMALL LETTER A (9372)
|
||||
CIRCLED LATIN SMALL LETTER A (9424)
|
||||
FULLWIDTH LATIN SMALL LETTER A (65345)
|
||||
*** horizontal line matches ***
|
||||
HORIZONTAL LINE EXTENSION (9135)
|
||||
"""
|
||||
|
||||
import unicodedata
|
||||
import sys
|
||||
import re
|
||||
|
||||
def main(args):
|
||||
unicode_names = []
|
||||
for ix in range(sys.maxunicode+1):
|
||||
try:
|
||||
unicode_names.append((ix, unicodedata.name(unichr(ix))))
|
||||
except ValueError: # no name for the character
|
||||
pass
|
||||
for arg in args:
|
||||
pat = re.compile(arg, re.I)
|
||||
matches = [(y,x) for (x,y) in unicode_names
|
||||
if pat.search(y) is not None]
|
||||
if matches:
|
||||
print "***", arg, "matches", "***"
|
||||
for match in matches:
|
||||
print "%s (%d)" % match
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv[1:])
|
35
2.7/Python-2.7.16/Demo/scripts/from.py
Normal file
35
2.7/Python-2.7.16/Demo/scripts/from.py
Normal file
@ -0,0 +1,35 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# Print From and Subject of messages in $MAIL.
|
||||
# Extension to multiple mailboxes and other bells & whistles are left
|
||||
# as exercises for the reader.
|
||||
|
||||
import sys, os
|
||||
|
||||
# Open mailbox file. Exits with exception when this fails.
|
||||
|
||||
try:
|
||||
mailbox = os.environ['MAIL']
|
||||
except (AttributeError, KeyError):
|
||||
sys.stderr.write('No environment variable $MAIL\n')
|
||||
sys.exit(2)
|
||||
|
||||
try:
|
||||
mail = open(mailbox)
|
||||
except IOError:
|
||||
sys.exit('Cannot open mailbox file: ' + mailbox)
|
||||
|
||||
while 1:
|
||||
line = mail.readline()
|
||||
if not line:
|
||||
break # EOF
|
||||
if line.startswith('From '):
|
||||
# Start of message found
|
||||
print line[:-1],
|
||||
while 1:
|
||||
line = mail.readline()
|
||||
if not line or line == '\n':
|
||||
break
|
||||
if line.startswith('Subject: '):
|
||||
print repr(line[9:-1]),
|
||||
print
|
102
2.7/Python-2.7.16/Demo/scripts/lpwatch.py
Normal file
102
2.7/Python-2.7.16/Demo/scripts/lpwatch.py
Normal file
@ -0,0 +1,102 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# Watch line printer queue(s).
|
||||
# Intended for BSD 4.3 lpq.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
DEF_PRINTER = 'psc'
|
||||
DEF_DELAY = 10
|
||||
|
||||
def main():
|
||||
delay = DEF_DELAY # XXX Use getopt() later
|
||||
try:
|
||||
thisuser = os.environ['LOGNAME']
|
||||
except:
|
||||
thisuser = os.environ['USER']
|
||||
printers = sys.argv[1:]
|
||||
if printers:
|
||||
# Strip '-P' from printer names just in case
|
||||
# the user specified it...
|
||||
for i, name in enumerate(printers):
|
||||
if name[:2] == '-P':
|
||||
printers[i] = name[2:]
|
||||
else:
|
||||
if os.environ.has_key('PRINTER'):
|
||||
printers = [os.environ['PRINTER']]
|
||||
else:
|
||||
printers = [DEF_PRINTER]
|
||||
|
||||
clearhome = os.popen('clear', 'r').read()
|
||||
|
||||
while True:
|
||||
text = clearhome
|
||||
for name in printers:
|
||||
text += makestatus(name, thisuser) + '\n'
|
||||
print text
|
||||
time.sleep(delay)
|
||||
|
||||
def makestatus(name, thisuser):
|
||||
pipe = os.popen('lpq -P' + name + ' 2>&1', 'r')
|
||||
lines = []
|
||||
users = {}
|
||||
aheadbytes = 0
|
||||
aheadjobs = 0
|
||||
userseen = False
|
||||
totalbytes = 0
|
||||
totaljobs = 0
|
||||
for line in pipe:
|
||||
fields = line.split()
|
||||
n = len(fields)
|
||||
if len(fields) >= 6 and fields[n-1] == 'bytes':
|
||||
rank, user, job = fields[0:3]
|
||||
files = fields[3:-2]
|
||||
bytes = int(fields[n-2])
|
||||
if user == thisuser:
|
||||
userseen = True
|
||||
elif not userseen:
|
||||
aheadbytes += bytes
|
||||
aheadjobs += 1
|
||||
totalbytes += bytes
|
||||
totaljobs += 1
|
||||
ujobs, ubytes = users.get(user, (0, 0))
|
||||
ujobs += 1
|
||||
ubytes += bytes
|
||||
users[user] = ujobs, ubytes
|
||||
else:
|
||||
if fields and fields[0] != 'Rank':
|
||||
line = line.strip()
|
||||
if line == 'no entries':
|
||||
line = name + ': idle'
|
||||
elif line[-22:] == ' is ready and printing':
|
||||
line = name
|
||||
lines.append(line)
|
||||
|
||||
if totaljobs:
|
||||
line = '%d K' % ((totalbytes+1023) // 1024)
|
||||
if totaljobs != len(users):
|
||||
line += ' (%d jobs)' % totaljobs
|
||||
if len(users) == 1:
|
||||
line += ' for %s' % (users.keys()[0],)
|
||||
else:
|
||||
line += ' for %d users' % len(users)
|
||||
if userseen:
|
||||
if aheadjobs == 0:
|
||||
line += ' (%s first)' % thisuser
|
||||
else:
|
||||
line += ' (%d K before %s)' % (
|
||||
(aheadbytes+1023) // 1024, thisuser)
|
||||
lines.append(line)
|
||||
|
||||
sts = pipe.close()
|
||||
if sts:
|
||||
lines.append('lpq exit status %r' % (sts,))
|
||||
return ': '.join(lines)
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
21
2.7/Python-2.7.16/Demo/scripts/makedir.py
Normal file
21
2.7/Python-2.7.16/Demo/scripts/makedir.py
Normal file
@ -0,0 +1,21 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# Like mkdir, but also make intermediate directories if necessary.
|
||||
# It is not an error if the given directory already exists (as long
|
||||
# as it is a directory).
|
||||
# Errors are not treated specially -- you just get a Python exception.
|
||||
|
||||
import sys, os
|
||||
|
||||
def main():
|
||||
for p in sys.argv[1:]:
|
||||
makedirs(p)
|
||||
|
||||
def makedirs(p):
|
||||
if p and not os.path.isdir(p):
|
||||
head, tail = os.path.split(p)
|
||||
makedirs(head)
|
||||
os.mkdir(p, 0777)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
121
2.7/Python-2.7.16/Demo/scripts/markov.py
Normal file
121
2.7/Python-2.7.16/Demo/scripts/markov.py
Normal file
@ -0,0 +1,121 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
class Markov:
|
||||
def __init__(self, histsize, choice):
|
||||
self.histsize = histsize
|
||||
self.choice = choice
|
||||
self.trans = {}
|
||||
|
||||
def add(self, state, next):
|
||||
self.trans.setdefault(state, []).append(next)
|
||||
|
||||
def put(self, seq):
|
||||
n = self.histsize
|
||||
add = self.add
|
||||
add(None, seq[:0])
|
||||
for i in range(len(seq)):
|
||||
add(seq[max(0, i-n):i], seq[i:i+1])
|
||||
add(seq[len(seq)-n:], None)
|
||||
|
||||
def get(self):
|
||||
choice = self.choice
|
||||
trans = self.trans
|
||||
n = self.histsize
|
||||
seq = choice(trans[None])
|
||||
while True:
|
||||
subseq = seq[max(0, len(seq)-n):]
|
||||
options = trans[subseq]
|
||||
next = choice(options)
|
||||
if not next:
|
||||
break
|
||||
seq += next
|
||||
return seq
|
||||
|
||||
|
||||
def test():
|
||||
import sys, random, getopt
|
||||
args = sys.argv[1:]
|
||||
try:
|
||||
opts, args = getopt.getopt(args, '0123456789cdwq')
|
||||
except getopt.error:
|
||||
print 'Usage: %s [-#] [-cddqw] [file] ...' % sys.argv[0]
|
||||
print 'Options:'
|
||||
print '-#: 1-digit history size (default 2)'
|
||||
print '-c: characters (default)'
|
||||
print '-w: words'
|
||||
print '-d: more debugging output'
|
||||
print '-q: no debugging output'
|
||||
print 'Input files (default stdin) are split in paragraphs'
|
||||
print 'separated blank lines and each paragraph is split'
|
||||
print 'in words by whitespace, then reconcatenated with'
|
||||
print 'exactly one space separating words.'
|
||||
print 'Output consists of paragraphs separated by blank'
|
||||
print 'lines, where lines are no longer than 72 characters.'
|
||||
sys.exit(2)
|
||||
histsize = 2
|
||||
do_words = False
|
||||
debug = 1
|
||||
for o, a in opts:
|
||||
if '-0' <= o <= '-9': histsize = int(o[1:])
|
||||
if o == '-c': do_words = False
|
||||
if o == '-d': debug += 1
|
||||
if o == '-q': debug = 0
|
||||
if o == '-w': do_words = True
|
||||
if not args:
|
||||
args = ['-']
|
||||
|
||||
m = Markov(histsize, random.choice)
|
||||
try:
|
||||
for filename in args:
|
||||
if filename == '-':
|
||||
f = sys.stdin
|
||||
if f.isatty():
|
||||
print 'Sorry, need stdin from file'
|
||||
continue
|
||||
else:
|
||||
f = open(filename, 'r')
|
||||
if debug: print 'processing', filename, '...'
|
||||
text = f.read()
|
||||
f.close()
|
||||
paralist = text.split('\n\n')
|
||||
for para in paralist:
|
||||
if debug > 1: print 'feeding ...'
|
||||
words = para.split()
|
||||
if words:
|
||||
if do_words:
|
||||
data = tuple(words)
|
||||
else:
|
||||
data = ' '.join(words)
|
||||
m.put(data)
|
||||
except KeyboardInterrupt:
|
||||
print 'Interrupted -- continue with data read so far'
|
||||
if not m.trans:
|
||||
print 'No valid input files'
|
||||
return
|
||||
if debug: print 'done.'
|
||||
|
||||
if debug > 1:
|
||||
for key in m.trans.keys():
|
||||
if key is None or len(key) < histsize:
|
||||
print repr(key), m.trans[key]
|
||||
if histsize == 0: print repr(''), m.trans['']
|
||||
print
|
||||
while True:
|
||||
data = m.get()
|
||||
if do_words:
|
||||
words = data
|
||||
else:
|
||||
words = data.split()
|
||||
n = 0
|
||||
limit = 72
|
||||
for w in words:
|
||||
if n + len(w) > limit:
|
||||
print
|
||||
n = 0
|
||||
print w,
|
||||
n += len(w) + 1
|
||||
print
|
||||
print
|
||||
|
||||
if __name__ == "__main__":
|
||||
test()
|
124
2.7/Python-2.7.16/Demo/scripts/mboxconvert.py
Normal file
124
2.7/Python-2.7.16/Demo/scripts/mboxconvert.py
Normal file
@ -0,0 +1,124 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# Convert MH directories (1 message per file) or MMDF mailboxes (4x^A
|
||||
# delimited) to unix mailbox (From ... delimited) on stdout.
|
||||
# If -f is given, files contain one message per file (e.g. MH messages)
|
||||
|
||||
import rfc822
|
||||
import sys
|
||||
import time
|
||||
import os
|
||||
import stat
|
||||
import getopt
|
||||
import re
|
||||
|
||||
def main():
|
||||
dofile = mmdf
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'f')
|
||||
except getopt.error, msg:
|
||||
sys.stderr.write('%s\n' % msg)
|
||||
sys.exit(2)
|
||||
for o, a in opts:
|
||||
if o == '-f':
|
||||
dofile = message
|
||||
if not args:
|
||||
args = ['-']
|
||||
sts = 0
|
||||
for arg in args:
|
||||
if arg == '-' or arg == '':
|
||||
sts = dofile(sys.stdin) or sts
|
||||
elif os.path.isdir(arg):
|
||||
sts = mh(arg) or sts
|
||||
elif os.path.isfile(arg):
|
||||
try:
|
||||
f = open(arg)
|
||||
except IOError, msg:
|
||||
sys.stderr.write('%s: %s\n' % (arg, msg))
|
||||
sts = 1
|
||||
continue
|
||||
sts = dofile(f) or sts
|
||||
f.close()
|
||||
else:
|
||||
sys.stderr.write('%s: not found\n' % arg)
|
||||
sts = 1
|
||||
if sts:
|
||||
sys.exit(sts)
|
||||
|
||||
numeric = re.compile('[1-9][0-9]*')
|
||||
|
||||
def mh(dir):
|
||||
sts = 0
|
||||
msgs = os.listdir(dir)
|
||||
for msg in msgs:
|
||||
if numeric.match(msg) != len(msg):
|
||||
continue
|
||||
fn = os.path.join(dir, msg)
|
||||
try:
|
||||
f = open(fn)
|
||||
except IOError, msg:
|
||||
sys.stderr.write('%s: %s\n' % (fn, msg))
|
||||
sts = 1
|
||||
continue
|
||||
sts = message(f) or sts
|
||||
return sts
|
||||
|
||||
def mmdf(f):
|
||||
sts = 0
|
||||
while 1:
|
||||
line = f.readline()
|
||||
if not line:
|
||||
break
|
||||
if line == '\1\1\1\1\n':
|
||||
sts = message(f, line) or sts
|
||||
else:
|
||||
sys.stderr.write(
|
||||
'Bad line in MMFD mailbox: %r\n' % (line,))
|
||||
return sts
|
||||
|
||||
counter = 0 # for generating unique Message-ID headers
|
||||
|
||||
def message(f, delimiter = ''):
|
||||
sts = 0
|
||||
# Parse RFC822 header
|
||||
m = rfc822.Message(f)
|
||||
# Write unix header line
|
||||
fullname, email = m.getaddr('From')
|
||||
tt = m.getdate('Date')
|
||||
if tt:
|
||||
t = time.mktime(tt)
|
||||
else:
|
||||
sys.stderr.write(
|
||||
'Unparseable date: %r\n' % (m.getheader('Date'),))
|
||||
t = os.fstat(f.fileno())[stat.ST_MTIME]
|
||||
print 'From', email, time.ctime(t)
|
||||
# Copy RFC822 header
|
||||
for line in m.headers:
|
||||
print line,
|
||||
# Invent Message-ID header if none is present
|
||||
if not m.has_key('message-id'):
|
||||
global counter
|
||||
counter = counter + 1
|
||||
msgid = "<%s.%d>" % (hex(t), counter)
|
||||
sys.stderr.write("Adding Message-ID %s (From %s)\n" %
|
||||
(msgid, email))
|
||||
print "Message-ID:", msgid
|
||||
print
|
||||
# Copy body
|
||||
while 1:
|
||||
line = f.readline()
|
||||
if line == delimiter:
|
||||
break
|
||||
if not line:
|
||||
sys.stderr.write('Unexpected EOF in message\n')
|
||||
sts = 1
|
||||
break
|
||||
if line[:5] == 'From ':
|
||||
line = '>' + line
|
||||
print line,
|
||||
# Print trailing newline
|
||||
print
|
||||
return sts
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
138
2.7/Python-2.7.16/Demo/scripts/morse.py
Normal file
138
2.7/Python-2.7.16/Demo/scripts/morse.py
Normal file
@ -0,0 +1,138 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# DAH should be three DOTs.
|
||||
# Space between DOTs and DAHs should be one DOT.
|
||||
# Space between two letters should be one DAH.
|
||||
# Space between two words should be DOT DAH DAH.
|
||||
|
||||
import sys, math, audiodev
|
||||
|
||||
DOT = 30
|
||||
DAH = 3 * DOT
|
||||
OCTAVE = 2 # 1 == 441 Hz, 2 == 882 Hz, ...
|
||||
|
||||
morsetab = {
|
||||
'A': '.-', 'a': '.-',
|
||||
'B': '-...', 'b': '-...',
|
||||
'C': '-.-.', 'c': '-.-.',
|
||||
'D': '-..', 'd': '-..',
|
||||
'E': '.', 'e': '.',
|
||||
'F': '..-.', 'f': '..-.',
|
||||
'G': '--.', 'g': '--.',
|
||||
'H': '....', 'h': '....',
|
||||
'I': '..', 'i': '..',
|
||||
'J': '.---', 'j': '.---',
|
||||
'K': '-.-', 'k': '-.-',
|
||||
'L': '.-..', 'l': '.-..',
|
||||
'M': '--', 'm': '--',
|
||||
'N': '-.', 'n': '-.',
|
||||
'O': '---', 'o': '---',
|
||||
'P': '.--.', 'p': '.--.',
|
||||
'Q': '--.-', 'q': '--.-',
|
||||
'R': '.-.', 'r': '.-.',
|
||||
'S': '...', 's': '...',
|
||||
'T': '-', 't': '-',
|
||||
'U': '..-', 'u': '..-',
|
||||
'V': '...-', 'v': '...-',
|
||||
'W': '.--', 'w': '.--',
|
||||
'X': '-..-', 'x': '-..-',
|
||||
'Y': '-.--', 'y': '-.--',
|
||||
'Z': '--..', 'z': '--..',
|
||||
'0': '-----', ',': '--..--',
|
||||
'1': '.----', '.': '.-.-.-',
|
||||
'2': '..---', '?': '..--..',
|
||||
'3': '...--', ';': '-.-.-.',
|
||||
'4': '....-', ':': '---...',
|
||||
'5': '.....', "'": '.----.',
|
||||
'6': '-....', '-': '-....-',
|
||||
'7': '--...', '/': '-..-.',
|
||||
'8': '---..', '(': '-.--.-',
|
||||
'9': '----.', ')': '-.--.-',
|
||||
' ': ' ', '_': '..--.-',
|
||||
}
|
||||
|
||||
nowave = '\0' * 200
|
||||
|
||||
# If we play at 44.1 kHz (which we do), then if we produce one sine
|
||||
# wave in 100 samples, we get a tone of 441 Hz. If we produce two
|
||||
# sine waves in these 100 samples, we get a tone of 882 Hz. 882 Hz
|
||||
# appears to be a nice one for playing morse code.
|
||||
def mkwave(octave):
|
||||
sinewave = ''
|
||||
for i in range(100):
|
||||
val = int(math.sin(math.pi * i * octave / 50.0) * 30000)
|
||||
sinewave += chr((val >> 8) & 255) + chr(val & 255)
|
||||
return sinewave
|
||||
|
||||
defaultwave = mkwave(OCTAVE)
|
||||
|
||||
def main():
|
||||
import getopt
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'o:p:')
|
||||
except getopt.error:
|
||||
sys.stderr.write('Usage ' + sys.argv[0] +
|
||||
' [ -o outfile ] [ -p octave ] [ words ] ...\n')
|
||||
sys.exit(1)
|
||||
dev = None
|
||||
wave = defaultwave
|
||||
for o, a in opts:
|
||||
if o == '-o':
|
||||
import aifc
|
||||
dev = aifc.open(a, 'w')
|
||||
dev.setframerate(44100)
|
||||
dev.setsampwidth(2)
|
||||
dev.setnchannels(1)
|
||||
if o == '-p':
|
||||
wave = mkwave(int(a))
|
||||
if not dev:
|
||||
import audiodev
|
||||
dev = audiodev.AudioDev()
|
||||
dev.setoutrate(44100)
|
||||
dev.setsampwidth(2)
|
||||
dev.setnchannels(1)
|
||||
dev.close = dev.stop
|
||||
dev.writeframesraw = dev.writeframes
|
||||
if args:
|
||||
source = [' '.join(args)]
|
||||
else:
|
||||
source = iter(sys.stdin.readline, '')
|
||||
for line in source:
|
||||
mline = morse(line)
|
||||
play(mline, dev, wave)
|
||||
if hasattr(dev, 'wait'):
|
||||
dev.wait()
|
||||
dev.close()
|
||||
|
||||
# Convert a string to morse code with \001 between the characters in
|
||||
# the string.
|
||||
def morse(line):
|
||||
res = ''
|
||||
for c in line:
|
||||
try:
|
||||
res += morsetab[c] + '\001'
|
||||
except KeyError:
|
||||
pass
|
||||
return res
|
||||
|
||||
# Play a line of morse code.
|
||||
def play(line, dev, wave):
|
||||
for c in line:
|
||||
if c == '.':
|
||||
sine(dev, DOT, wave)
|
||||
elif c == '-':
|
||||
sine(dev, DAH, wave)
|
||||
else: # space
|
||||
pause(dev, DAH + DOT)
|
||||
pause(dev, DOT)
|
||||
|
||||
def sine(dev, length, wave):
|
||||
for i in range(length):
|
||||
dev.writeframesraw(wave)
|
||||
|
||||
def pause(dev, length):
|
||||
for i in range(length):
|
||||
dev.writeframesraw(nowave)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
33
2.7/Python-2.7.16/Demo/scripts/pi.py
Normal file
33
2.7/Python-2.7.16/Demo/scripts/pi.py
Normal file
@ -0,0 +1,33 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# Print digits of pi forever.
|
||||
#
|
||||
# The algorithm, using Python's 'long' integers ("bignums"), works
|
||||
# with continued fractions, and was conceived by Lambert Meertens.
|
||||
#
|
||||
# See also the ABC Programmer's Handbook, by Geurts, Meertens & Pemberton,
|
||||
# published by Prentice-Hall (UK) Ltd., 1990.
|
||||
|
||||
import sys
|
||||
|
||||
def main():
|
||||
k, a, b, a1, b1 = 2, 4, 1, 12, 4
|
||||
while True:
|
||||
# Next approximation
|
||||
p, q, k = k*k, 2*k+1, k+1
|
||||
a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1
|
||||
# Print common digits
|
||||
d, d1 = a//b, a1//b1
|
||||
while d == d1:
|
||||
output(d)
|
||||
a, a1 = 10*(a%b), 10*(a1%b1)
|
||||
d, d1 = a//b, a1//b1
|
||||
|
||||
def output(d):
|
||||
# Use write() to avoid spaces between the digits
|
||||
sys.stdout.write(str(d))
|
||||
# Flush so the output is seen immediately
|
||||
sys.stdout.flush()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
129
2.7/Python-2.7.16/Demo/scripts/pp.py
Normal file
129
2.7/Python-2.7.16/Demo/scripts/pp.py
Normal file
@ -0,0 +1,129 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# Emulate some Perl command line options.
|
||||
# Usage: pp [-a] [-c] [-d] [-e scriptline] [-F fieldsep] [-n] [-p] [file] ...
|
||||
# Where the options mean the following:
|
||||
# -a : together with -n or -p, splits each line into list F
|
||||
# -c : check syntax only, do not execute any code
|
||||
# -d : run the script under the debugger, pdb
|
||||
# -e scriptline : gives one line of the Python script; may be repeated
|
||||
# -F fieldsep : sets the field separator for the -a option [not in Perl]
|
||||
# -n : runs the script for each line of input
|
||||
# -p : prints the line after the script has run
|
||||
# When no script lines have been passed, the first file argument
|
||||
# contains the script. With -n or -p, the remaining arguments are
|
||||
# read as input to the script, line by line. If a file is '-'
|
||||
# or missing, standard input is read.
|
||||
|
||||
# XXX To do:
|
||||
# - add -i extension option (change files in place)
|
||||
# - make a single loop over the files and lines (changes effect of 'break')?
|
||||
# - add an option to specify the record separator
|
||||
# - except for -n/-p, run directly from the file if at all possible
|
||||
|
||||
import sys
|
||||
import getopt
|
||||
|
||||
FS = ''
|
||||
SCRIPT = []
|
||||
AFLAG = 0
|
||||
CFLAG = 0
|
||||
DFLAG = 0
|
||||
NFLAG = 0
|
||||
PFLAG = 0
|
||||
|
||||
try:
|
||||
optlist, ARGS = getopt.getopt(sys.argv[1:], 'acde:F:np')
|
||||
except getopt.error, msg:
|
||||
sys.stderr.write('%s: %s\n' % (sys.argv[0], msg))
|
||||
sys.exit(2)
|
||||
|
||||
for option, optarg in optlist:
|
||||
if option == '-a':
|
||||
AFLAG = 1
|
||||
elif option == '-c':
|
||||
CFLAG = 1
|
||||
elif option == '-d':
|
||||
DFLAG = 1
|
||||
elif option == '-e':
|
||||
for line in optarg.split('\n'):
|
||||
SCRIPT.append(line)
|
||||
elif option == '-F':
|
||||
FS = optarg
|
||||
elif option == '-n':
|
||||
NFLAG = 1
|
||||
PFLAG = 0
|
||||
elif option == '-p':
|
||||
NFLAG = 1
|
||||
PFLAG = 1
|
||||
else:
|
||||
print option, 'not recognized???'
|
||||
|
||||
if not ARGS: ARGS.append('-')
|
||||
|
||||
if not SCRIPT:
|
||||
if ARGS[0] == '-':
|
||||
fp = sys.stdin
|
||||
else:
|
||||
fp = open(ARGS[0], 'r')
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if not line: break
|
||||
SCRIPT.append(line[:-1])
|
||||
del fp
|
||||
del ARGS[0]
|
||||
if not ARGS: ARGS.append('-')
|
||||
|
||||
if CFLAG:
|
||||
prologue = ['if 0:']
|
||||
epilogue = []
|
||||
elif NFLAG:
|
||||
# Note that it is on purpose that AFLAG and PFLAG are
|
||||
# tested dynamically each time through the loop
|
||||
prologue = [
|
||||
'LINECOUNT = 0',
|
||||
'for FILE in ARGS:',
|
||||
' \tif FILE == \'-\':',
|
||||
' \t \tFP = sys.stdin',
|
||||
' \telse:',
|
||||
' \t \tFP = open(FILE, \'r\')',
|
||||
' \tLINENO = 0',
|
||||
' \twhile 1:',
|
||||
' \t \tLINE = FP.readline()',
|
||||
' \t \tif not LINE: break',
|
||||
' \t \tLINENO = LINENO + 1',
|
||||
' \t \tLINECOUNT = LINECOUNT + 1',
|
||||
' \t \tL = LINE[:-1]',
|
||||
' \t \taflag = AFLAG',
|
||||
' \t \tif aflag:',
|
||||
' \t \t \tif FS: F = L.split(FS)',
|
||||
' \t \t \telse: F = L.split()'
|
||||
]
|
||||
epilogue = [
|
||||
' \t \tif not PFLAG: continue',
|
||||
' \t \tif aflag:',
|
||||
' \t \t \tif FS: print FS.join(F)',
|
||||
' \t \t \telse: print \' \'.join(F)',
|
||||
' \t \telse: print L',
|
||||
]
|
||||
else:
|
||||
prologue = ['if 1:']
|
||||
epilogue = []
|
||||
|
||||
# Note that we indent using tabs only, so that any indentation style
|
||||
# used in 'command' will come out right after re-indentation.
|
||||
|
||||
program = '\n'.join(prologue) + '\n'
|
||||
for line in SCRIPT:
|
||||
program += ' \t \t' + line + '\n'
|
||||
program += '\n'.join(epilogue) + '\n'
|
||||
|
||||
import tempfile
|
||||
fp = tempfile.NamedTemporaryFile()
|
||||
fp.write(program)
|
||||
fp.flush()
|
||||
if DFLAG:
|
||||
import pdb
|
||||
pdb.run('execfile(%r)' % (fp.name,))
|
||||
else:
|
||||
execfile(fp.name)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user