summaryrefslogtreecommitdiff
path: root/test/scanners/python/pleac.in.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/scanners/python/pleac.in.py')
-rw-r--r--test/scanners/python/pleac.in.py11119
1 files changed, 0 insertions, 11119 deletions
diff --git a/test/scanners/python/pleac.in.py b/test/scanners/python/pleac.in.py
deleted file mode 100644
index 6b9a79b..0000000
--- a/test/scanners/python/pleac.in.py
+++ /dev/null
@@ -1,11119 +0,0 @@
-# -*- python -*-
-# vim:set ft=python:
-
-# @@PLEAC@@_NAME
-# @@SKIP@@ Python
-
-# @@PLEAC@@_WEB
-# @@SKIP@@ http://www.python.org
-
-# @@PLEAC@@_INTRO
-# @@SKIP@@ The latest version of Python is 2.4 but users of 2.3 and 2.2 (and
-# @@SKIP@@ in some cases earlier versions) can use the code herein.
-# @@SKIP@@ Users of 2.2 and 2.3 should install or copy code from utils.py
-# @@SKIP@@ (http://aima.cs.berkeley.edu/python/utils.py)
-# @@SKIP@@ [the first section provides compatability code with 2.4]
-# @@SKIP@@ Users of 2.2 should install optik (http://optik.sourceforge.com)
-# @@SKIP@@ [for optparse and textwrap]
-# @@SKIP@@ Where a 2.3 or 2.4 feature is unable to be replicated, an effort
-# @@SKIP@@ has been made to provide a backward-compatible version in addition
-# @@SKIP@@ to one using modern idioms.
-# @@SKIP@@ Examples which translate the original Perl closely but which are
-# @@SKIP@@ unPythonic are prefixed with a comment stating "DON'T DO THIS".
-# @@SKIP@@ In some cases, it may be useful to know the techniques in these,
-# @@SKIP@@ though it's a bad solution for the specific problem.
-
-# @@PLEAC@@_1.0
-#-----------------------------
-mystr = "\n" # a newline character
-mystr = r"\n" # two characters, \ and n
-#-----------------------------
-mystr = "Jon 'Maddog' Orwant" # literal single quote inside double quotes
-mystr = 'Jon "Maddog" Orwant' # literal double quote inside single quotes
-#-----------------------------
-mystr = 'Jon \'Maddog\' Orwant' # escaped single quote
-mystr = "Jon \"Maddog\" Orwant" # escaped double quote
-#-----------------------------
-mystr = """
-This is a multiline string literal
-enclosed in triple double quotes.
-"""
-mystr = '''
-And this is a multiline string literal
-enclosed in triple single quotes.
-'''
-#-----------------------------
-
-# @@PLEAC@@_1.1
-#-----------------------------
-
-# get a 5-char string, skip 3, then grab 2 8-char strings, then the rest
-# Note that struct.unpack cannot use * for an unknown length.
-# See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65224
-import struct
-(lead, s1, s2), tail = struct.unpack("5s 3x 8s 8s", data[:24]), data[24:]
-
-# split at five-char boundaries
-fivers = struct.unpack("5s" * (len(data)//5), data)
-fivers = print [x[i*5:i*5+5] for i in range(len(x)/5)]
-
-# chop string into individual characters
-chars = list(data)
-#-----------------------------
-mystr = "This is what you have"
-# +012345678901234567890 Indexing forwards (left to right)
-# 109876543210987654321- Indexing backwards (right to left)
-# note that 0 means 10 or 20, etc. above
-
-first = mystr[0] # "T"
-start = mystr[5:7] # "is"
-rest = mystr[13:] # "you have"
-last = mystr[-1] # "e"
-end = mystr[-4:] # "have"
-piece = mystr[-8:-5] # "you"
-#-----------------------------
-# Python strings are immutable.
-# In general, you should just do piecemeal reallocation:
-mystr = "This is what you have"
-mystr = mystr[:5] + "wasn't" + mystr[7:]
-
-# Or replace and reallocate
-mystr = "This is what you have"
-mystr = mystr.replace(" is ", " wasn't ")
-
-# DON'T DO THIS: In-place modification could be done using character arrays
-import array
-mystr = array.array("c", "This is what you have")
-mystr[5:7] = array.array("c", "wasn't")
-# mystr is now array('c', "This wasn't what you have")
-
-# DON'T DO THIS: It could also be done using MutableString
-from UserString import MutableString
-mystr = MutableString("This is what you have")
-mystr[-12:] = "ondrous"
-# mystr is now "This is wondrous"
-#-----------------------------
-# you can test simple substrings with "in" (for regex matching see ch.6):
-if txt in mystr[-10:]:
- print "'%s' found in last 10 characters"%txt
-
-# Or use the startswith() and endswith() string methods:
-if mystr.startswith(txt):
- print "%s starts with %s."%(mystr, txt)
-if mystr.endswith(txt):
- print "%s ends with %s."%(mystr, txt)
-
-#-----------------------------
-
-# @@PLEAC@@_1.2
-#-----------------------------
-# Introductory Note: quite a bit of this section is not terribly Pythonic
-# as names must be set before being used. For instance, unless myvar has
-# been previously defined, these next lines will all raise NameError:
-myvar = myvar or some_default
-myvar2 = myvar or some_default
-myvar |= some_default # bitwise-or, not logical-or - for demo
-
-# The standard way of setting a default is often:
-myvar = default_value
-if some_condition:
- pass # code which may set myvar to something else
-
-# if myvar is returned from a function and may be empty/None, then use:
-myvar = somefunc()
-if not myvar:
- myvar = default_value
-
-# If you want a default value that can be overridden by the person calling
-# your code, you can often wrap it in a function with a named parameter:
-def myfunc(myvar="a"):
- return myvar + "b"
-print myfunc(), myfunc("c")
-#=> ab cb
-
-# Note, though, that this won't work for mutable objects such as lists or
-# dicts that are mutated in the function as the object is only created once
-# and repeated calls to the same function will return the same object. This
-# can be desired behaviour however - see section 10.3, for instance.
-def myfunc(myvar=[]):
- myvar.append("x")
- return myvar
-print myfunc(), myfunc()
-#=> ['x'] ['x', 'x']
-
-# You need to do:
-def myfunc(myvar=None):
- if myvar is None:
- myvar = []
- myvar.append("x")
- return myvar
-print myfunc(), myfunc()
-#=> ['x'] ['x']
-
-#=== Perl Equivalencies start here
-# use b if b is true, otherwise use c
-a = b or c
-
-# as that is a little tricksy, the following may be preferred:
-if b:
- a = b
-else:
- a = c
-
-# set x to y unless x is already true
-if not x:
- x = y
-#-----------------------------
-# use b if b is defined, else c
-try:
- a = b
-except NameError:
- a = c
-#-----------------------------
-foo = bar or "DEFAULT VALUE"
-#-----------------------------
-# To get a user (for both UNIX and Windows), use:
-import getpass
-user = getpass.getuser()
-
-# DON'T DO THIS: find the user name on Unix systems
-import os
-user = os.environ.get("USER")
-if user is None:
- user = os.environ.get("LOGNAME")
-#-----------------------------
-if not starting_point:
- starting_point = "Greenwich"
-#-----------------------------
-if not a: # copy only if empty
- a = b
-
-if b: # assign b if nonempty, else c
- a = b
-else:
- a = c
-#-----------------------------
-
-# @@PLEAC@@_1.3
-#-----------------------------
-v1, v2 = v2, v1
-#-----------------------------
-# DON'T DO THIS:
-temp = a
-a = b
-b = temp
-#-----------------------------
-a = "alpha"
-b = "omega"
-a, b = b, a # the first shall be last -- and versa vice
-#-----------------------------
-alpha, beta, production = "January March August".split()
-alpha, beta, production = beta, production, alpha
-#-----------------------------
-
-# @@PLEAC@@_1.4
-#-----------------------------
-num = ord(char)
-char = chr(num)
-#-----------------------------
-char = "%c" % num
-print "Number %d is character %c" % (num, num)
-print "Number %(n)d is character %(n)c" % {"n": num}
-print "Number %(num)d is character %(num)c" % locals()
-#=> Number 101 is character e
-#-----------------------------
-ascii_character_numbers = [ord(c) for c in "sample"]
-print ascii_character_numbers
-#=> [115, 97, 109, 112, 108, 101]
-
-word = "".join([chr(n) for n in ascii_character_numbers])
-word = "".join([chr(n) for n in [115, 97, 109, 112, 108, 101]])
-print word
-#=> sample
-#-----------------------------
-hal = "HAL"
-ibm = "".join([chr(ord(c)+1) for c in hal]) # add one to each ASCII value
-print ibm
-#=> IBM
-#-----------------------------
-
-# @@PLEAC@@_1.5
-#-----------------------------
-mylist = list(mystr)
-#-----------------------------
-for char in mystr:
- pass # do something with char
-#-----------------------------
-mystr = "an apple a day"
-uniq = sorted(set(mystr))
-print "unique chars are: '%s'" % "".join(uniq)
-#=> unique chars are: ' adelnpy'
-#-----------------------------
-ascvals = [ord(c) for c in mystr]
-print "total is %s for '%s'."%(sum(ascvals), mystr)
-#=> total is 1248 for 'an apple a day'.
-#-----------------------------
-# sysv checksum
-def checksum(myfile):
- values = [ord(c) for line in myfile for c in line]
- return sum(values)%(2**16) - 1
-
-import fileinput
-print checksum(fileinput.input()) # data from sys.stdin
-
-# Using a function means any iterable can be checksummed:
-print checksum(open("C:/test.txt") # data from file
-print checksum("sometext") # data from string
-#-----------------------------
-#!/usr/bin/python
-# slowcat - emulate a s l o w line printer
-# usage: slowcat [- DELAY] [files ...]
-import sys, select
-import re
-DELAY = 1
-if re.match("^-\d+$",sys.argv[1]):
- DELAY=-int(sys.argv[1])
- del sys.argv[1]
-for ln in fileinput.input():
- for c in ln:
- sys.stdout.write(c)
- sys.stdout.flush()
- select.select([],[],[], 0.005 * DELAY)
-#-----------------------------
-
-# @@PLEAC@@_1.6
-#-----------------------------
-# 2.3+ only
-revchars = mystr[::-1] # extended slice - step is -1
-revwords = " ".join(mystr.split(" ")[::-1])
-
-# pre 2.3 version:
-mylist = list(mystr)
-mylist.reverse()
-revbytes = "".join(mylist)
-
-mylist = mystr.split()
-mylist.reverse()
-revwords = ' '.join(mylist)
-
-# Alternative version using reversed():
-revchars = "".join(reversed(mystr))
-revwords = " ".join(reversed(mystr.split(" ")))
-
-# reversed() makes an iterator, which means that the reversal
-# happens as it is consumed. This means that "print reversed(mystr)" is not
-# the same as mystr[::-1]. Standard usage is:
-for char in reversed(mystr):
- pass # ... do something
-#-----------------------------
-# 2.3+ only
-word = "reviver"
-is_palindrome = (word == word[::-1])
-#-----------------------------
-# Generator version
-def get_palindromes(fname):
- for line in open(fname):
- word = line.rstrip()
- if len(word) > 5 and word == word[::-1]:
- yield word
-long_palindromes = list(get_palindromes("/usr/share/dict/words"))
-
-# Simpler old-style version using 2.2 string reversal
-def rev_string(mystr):
- mylist = list(mystr)
- mylist.reverse()
- return "".join(mylist)
-
-long_palindromes=[]
-for line in open("/usr/share/dict/words"):
- word = line.rstrip()
- if len(word) > 5 and word == rev_string(word):
- long_palindromes.append(word)
-print long_palindromes
-#-----------------------------
-
-# @@PLEAC@@_1.7
-#-----------------------------
-mystr.expandtabs()
-mystr.expandtabs(4)
-#-----------------------------
-
-# @@PLEAC@@_1.8
-#-----------------------------
-text = "I am %(rows)s high and %(cols)s long"%{"rows":24, "cols":80)
-print text
-#=> I am 24 high and 80 long
-
-rows, cols = 24, 80
-text = "I am %(rows)s high and %(cols)s long"%locals()
-print text
-#=> I am 24 high and 80 long
-#-----------------------------
-import re
-print re.sub("\d+", lambda i: str(2 * int(i.group(0))), "I am 17 years old")
-#=> I am 34 years old
-#-----------------------------
-# expand variables in text, but put an error message in
-# if the variable isn't defined
-class SafeDict(dict):
- def __getitem__(self, key):
- return self.get(key, "[No Variable: %s]"%key)
-
-hi = "Hello"
-text = "%(hi)s and %(bye)s!"%SafeDict(locals())
-print text
-#=> Hello and [No Variable: bye]!
-
-#If you don't need a particular error message, just use the Template class:
-from string import Template
-x = Template("$hi and $bye!")
-hi = "Hello"
-print x.safe_substitute(locals())
-#=> Hello and $bye!
-print x.substitute(locals()) # will throw a KeyError
-
-#-----------------------------
-
-# @@PLEAC@@_1.9
-#-----------------------------
-mystr = "bo peep".upper() # BO PEEP
-mystr = mystr.lower() # bo peep
-mystr = mystr.capitalize() # Bo peep
-#-----------------------------
-beast = "python"
-caprest = beast.capitalize().swapcase() # pYTHON
-#-----------------------------
-print "thIS is a loNG liNE".title()
-#=> This Is A Long Line
-#-----------------------------
-if a.upper() == b.upper():
- print "a and b are the same"
-#-----------------------------
-import random
-def randcase_one(letter):
- if random.randint(0,5): # True on 1, 2, 3, 4
- return letter.lower()
- else:
- return letter.upper()
-
-def randcase(myfile):
- for line in myfile:
- yield "".join(randcase_one(letter) for letter in line[:-1])
-
-for line in randcase(myfile):
- print line
-#-----------------------------
-
-# @@PLEAC@@_1.10
-#-----------------------------
-"I have %d guanacos." % (n + 1)
-print "I have", n+1, "guanacos."
-#-----------------------------
-#Python templates disallow in-string calculations (see PEP 292)
-from string import Template
-
-email_template = Template("""\
-To: $address
-From: Your Bank
-CC: $cc_number
-Date: $date
-
-Dear $name,
-
-Today you bounced check number $checknum to us.
-Your account is now closed.
-
-Sincerely,
-the management
-""")
-
-import random
-import datetime
-
-person = {"address":"Joe@somewhere.com",
- "name": "Joe",
- "cc_number" : 1234567890,
- "checknum" : 500+random.randint(0,99)}
-
-print email_template.substitute(person, date=datetime.date.today())
-#-----------------------------
-
-# @@PLEAC@@_1.11
-#-----------------------------
-# indenting here documents
-#
-# in python multiline strings can be used as here documents
-var = """
- your text
- goes here
- """
-
-# using regular expressions
-import re
-re_leading_blanks = re.compile("^\s+",re.MULTILINE)
-var1 = re_leading_blanks.sub("",var)[:-1]
-
-# using string methods
-# split into lines, use every line except first and last, left strip and rejoin.
-var2 = "\n".join([line.lstrip() for line in var.split("\n")[1:-1]])
-
-poem = """
- Here's your poem:
- Now far ahead the Road has gone,
- And I must follow, if I can,
- Pursuing it with eager feet,
- Until it joins some larger way
- Where many paths and errand meet.
- And whither then? I cannot say.
- --Bilbo in /usr/src/perl/pp_ctl.c
- """
-
-import textwrap
-print textwrap.dedent(poem)[1:-1]
-#-----------------------------
-
-
-# @@PLEAC@@_1.12
-#-----------------------------
-from textwrap import wrap
-output = wrap(para,
- initial_indent=leadtab
- subsequent_indent=nexttab)
-#-----------------------------
-#!/usr/bin/env python
-# wrapdemo - show how textwrap works
-
-txt = """\
-Folding and splicing is the work of an editor,
-not a mere collection of silicon
-and
-mobile electrons!
-"""
-
-from textwrap import TextWrapper
-
-wrapper = TextWrapper(width=20,
- initial_indent=" "*4,
- subsequent_indent=" "*2)
-
-print "0123456789" * 2
-print wrapper.fill(txt)
-
-#-----------------------------
-"""Expected result:
-
-01234567890123456789
- Folding and
- splicing is the
- work of an editor,
- not a mere
- collection of
- silicon and mobile
- electrons!
-"""
-
-#-----------------------------
-# merge multiple lines into one, then wrap one long line
-
-from textwrap import fill
-import fileinput
-
-print fill("".join(fileinput.input()))
-
-#-----------------------------
-# Term::ReadKey::GetTerminalSize() isn't in the Perl standard library.
-# It isn't in the Python standard library either. Michael Hudson's
-# recipe from python-list #530228 is shown here.
-# (http://aspn.activestate.com/ASPN/Mail/Message/python-list/530228)
-# Be aware that this will work on Unix but not on Windows.
-
-from termwrap import wrap
-import struct, fcntl
-def getheightwidth():
- height, width = struct.unpack(
- "hhhh", fcntl.ioctl(0, TERMIOS.TIOCGWINSZ ,"\000"*8))[0:2]
- return height, width
-
-# PERL <>, $/, $\ emulation
-import fileinput
-import re
-
-_, width = getheightwidth()
-for para in re.split(r"\n{2,}", "".join(fileinput.input())):
- print fill(para, width)
-
-
-# @@PLEAC@@_1.13
-#-----------------------------
-mystr = '''Mom said, "Don't do that."''' #"
-re.sub("['\"]", lambda i: "\\" + i.group(0), mystr)
-re.sub("[A-Z]", lambda i: "\\" + i.group(0), mystr)
-re.sub("\W", lambda i: "\\" + i.group(0), "is a test!") # no function like quotemeta?
-
-
-# @@PLEAC@@_1.14
-#-----------------------------
-mystr = mystr.lstrip() # left
-mystr = mystr.rstrip() # right
-mystr = mystr.strip() # both ends
-
-
-# @@PLEAC@@_1.15
-#-----------------------------
-import csv
-def parse_csv(line):
- reader = csv.reader([line], escapechar='\\')
- return reader.next()
-
-line = '''XYZZY,"","O'Reilly, Inc","Wall, Larry","a \\"glug\\" bit,",5,"Error, Core Dumped,",''' #"
-
-fields = parse_csv(line)
-
-for i, field in enumerate(fields):
- print "%d : %s" % (i, field)
-
-# pre-2.3 version of parse_csv
-import re
-def parse_csv(text):
- pattern = re.compile('''"([^"\\\]*(?:\\\.[^"\\\]*)*)",?|([^,]+),?|,''')
- mylist = ["".join(elem)
- for elem in re.findall(pattern, text)]
- if text[-1] == ",":
- mylist += ['']
- return mylist
-
-# cvs.reader is meant to work for many lines, something like:
-# (NB: in Python default, quotechar is *not* escaped by backslash,
-# but doubled instead. That's what Excel does.)
-for fields in cvs.reader(lines, dialect="some"):
- for num, field in enumerate(fields):
- print num, ":", field
-#-----------------------------
-
-# @@PLEAC@@_1.16
-#-----------------------------
-def soundex(name, len=4):
- """ soundex module conforming to Knuth's algorithm
- implementation 2000-12-24 by Gregory Jorgensen
- public domain
- """
-
- # digits holds the soundex values for the alphabet
- digits = '01230120022455012623010202'
- sndx = ''
- fc = ''
-
- # translate alpha chars in name to soundex digits
- for c in name.upper():
- if c.isalpha():
- if not fc:
- fc = c # remember first letter
- d = digits[ord(c)-ord('A')]
- # duplicate consecutive soundex digits are skipped
- if not sndx or (d != sndx[-1]):
- sndx += d
-
- # replace first digit with first alpha character
- sndx = fc + sndx[1:]
-
- # remove all 0s from the soundex code
- sndx = sndx.replace('0','')
-
- # return soundex code padded to len characters
- return (sndx + (len * '0'))[:len]
-
-user = raw_input("Lookup user: ")
-if user == "":
- raise SystemExit
-
-name_code = soundex(user)
-for line in open("/etc/passwd"):
- line = line.split(":")
- for piece in line[4].split():
- if name_code == soundex(piece):
- print "%s: %s\n" % line[0], line[4])
-#-----------------------------
-
-# @@PLEAC@@_1.17
-#-----------------------------
-import sys, fileinput, re
-
-data = """\
-analysed => analyzed
-built-in => builtin
-chastized => chastised
-commandline => command-line
-de-allocate => deallocate
-dropin => drop-in
-hardcode => hard-code
-meta-data => metadata
-multicharacter => multi-character
-multiway => multi-way
-non-empty => nonempty
-non-profit => nonprofit
-non-trappable => nontrappable
-pre-define => predefine
-preextend => pre-extend
-re-compiling => recompiling
-reenter => re-enter
-turnkey => turn-key
-"""
-mydict = {}
-for line in data.split("\n"):
- if not line.strip():
- continue
- k, v = [word.strip() for word in line.split("=>")]
- mydict[k] = v
-pattern_text = "(" + "|".join([re.escape(word) for word in mydict.keys()]) + ")"
-pattern = re.compile(pattern_text)
-
-args = sys.argv[1:]
-verbose = 0
-if args and args[0] == "-v":
- verbose = 1
- args = args[1:]
-
-if not args:
- sys.stderr.write("%s: Reading from stdin\n" % sys.argv[0])
-
-for line in fileinput.input(args, inplace=1, backup=".orig"):
- output = ""
- pos = 0
- while True:
- match = pattern.search(line, pos)
- if not match:
- output += line[pos:]
- break
- output += line[pos:match.start(0)] + mydict[match.group(1)]
- pos = match.end(0)
- sys.stdout.write(output)
-#-----------------------------
-
-# @@PLEAC@@_1.18
-#-----------------------------
-#!/usr/bin/python
-# psgrep - print selected lines of ps output by
-# compiling user queries into code.
-#
-# examples :
-# psgrep "uid<10"
-import sys, os, re
-
-class PsLineMatch:
- # each field from the PS header
- fieldnames = ("flags","uid","pid","ppid","pri","nice","size", \
- "rss","wchan","stat","tty","time","command")
- numeric_fields = ("flags","uid","pid","ppid","pri","nice","size","rss")
- def __init__(self):
- self._fields = {}
-
- def new_line(self, ln):
- self._ln = ln.rstrip()
- # ps header for option "wwaxl" (different than in the perl code)
- """
- F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND"
- 004 0 1 0 15 0 448 236 schedu S ? 0:07 init"
- . . . . . . . . . . . . .
- """
- # because only the last entry might contain blanks, splitting
- # is safe
- data = self._ln.split(None,12)
- for fn, elem in zip(self.fieldnames, data):
- if fn in self.numeric_fields: # make numbers integer
- self._fields[fn] = int(elem)
- else:
- self._fields[fn] = elem
-
- def set_query(self, args):
- # assume args: "uid==500", "command ~ ^wm"
- conds=[]
- m = re.compile("(\w+)([=<>]+)(.+)")
- for a in args:
- try:
- (field,op,val) = m.match(a).groups()
- except:
- print "can't understand query \"%s\"" % (a)
- raise SystemExit
- if field in self.numeric_fields:
- conds.append(a)
- else:
- conds.append("%s%s'%s'",(field,op,val))
- self._desirable = compile("(("+")and(".join(conds)+"))", "<string>","eval")
-
- def is_desirable(self):
- return eval(self._desirable, {}, self._fields)
-
- def __str__(self):
- # to allow "print".
- return self._ln
-
-if len(sys.argv)<=1:
- print """usage: %s criterion ...
- Each criterion is a Perl expression involving:
- %s
- All criteria must be met for a line to be printed.""" \
- % (sys.argv[0], " ".join(PsLineMatch().fieldnames))
- raise SystemExit
-
-psln = PsLineMatch()
-psln.set_query(sys.argv[1:])
-p = os.popen("ps wwaxl")
-print p.readline()[:-1] # emit header line
-for ln in p.readlines():
- psln.new_line(ln)
- if psln.is_desirable():
- print psln
-p.close()
-
-# alternatively one could consider every argument being a string and
-# support wildcards: "uid==500" "command~^wm" by means of re, but this
-# does not show dynamic python code generation, although re.compile
-# also precompiles.
-#-----------------------------
-
-
-# @@PLEAC@@_2.1
-#-----------------------------
-# The standard way of validating numbers is to convert them and catch
-# an exception on failure
-
-try:
- myfloat = float(mystr)
- print "is a decimal number"
-except TypeError:
- print "is not a decimal number"
-
-try:
- myint = int(mystr)
- print "is an integer"
-except TypeError:
- print "is not an integer"
-
-# DON'T DO THIS. Explicit checking is prone to errors:
-if mystr.isdigit(): # Fails on "+4"
- print 'is a positive integer'
-else:
- print 'is not'
-
-if re.match("[+-]?\d+$", mystr): # Fails on "- 1"
- print 'is an integer'
-else:
- print 'is not'
-
-if re.match("-?(?:\d+(?:\.\d*)?|\.\d+)$", mystr): # Opaque, and fails on "- 1"
- print 'is a decimal number'
-else:
- print 'is not'
-
-#-----------------------------
-
-# @@PLEAC@@_2.2
-#-----------------------------
-# equal(num1, num2, accuracy) : returns true if num1 and num2 are
-# equal to accuracy number of decimal places
-
-def equal(num1, num2, accuracy):
- return abs(num1 - num2) < 10**(-accuracy)
-#-----------------------------
-from __future__ import division # use / for float div and // for int div
-
-wage = 536 # $5.36/hour
-week = 40 * wage # $214.40
-print "One week's wage is: $%.2f" % (week/100)
-#=> One week's wage is: $214.40
-#-----------------------------
-
-# @@PLEAC@@_2.3
-#-----------------------------
-rounded = round(num) # rounds to integer
-#-----------------------------
-a = 0.255
-b = "%.2f" % a
-print "Unrounded: %f\nRounded: %s" % (a, b)
-print "Unrounded: %f\nRounded: %.2f" % (a, a)
-#=> Unrounded: 0.255000
-#=> Rounded: 0.26
-#=> Unrounded: 0.255000
-#=> Rounded: 0.26
-#-----------------------------
-from math import floor, ceil
-
-print "number\tint\tfloor\tceil"
-a = [3.3, 3.5, 3.7, -3.3]
-for n in a:
- print "% .1f\t% .1f\t% .1f\t% .1f" % (n, int(n), floor(n), ceil(n))
-#=> number int floor ceil
-#=> 3.3 3.0 3.0 4.0
-#=> 3.5 3.0 3.0 4.0
-#=> 3.7 3.0 3.0 4.0
-#=> -3.3 -3.0 -4.0 -3.0
-#-----------------------------
-
-# @@PLEAC@@_2.4
-#-----------------------------
-# To convert a string in any base up to base 36, use the optional arg to int():
-num = int('0110110', 2) # num is 54
-
-# To convert an int to an string representation in another base, you could use
-# <http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/111286>:
-import baseconvert
-def dec2bin(i):
- return baseconvert.baseconvert(i, baseconvert.BASE10, baseconvert.BASE2)
-
-binstr = dec2bin(54) # binstr is 110110
-#-----------------------------
-
-# @@PLEAC@@_2.5
-#-----------------------------
-for i in range(x,y):
- pass # i is set to every integer from x to y, excluding y
-
-for i in range(x, y, 7):
- pass # i is set to every integer from x to y, stepsize = 7
-
-print "Infancy is:",
-for i in range(0,3):
- print i,
-print
-
-print "Toddling is:",
-for i in range(3,5):
- print i,
-print
-
-# DON'T DO THIS:
-print "Childhood is:",
-i = 5
-while i <= 12:
- print i
- i += 1
-
-#=> Infancy is: 0 1 2
-#=> Toddling is: 3 4
-#=> Childhood is: 5 6 7 8 9 10 11 12
-#-----------------------------
-
-# @@PLEAC@@_2.6
-#-----------------------------
-# See http://www.faqts.com/knowledge_base/view.phtml/aid/4442
-# for a module that does this
-#-----------------------------
-
-# @@PLEAC@@_2.7
-#-----------------------------
-import random # use help(random) to see the (large) list of funcs
-
-rand = random.randint(x, y)
-#-----------------------------
-rand = random.randint(25, 76)
-print rand
-#-----------------------------
-elt = random.choice(mylist)
-#-----------------------------
-import string
-chars = string.letters + string.digits + "!@$%^&*"
-password = "".join([random.choice(chars) for i in range(8)])
-#-----------------------------
-
-# @@PLEAC@@_2.8
-#-----------------------------
-# Changes the default RNG
-random.seed()
-
-# Or you can create independent RNGs
-gen1 = random.Random(6)
-gen2 = random.Random(6)
-gen3 = random.Random(10)
-a1, b1 = gen1.random(), gen1.random()
-a2, b2 = gen2.random(), gen2.random()
-a3, b3 = gen3.random(), gen3.random()
-# a1 == a2 and b1 == b2
-#-----------------------------
-
-# @@PLEAC@@_2.9
-#-----------------------------
-# see http://www.sbc.su.se/~per/crng/ or http://www.frohne.westhost.com/rv11reference.htm
-#-----------------------------
-
-# @@PLEAC@@_2.10
-#-----------------------------
-import random
-mean = 25
-sdev = 2
-salary = random.gauss(mean, sdev)
-print "You have been hired at %.2f" % salary
-#-----------------------------
-
-# @@PLEAC@@_2.11
-#-----------------------------
-radians = math.radians(degrees)
-degrees = math.degrees(radians)
-
-# pre-2.3:
-from __future__ import division
-import math
-def deg2rad(degrees):
- return (degrees / 180) * math.pi
-def rad2deg(radians):
- return (radians / math.pi) * 180
-#-----------------------------
-# Use deg2rad instead of math.radians if you have pre-2.3 Python.
-import math
-def degree_sine(degrees):
- radians = math.radians(degrees)
- return math.sin(radians)
-#-----------------------------
-
-# @@PLEAC@@_2.12
-#-----------------------------
-import math
-
-# DON'T DO THIS. Use math.tan() instead.
-def tan(theta):
- return math.sin(theta) / math.cos(theta)
-#----------------
-# NOTE: this sets y to 16331239353195370.0
-try:
- y = math.tan(math.pi/2)
-except ValueError:
- y = None
-#-----------------------------
-
-# @@PLEAC@@_2.13
-#-----------------------------
-import math
-log_e = math.log(VALUE)
-#-----------------------------
-log_10 = math.log10(VALUE)
-#-----------------------------
-def log_base(base, value):
- return math.log(value) / math.log(base)
-#-----------------------------
-# log_base defined as above
-answer = log_base(10, 10000)
-print "log10(10,000) =", answer
-#=> log10(10,000) = 4.0
-#-----------------------------
-
-# @@PLEAC@@_2.14
-#-----------------------------
-# NOTE: must have NumPy installed. See
-# http://www.pfdubois.com/numpy/
-
-import Numeric
-a = Numeric.array( ((3, 2, 3),
- (5, 9, 8) ), "d")
-b = Numeric.array( ((4, 7),
- (9, 3),
- (8, 1) ), "d")
-c = Numeric.matrixmultiply(a, b)
-
-print c
-#=> [[ 54. 30.]
-#=> [ 165. 70.]]
-
-print a.shape, b.shape, c.shape
-#=> (2, 3) (3, 2) (2, 2)
-#-----------------------------
-
-# @@PLEAC@@_2.15
-#-----------------------------
-a = 3+5j
-b = 2-2j
-c = a * b
-print "c =", c
-#=> c = (16+4j)
-
-print c.real, c.imag, c.conjugate()
-#=> 16.0 4.0 (16-4j)
-#-----------------------------
-import cmath
-print cmath.sqrt(3+4j)
-#=> (2+1j)
-#-----------------------------
-
-# @@PLEAC@@_2.16
-#-----------------------------
-number = int(hexadecimal, 16)
-number = int(octal, 8)
-s = hex(number)
-s = oct(number)
-
-num = raw_input("Gimme a number in decimal, octal, or hex: ").rstrip()
-if num.startswith("0x"):
- num = int(num[2:], 16)
-elif num.startswith("0"):
- num = int(num[1:], 8)
-else:
- num = int(num)
-print "%(num)d %(num)x %(num)o\n" % { "num": num }
-#-----------------------------
-
-
-# @@PLEAC@@_2.17
-#-----------------------------
-def commify(amount):
- amount = str(amount)
- firstcomma = len(amount)%3 or 3 # set to 3 if would make a leading comma
- first, rest = amount[:firstcomma], amount[firstcomma:]
- segments = [first] + [rest[i:i+3] for i in range(0, len(rest), 3)]
- return ",".join(segments)
-
-print commify(12345678)
-#=> 12,345,678
-
-# DON'T DO THIS. It works on 2.3+ only and is slower and less straightforward
-# than the non-regex version above.
-import re
-def commify(amount):
- amount = str(amount)
- amount = amount[::-1]
- amount = re.sub(r"(\d\d\d)(?=\d)(?!\d*\.)", r"\1,", amount)
- return amount[::-1]
-
-# @@PLEAC@@_2.18
-# Printing Correct Plurals
-#-----------------------------
-def pluralise(value, root, singular="", plural="s"):
- if value == 1:
- return root + singular
- else:
- return root + plural
-
-print "It took", duration, pluralise(duration, 'hour')
-
-print "%d %s %s enough." % (duration,
- pluralise(duration, 'hour'),
- pluralise(duration, '', 'is', 'are'))
-#-----------------------------
-import re
-def noun_plural(word):
- endings = [("ss", "sses"),
- ("([psc]h)", r"\1es"),
- ("z", "zes"),
- ("ff", "ffs"),
- ("f", "ves"),
- ("ey", "eys"),
- ("y", "ies"),
- ("ix", "ices"),
- ("([sx])", r"\1es"),
- ("", "s")]
- for singular, plural in endings:
- ret, found = re.subn("%s$"%singular, plural, word)
- if found:
- return ret
-
-verb_singular = noun_plural; # make function alias
-#-----------------------------
-
-# @@PLEAC@@_2.19
-# Program: Calculating Prime Factors
-#-----------------------------
-#% bigfact 8 9 96 2178
-#8 2**3
-#
-#9 3**2
-#
-#96 2**5 3
-#
-#2178 2 3**2 11**2
-#-----------------------------
-#% bigfact 239322000000000000000000
-#239322000000000000000000 2**19 3 5**18 39887
-#
-#
-#% bigfact 25000000000000000000000000
-#25000000000000000000000000 2**24 5**26
-#-----------------------------
-import sys
-
-def factorise(num):
- factors = {}
- orig = num
- print num, '\t',
-
- # we take advantage of the fact that (i +1)**2 = i**2 + 2*i +1
- i, sqi = 2, 4
- while sqi <= num:
- while not num%i:
- num /= i
- factors[i] = factors.get(i, 0) + 1
-
- sqi += 2*i + 1
- i += 1
-
- if num != 1 and num != orig:
- factors[num] = factors.get(num, 0) + 1
-
- if not factors:
- print "PRIME"
-
- for factor in sorted(factors):
- if factor:
- tmp = str(factor)
- if factors[factor]>1: tmp += "**" + str(factors[factor])
- print tmp,
- print
-
-#--------
-if __name__ == '__main__':
- if len(sys.argv) == 1:
- print "Usage:", sys.argv[0], " number [number, ]"
- else:
- for strnum in sys.argv[1:]:
- try:
- num = int(strnum)
- factorise(num)
- except ValueError:
- print strnum, "is not an integer"
-#-----------------------------
-# A more Pythonic variant (which separates calculation from printing):
-def format_factor(base, exponent):
- if exponent > 1:
- return "%s**%s"%(base, exponent)
- return str(base)
-
-def factorise(num):
- factors = {}
- orig = num
-
- # we take advantage of the fact that (i+1)**2 = i**2 + 2*i +1
- i, sqi = 2, 4
- while sqi <= num:
- while not num%i:
- num /= i
- factors[i] = factors.get(i, 0) + 1
- sqi += 2*i + 1
- i += 1
-
- if num not in (1, orig):
- factors[num] = factors.get(num, 0) + 1
-
- if not factors:
- return ["PRIME"]
-
- out = [format_factor(base, exponent)
- for base, exponent in sorted(factors.items())]
- return out
-
-def print_factors(value):
- try:
- num = int(value)
- if num != float(value):
- raise ValueError
- except (ValueError, TypeError):
- raise ValueError("Can only factorise an integer")
- factors = factorise(num)
- print num, "\t", " ".join(factors)
-
-# @@PLEAC@@_3.0
-#-----------------------------
-#introduction
-# There are three common ways of manipulating dates in Python
-# mxDateTime - a popular third-party module (not discussed here)
-# time - a fairly low-level standard library module
-# datetime - a new library module for Python 2.3 and used for most of these samples
-# (I will use full names to show which module they are in, but you can also use
-# from datetime import datetime, timedelta and so on for convenience)
-
-import time
-import datetime
-
-print "Today is day", time.localtime()[7], "of the current year"
-# Today is day 218 of the current year
-
-today = datetime.date.today()
-print "Today is day", today.timetuple()[7], "of ", today.year
-# Today is day 218 of 2003
-
-print "Today is day", today.strftime("%j"), "of the current year"
-# Today is day 218 of the current year
-
-
-# @@PLEAC@@_3.1
-#-----------------------------
-# Finding todays date
-
-today = datetime.date.today()
-print "The date is", today
-#=> The date is 2003-08-06
-
-# the function strftime() (string-format time) produces nice formatting
-# All codes are detailed at http://www.python.org/doc/current/lib/module-time.html
-print t.strftime("four-digit year: %Y, two-digit year: %y, month: %m, day: %d")
-#=> four-digit year: 2003, two-digit year: 03, month: 08, day: 06
-
-
-# @@PLEAC@@_3.2
-#-----------------------------
-# Converting DMYHMS to Epoch Seconds
-# To work with Epoch Seconds, you need to use the time module
-
-# For the local timezone
-t = datetime.datetime.now()
-print "Epoch Seconds:", time.mktime(t.timetuple())
-#=> Epoch Seconds: 1060199000.0
-
-# For UTC
-t = datetime.datetime.utcnow()
-print "Epoch Seconds:", time.mktime(t.timetuple())
-#=> Epoch Seconds: 1060195503.0
-
-
-# @@PLEAC@@_3.3
-#-----------------------------
-# Converting Epoch Seconds to DMYHMS
-
-now = datetime.datetime.fromtimestamp(EpochSeconds)
-#or use datetime.datetime.utcfromtimestamp()
-print now
-#=> datetime.datetime(2003, 8, 6, 20, 43, 20)
-print now.ctime()
-#=> Wed Aug 6 20:43:20 2003
-
-# or with the time module
-oldtimetuple = time.localtime(EpochSeconds)
-# oldtimetuple contains (year, month, day, hour, minute, second, weekday, yearday, daylightSavingAdjustment)
-print oldtimetuple
-#=> (2003, 8, 6, 20, 43, 20, 2, 218, 1)
-
-
-# @@PLEAC@@_3.4
-#-----------------------------
-# Adding to or Subtracting from a Date
-# Use the rather nice datetime.timedelta objects
-
-now = datetime.date(2003, 8, 6)
-difference1 = datetime.timedelta(days=1)
-difference2 = datetime.timedelta(weeks=-2)
-
-print "One day in the future is:", now + difference1
-#=> One day in the future is: 2003-08-07
-
-print "Two weeks in the past is:", now + difference2
-#=> Two weeks in the past is: 2003-07-23
-
-print datetime.date(2003, 8, 6) - datetime.date(2000, 8, 6)
-#=> 1095 days, 0:00:00
-
-#-----------------------------
-birthtime = datetime.datetime(1973, 01, 18, 3, 45, 50) # 1973-01-18 03:45:50
-
-interval = datetime.timedelta(seconds=5, minutes=17, hours=2, days=55)
-then = birthtime + interval
-
-print "Then is", then.ctime()
-#=> Then is Wed Mar 14 06:02:55 1973
-
-print "Then is", then.strftime("%A %B %d %I:%M:%S %p %Y")
-#=> Then is Wednesday March 14 06:02:55 AM 1973
-
-#-----------------------------
-when = datetime.datetime(1973, 1, 18) + datetime.timedelta(days=55)
-print "Nat was 55 days old on:", when.strftime("%m/%d/%Y").lstrip("0")
-#=> Nat was 55 days old on: 3/14/1973
-
-
-# @@PLEAC@@_3.5
-#-----------------------------
-# Dates produce timedeltas when subtracted.
-
-diff = date2 - date1
-diff = datetime.date(year1, month1, day1) - datetime.date(year2, month2, day2)
-#-----------------------------
-
-bree = datetime.datetime(1981, 6, 16, 4, 35, 25)
-nat = datetime.datetime(1973, 1, 18, 3, 45, 50)
-
-difference = bree - nat
-print "There were", difference, "minutes between Nat and Bree"
-#=> There were 3071 days, 0:49:35 between Nat and Bree
-
-weeks, days = divmod(difference.days, 7)
-
-minutes, seconds = divmod(difference.seconds, 60)
-hours, minutes = divmod(minutes, 60)
-
-print "%d weeks, %d days, %d:%d:%d" % (weeks, days, hours, minutes, seconds)
-#=> 438 weeks, 5 days, 0:49:35
-
-#-----------------------------
-print "There were", difference.days, "days between Bree and Nat."
-#=> There were 3071 days between bree and nat
-
-
-# @@PLEAC@@_3.6
-#-----------------------------
-# Day in a Week/Month/Year or Week Number
-
-when = datetime.date(1981, 6, 16)
-
-print "16/6/1981 was:"
-print when.strftime("Day %w of the week (a %A). Day %d of the month (%B).")
-print when.strftime("Day %j of the year (%Y), in week %W of the year.")
-
-#=> 16/6/1981 was:
-#=> Day 2 of the week (a Tuesday). Day 16 of the month (June).
-#=> Day 167 of the year (1981), in week 24 of the year.
-
-
-# @@PLEAC@@_3.7
-#-----------------------------
-# Parsing Dates and Times from Strings
-
-time.strptime("Tue Jun 16 20:18:03 1981")
-# (1981, 6, 16, 20, 18, 3, 1, 167, -1)
-
-time.strptime("16/6/1981", "%d/%m/%Y")
-# (1981, 6, 16, 0, 0, 0, 1, 167, -1)
-# strptime() can use any of the formatting codes from time.strftime()
-
-# The easiest way to convert this to a datetime seems to be;
-now = datetime.datetime(*time.strptime("16/6/1981", "%d/%m/%Y")[0:5])
-# the '*' operator unpacks the tuple, producing the argument list.
-
-
-# @@PLEAC@@_3.8
-#-----------------------------
-# Printing a Date
-# Use datetime.strftime() - see helpfiles in distro or at python.org
-
-print datetime.datetime.now().strftime("The date is %A (%a) %d/%m/%Y")
-#=> The date is Friday (Fri) 08/08/2003
-
-# @@PLEAC@@_3.9
-#-----------------------------
-# High Resolution Timers
-
-t1 = time.clock()
-# Do Stuff Here
-t2 = time.clock()
-print t2 - t1
-
-# 2.27236813618
-# Accuracy will depend on platform and OS,
-# but time.clock() uses the most accurate timer it can
-
-time.clock(); time.clock()
-# 174485.51365466841
-# 174485.55702610247
-
-#-----------------------------
-# Also useful;
-import timeit
-code = '[x for x in range(10) if x % 2 == 0]'
-eval(code)
-# [0, 2, 4, 6, 8]
-
-t = timeit.Timer(code)
-print "10,000 repeats of that code takes:", t.timeit(10000), "seconds"
-print "1,000,000 repeats of that code takes:", t.timeit(), "seconds"
-
-# 10,000 repeats of that code takes: 0.128238644856 seconds
-# 1,000,000 repeats of that code takes: 12.5396490336 seconds
-
-#-----------------------------
-import timeit
-code = 'import random; l = random.sample(xrange(10000000), 1000); l.sort()'
-t = timeit.Timer(code)
-
-print "Create a list of a thousand random numbers. Sort the list. Repeated a thousand times."
-print "Average Time:", t.timeit(1000) / 1000
-# Time taken: 5.24391507859
-
-
-# @@PLEAC@@_3.10
-#-----------------------------
-# Short Sleeps
-
-seconds = 3.1
-time.sleep(seconds)
-print "boo"
-
-# @@PLEAC@@_3.11
-#-----------------------------
-# Program HopDelta
-# Save a raw email to disk and run "python hopdelta.py FILE"
-# and it will process the headers and show the time taken
-# for each server hop (nb: if server times are wrong, negative dates
-# might appear in the output).
-
-import datetime, email, email.Utils
-import os, sys, time
-
-def extract_date(hop):
- # According to RFC822, the date will be prefixed with
- # a semi-colon, and is the last part of a received
- # header.
- date_string = hop[hop.find(';')+2:]
- date_string = date_string.strip()
- time_tuple = email.Utils.parsedate(date_string)
-
- # convert time_tuple to datetime
- EpochSeconds = time.mktime(time_tuple)
- dt = datetime.datetime.fromtimestamp(EpochSeconds)
- return dt
-
-def process(filename):
- # Main email file processing
- # read the headers and process them
- f = file(filename, 'rb')
- msg = email.message_from_file(f)
-
- hops = msg.get_all('received')
-
- # in reverse order, get the server(s) and date/time involved
- hops.reverse()
- results = []
- for hop in hops:
- hop = hop.lower()
-
- if hop.startswith('by'): # 'Received: by' line
- sender = "start"
- receiver = hop[3:hop.find(' ',3)]
- date = extract_date(hop)
-
- else: # 'Received: from' line
- sender = hop[5:hop.find(' ',5)]
- by = hop.find('by ')+3
- receiver = hop[by:hop.find(' ', by)]
- date = extract_date(hop)
-
- results.append((sender, receiver, date))
- output(results)
-
-def output(results):
- print "Sender, Recipient, Time, Delta"
- print
- previous_dt = delta = 0
- for (sender, receiver, date) in results:
- if previous_dt:
- delta = date - previous_dt
-
- print "%s, %s, %s, %s" % (sender,
- receiver,
- date.strftime("%Y/%d/%m %H:%M:%S"),
- delta)
- print
- previous_dt = date
-
-def main():
- # Perform some basic argument checking
- if len(sys.argv) != 2:
- print "Usage: mailhop.py FILENAME"
-
- else:
- filename = sys.argv[1]
- if os.path.isfile(filename):
- process(filename)
- else:
- print filename, "doesn't seem to be a valid file."
-
-if __name__ == '__main__':
- main()
-
-
-# @@PLEAC@@_4.0
-#-----------------------------
-# Python does not automatically flatten lists, in other words
-# in the following, non-nested contains four elements and
-# nested contains three elements, the third element of which
-# is itself a list containing two elements:
-non_nested = ["this", "that", "the", "other"]
-nested = ["this", "that", ["the", "other"]]
-#-----------------------------
-tune = ["The", "Star-Spangled", "Banner"]
-#-----------------------------
-
-# @@PLEAC@@_4.1
-#-----------------------------
-a = ["quick", "brown", "fox"]
-a = "Why are you teasing me?".split()
-
-text = """
- The boy stood on the burning deck,
- It was as hot as glass.
-"""
-lines = [line.lstrip() for line in text.strip().split("\n")]
-#-----------------------------
-biglist = [line.rstrip() for line in open("mydatafile")]
-#-----------------------------
-banner = "The Mines of Moria"
-banner = 'The Mines of Moria'
-#-----------------------------
-name = "Gandalf"
-banner = "Speak, " + name + ", and enter!"
-banner = "Speak, %s, and welcome!" % name
-#-----------------------------
-his_host = "www.python.org"
-import os
-host_info = os.popen("nslookup " + his_host).read()
-
-# NOTE: not really relevant to Python (no magic '$$' variable)
-python_info = os.popen("ps %d" % os.getpid()).read()
-shell_info = os.popen("ps $$").read()
-#-----------------------------
-# NOTE: not really relevant to Python (no automatic interpolation)
-banner = ["Costs", "only", "$4.95"]
-banner = "Costs only $4.95".split()
-#-----------------------------
-brax = """ ' " ( ) < > { } [ ] """.split() #"""
-brax = list("""'"()<>{}[]""") #"""
-rings = '''They're "Nenya Narya Vilya"'''.split() #'''
-tags = 'LI TABLE TR TD A IMG H1 P'.split()
-sample = r'The backslash (\) is often used in regular expressions.'.split()
-
-#-----------------------------
-banner = "The backslash (\\) is often used in regular expressions.".split()
-#-----------------------------
-ships = u"Niña Pinta Santa María".split() # WRONG (only three ships)
-ships = [u"Niña", u"Pinta", u"Santa María"] # right
-#-----------------------------
-
-# @@PLEAC@@_4.2
-#-----------------------------
-def commify_series(args):
- n = len(args)
- if n == 0:
- return ""
- elif n == 1:
- return args[0]
- elif n == 2:
- return args[0] + " and " + args[1]
- return ", ".join(args[:-1]) + ", and " + args[-1]
-
-commify_series([])
-commify_series(["red"])
-commify_series(["red", "yellow"])
-commify_series(["red", "yellow", "green"])
-#-----------------------------
-mylist = ["red", "yellow", "green"]
-print "I have", mylist, "marbles."
-print "I have", " ".join(mylist), "marbles."
-#=> I have ['red', 'yellow', 'green'] marbles.
-#=> I have red yellow green marbles.
-
-#-----------------------------
-#!/usr/bin/env python
-# commify_series - show proper comma insertion in list output
-data = (
- ( 'just one thing', ),
- ( 'Mutt Jeff'.split() ),
- ( 'Peter Paul Mary'.split() ),
- ( 'To our parents', 'Mother Theresa', 'God' ),
- ( 'pastrami', 'ham and cheese', 'peanut butter and jelly', 'tuna' ),
- ( 'recycle tired, old phrases', 'ponder big, happy thoughts' ),
- ( 'recycle tired, old phrases',
- 'ponder big, happy thoughts',
- 'sleep and dream peacefully' ),
- )
-
-def commify_series(terms):
- for term in terms:
- if "," in term:
- sepchar = "; "
- break
- else:
- sepchar = ", "
-
- n = len(terms)
- if n == 0:
- return ""
- elif n == 1:
- return terms[0]
- elif n == 2:
- return " and ".join(terms)
- return "%s%sand %s" % (sepchar.join(terms[:-1]), sepchar, terms[-1])
-
-for item in data:
- print "The list is: %s." % commify_series(item)
-
-#=> The list is: just one thing.
-#=> The list is: Mutt and Jeff.
-#=> The list is: Peter, Paul, and Mary.
-#=> The list is: To our parents, Mother Theresa, and God.
-#=> The list is: pastrami, ham and cheese, peanut butter and jelly, and tuna.
-#=> The list is: recycle tired, old phrases and ponder big, happy thoughts.
-#=> The list is: recycle tired, old phrases; ponder big, happy thoughts; and
-# sleep and dream peacefully.
-#-----------------------------
-
-# @@PLEAC@@_4.3
-#-----------------------------
-# Python allocates more space than is necessary every time a list needs to
-# grow and only shrinks lists when more than half the available space is
-# unused. This means that adding or removing an element will in most cases
-# not force a reallocation.
-
-del mylist[size:] # shrink mylist
-mylist += [None] * size # grow mylist by appending 'size' None elements
-
-# To add an element to the end of a list, use the append method:
-mylist.append(4)
-
-# To insert an element, use the insert method:
-mylist.insert(0, 10) # Insert 10 at the beginning of the list
-
-# To extend one list with the contents of another, use the extend method:
-list2 = [1,2,3]
-mylist.extend(list2)
-
-# To insert the contents of one list into another, overwriting zero or
-# more elements, specify a slice:
-mylist[1:1] = list2 # Don't overwrite anything; grow mylist if needed
-mylist[2:3] = list2 # Overwrite mylist[2] and grow mylist if needed
-
-# To remove one element from the middle of a list:
-# To remove elements from the middle of a list:
-del mylist[idx1:idx2] # 0 or more
-x = mylist.pop(idx) # remove mylist[idx] and assign it to x
-
-# You cannot assign to or get a non-existent element:
-# >>> x = []
-# >>> x[4] = 5
-#
-# Traceback (most recent call last):
-# File "<pyshell#1>", line 1, in -toplevel-
-# x[4] = 5
-# IndexError: list assignment index out of range
-#
-# >>> print x[1000]
-#
-# Traceback (most recent call last):
-# File "<pyshell#16>", line 1, in -toplevel-
-# print x[1000]
-# IndexError: list index out of range
-#-----------------------------
-def what_about_that_list(terms):
- print "The list now has", len(terms), "elements."
- print "The index of the last element is", len(terms)-1, "(or -1)."
- print "Element #3 is %s." % terms[3]
-
-people = "Crosby Stills Nash Young".split()
-what_about_that_list(people)
-#-----------------------------
-#=> The list now has 4 elements.
-#=> The index of the last element is 3 (or -1).
-#=> Element #3 is Young.
-#-----------------------------
-people.pop()
-what_about_that_list(people)
-#-----------------------------
-people += [None] * (10000 - len(people))
-#-----------------------------
-#>>> people += [None] * (10000 - len(people))
-#>>> what_about_that_list(people)
-#The list now has 10000 elements.
-#The index of the last element is 9999 (or -1).
-#Element #3 is None.
-#-----------------------------
-
-# @@PLEAC@@_4.4
-#-----------------------------
-for item in mylist:
- pass # do something with item
-#-----------------------------
-for user in bad_users:
- complain(user)
-#-----------------------------
-import os
-for (key, val) in sorted(os.environ.items()):
- print "%s=%s" % (key, val)
-#-----------------------------
-for user in all_users:
- disk_space = get_usage(user) # find out how much disk space in use
- if disk_space > MAX_QUOTA: # if it's more than we want ...
- complain(user) # ... then object vociferously
-#-----------------------------
-import os
-for line in os.popen("who"):
- if "dalke" in line:
- print line, # or print line[:-1]
-
-# or:
-print "".join([line for line in os.popen("who")
- if "dalke" in line]),
-
-#-----------------------------
-for line in myfile:
- for word in line.split(): # Split on whitespace
- print word[::-1], # reverse word
- print
-
-# pre 2.3:
-for line in myfile:
- for word in line.split(): # Split on whitespace
- chars = list(word) # Turn the string into a list of characters
- chars.reverse()
- print "".join(chars),
- print
-#-----------------------------
-for item in mylist:
- print "i =", item
-#-----------------------------
-# NOTE: you can't modify in place the way Perl does:
-# data = [1, 2, 3]
-# for elem in data:
-# elem -= 1
-#print data
-#=>[1, 2, 3]
-
-data = [1, 2, 3]
-data = [i-1 for i in data]
-print data
-#=>[0, 1, 2]
-
-# or
-for i, elem in enumerate(data):
- data[i] = elem - 1
-#-----------------------------
-# NOTE: strings are immutable in Python so this doesn't translate well.
-s = s.strip()
-data = [s.strip() for s in data]
-for k, v in mydict.items():
- mydict[k] = v.strip()
-#-----------------------------
-
-# @@PLEAC@@_4.5
-#-----------------------------
-fruits = ["Apple", "Blackberry"]
-for fruit in fruits:
- print fruit, "tastes good in a pie."
-#=> Apple tastes good in a pie.
-#=> Blackberry tastes good in a pie.
-#-----------------------------
-# DON'T DO THIS:
-for i in range(len(fruits)):
- print fruits[i], "tastes good in a pie."
-
-# If you must explicitly index, use enumerate():
-for i, fruit in enumerate(fruits):
- print "%s) %s tastes good in a pie."%(i+1, fruit)
-#-----------------------------
-rogue_cats = ["Morris", "Felix"]
-namedict = { "felines": rogue_cats }
-for cat in namedict["felines"]:
- print cat, "purrs hypnotically."
-print "--More--\nYou are controlled."
-#-----------------------------
-# As noted before, if you need an index, use enumerate() and not this:
-for i in range(len(namedict["felines"])):
- print namedict["felines"][i], "purrs hypnotically."
-#-----------------------------
-
-# @@PLEAC@@_4.6
-#-----------------------------
-uniq = list(set(mylist))
-#-----------------------------
-# See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/259174
-# for a more heavyweight version of a bag
-seen = {}
-for item in mylist:
- seen[item] = seen.get(item, 0) + 1
-
-uniq = seen.keys()
-#-----------------------------
-seen = {}
-uniq = []
-for item in mylist:
- count = seen.get(item, 0)
- if count == 0:
- uniq.append(item)
- seen[item] = count + 1
-#-----------------------------
-# generate a list of users logged in, removing duplicates
-import os
-usernames = [line.split()[0] for line in os.popen("who")]
-uniq = sorted(set(usernames))
-print "users logged in:", " ".join(uniq)
-
-# DON'T DO THIS:
-import os
-ucnt = {}
-for line in os.popen("who"):
- username = line.split()[0] # Get the first word
- ucnt[username] = ucnt.get(username, 0) + 1 # record the users' presence
-
-# extract and print unique keys
-users = ucnt.keys()
-users.sort()
-print "users logged in:", " ".join(users)
-#-----------------------------
-
-# @@PLEAC@@_4.7
-#-----------------------------
-# assume a_list and b_list are already loaded
-aonly = [item for item in a_list if item not in b_list]
-
-# A slightly more complex Pythonic version using sets - if you had a few
-# lists, subtracting sets would be clearer than the listcomp version above
-a_set = set(a_list)
-b_set = set(b_list)
-aonly = list(a_set - b_set) # Elements in a_set but not in b_set
-
-# DON'T DO THIS.
-seen = {} # lookup table to test membership of B
-aonly = [] # answer
-
-# build lookup table
-for item in b_list:
- seen[item] = 1
-
-# find only elements in a_list and not in b_list
-for item in a_list:
- if not item not in seen:
- # it's not in 'seen', so add to 'aonly'
- aonly.append(item)
-#-----------------------------
-# DON'T DO THIS. There's lots of ways not to do it.
-seen = {} # lookup table
-aonly = [] # answer
-
-# build lookup table - unnecessary and poor Python style
-[seen.update({x: 1}) for x in b_list]
-
-aonly = [item for item in a_list if item not in seen]
-
-#-----------------------------
-aonly = list(set(a_list))
-
-# DON'T DO THIS.
-seen = {}
-aonly = []
-for item in a_list:
- if item not in seen:
- aonly.append(item)
- seen[item] = 1 # mark as seen
-#-----------------------------
-mydict["key1"] = 1
-mydict["key2"] = 2
-#-----------------------------
-mydict[("key1", "key2")] = (1,2)
-#-----------------------------
-# DON'T DO THIS:
-seen = dict.fromkeys(B.keys())
-
-# DON'T DO THIS pre-2.3:
-seen = {}
-for term in B:
- seen[term] = None
-#-----------------------------
-# DON'T DO THIS:
-seen = {}
-for k, v in B:
- seen[k] = 1
-#-----------------------------
-
-# @@PLEAC@@_4.8
-#-----------------------------
-a = (1, 3, 5, 6, 7, 8)
-b = (2, 3, 5, 7, 9)
-
-a_set = set(a)
-b_set = set(b)
-
-union = a_set | b_set # or a_set.union(b_set)
-isect = a_set & b_set # or a_set.intersection(b_set)
-diff = a_set ^ b_set # or a_set.symmetric_difference(b_set)
-
-
-# DON'T DO THIS:
-union_list = []; isect_list = []; diff = []
-union_dict = {}; isect_dict = {}
-count = {}
-#-----------------------------
-# DON'T DO THIS:
-for e in a:
- union_dict[e] = 1
-
-for e in b:
- if union_dict.has_key(e):
- isect_dict[e] = 1
- union_dict[e] = 1
-
-union_list = union_dict.keys()
-isect_list = isect_dict.keys()
-#-----------------------------
-# DON'T DO THIS:
-for e in a + b:
- if union.get(e, 0) == 0:
- isect[e] = 1
- union[e] = 1
-
-union = union.keys()
-isect = isect.keys()
-#-----------------------------
-# DON'T DO THIS:
-count = {}
-for e in a + b:
- count[e] = count.get(e, 0) + 1
-
-union = []; isect = []; diff = []
-
-for e in count.keys():
- union.append(e)
- if count[e] == 2:
- isect.append(e)
- else:
- diff.append(e)
-#-----------------------------
-# DON'T DO THIS:
-isect = []; diff = []; union = []
-count = {}
-for e in a + b:
- count[e] = count.get(e, 0) + 1
-
-for e, num in count.items():
- union.append(e)
- [None, diff, isect][num].append(e)
-#-----------------------------
-
-# @@PLEAC@@_4.9
-#-----------------------------
-# "append" for a single term and
-# "extend" for many terms
-mylist1.extend(mylist2)
-#-----------------------------
-mylist1 = mylist1 + mylist2
-mylist1 += mylist2
-#-----------------------------
-members = ["Time", "Flies"]
-initiates = ["An", "Arrow"]
-members.extend(initiates)
-# members is now ["Time", "Flies", "An", "Arrow"]
-#-----------------------------
-members[2:] = ["Like"] + initiates
-print " ".join(members)
-members[:1] = ["Fruit"] # or members[1] = "Fruit"
-members[-2:] = ["A", "Banana"]
-print " ".join(members)
-#-----------------------------
-#=> Time Flies Like An Arrow
-#=> Fruit Flies Like A Banana
-#-----------------------------
-
-# @@PLEAC@@_4.10
-#-----------------------------
-# reverse mylist into revlist
-
-revlist = mylist[::-1]
-
-# or
-revlist = list(reversed(mylist))
-
-# or pre-2.3
-revlist = mylist[:] # shallow copy
-revlist.reverse()
-#-----------------------------
-for elem in reversed(mylist):
- pass # do something with elem
-
-# or
-for elem in mylist[::-1]:
- pass # do something with elem
-
-# if you need the index and the list won't take too much memory:
-for i, elem in reversed(list(enumerate(mylist))):
- pass
-
-# If you absolutely must explicitly index:
-for i in range(len(mylist)-1, -1, -1):
- pass
-#-----------------------------
-descending = sorted(users, reverse=True)
-#-----------------------------
-
-# @@PLEAC@@_4.11
-#-----------------------------
-# remove n elements from the front of mylist
-mylist[:n] = [] # or del mylist[:n]
-
-# remove n elements from front of mylist, saving them into front
-front, mylist[:n] = mylist[:n], []
-
-# remove 1 element from the front of mylist, saving it in front:
-front = mylist.pop(0)
-
-# remove n elements from the end of mylist
-mylist[-n:] = [] # or del mylist[-n:]
-
-# remove n elements from the end of mylist, saving them in end
-end, mylist[-n:] = mylist[-n:], []
-
-# remove 1 element from the end of mylist, saving it in end:
-end = mylist.pop()
-
-#-----------------------------
-def shift2(terms):
- front = terms[:2]
- terms[:2] = []
- return front
-
-def pop2(terms):
- back = terms[-2:]
- terms[-2:] = []
- return back
-#-----------------------------
-friends = "Peter Paul Mary Jim Tim".split()
-this, that = shift2(friends)
-# 'this' contains Peter, 'that' has Paul, and
-# 'friends' has Mary, Jim, and Tim
-
-beverages = "Dew Jolt Cola Sprite Fresca".split()
-pair = pop2(beverages)
-# pair[0] contains Sprite, pair[1] has Fresca,
-# and 'beverages' has (Dew, Jolt, Cola)
-
-# In general you probably shouldn't do things that way because it's
-# not clear from these calls that the lists are modified.
-#-----------------------------
-
-# @@PLEAC@@_4.12
-for item in mylist:
- if criterion:
- pass # do something with matched item
- break
-else:
- pass # unfound
-#-----------------------------
-for idx, elem in enumerate(mylist):
- if criterion:
- pass # do something with elem found at mylist[idx]
- break
-else:
- pass ## unfound
-#-----------------------------
-# Assuming employees are sorted high->low by wage.
-for employee in employees:
- if employee.category == 'engineer':
- highest_engineer = employee
- break
-
-print "Highest paid engineer is:", highest_engineer.name
-#-----------------------------
-# If you need the index, use enumerate:
-for i, employee in enumerate(employees):
- if employee.category == 'engineer':
- highest_engineer = employee
- break
-print "Highest paid engineer is: #%s - %s" % (i, highest_engineer.name)
-
-
-# The following is rarely appropriate:
-for i in range(len(mylist)):
- if criterion:
- pass # do something
- break
-else:
- pass ## not found
-#-----------------------------
-
-
-# @@PLEAC@@_4.13
-matching = [term for term in mylist if test(term)]
-#-----------------------------
-matching = []
-for term in mylist:
- if test(term):
- matching.append(term)
-#-----------------------------
-bigs = [num for num in nums if num > 1000000]
-pigs = [user for (user, val) in users.items() if val > 1e7]
-#-----------------------------
-import os
-matching = [line for line in os.popen("who")
- if line.startswith("gnat ")]
-#-----------------------------
-engineers = [employee for employee in employees
- if employee.position == "Engineer"]
-#-----------------------------
-secondary_assistance = [applicant for applicant in applicants
- if 26000 <= applicant.income < 30000]
-#-----------------------------
-
-# @@PLEAC@@_4.14
-sorted_list = sorted(unsorted_list)
-#-----------------------------
-# pids is an unsorted list of process IDs
-import os, signal, time
-for pid in sorted(pids):
- print pid
-
-pid = raw_input("Select a process ID to kill: ")
-try:
- pid = int(pid)
-except ValueError:
- raise SystemExit("Exiting ... ")
-os.kill(pid, signal.SIGTERM)
-time.sleep(2)
-try:
- os.kill(pid, signal.SIGKILL)
-except OSError, err:
- if err.errno != 3: # was it already killed?
- raise
-#-----------------------------
-descending = sorted(unsorted_list, reverse=True)
-#-----------------------------
-allnums = [4, 19, 8, 3]
-allnums.sort(reverse=True) # inplace
-#-----------------------------
-# pre 2.3
-allnums.sort() # inplace
-allnums.reverse() # inplace
-#or
-allnums = sorted(allnums, reverse=True) # reallocating
-#-----------------------------
-
-# @@PLEAC@@_4.15
-ordered = sorted(unordered, cmp=compare)
-#-----------------------------
-ordered = sorted(unordered, key=compute)
-
-# ...which is somewhat equivalent to:
-precomputed = [(compute(x), x) for x in unordered]
-precomputed.sort(lambda a, b: cmp(a[0], b[0]))
-ordered = [v for k,v in precomputed.items()]
-#-----------------------------
-# DON'T DO THIS.
-def functional_sort(mylist, function):
- mylist.sort(function)
- return mylist
-
-ordered = [v for k,v in functional_sort([(compute(x), x) for x in unordered],
- lambda a, b: cmp(a[0], b[0]))]
-#-----------------------------
-ordered = sorted(employees, key=lambda x: x.name)
-#-----------------------------
-for employee in sorted(employees, key=lambda x: x.name):
- print "%s earns $%s" % (employee.name, employee.salary)
-#-----------------------------
-sorted_employees = sorted(employees, key=lambda x: x.name):
-for employee in sorted_employees:
- print "%s earns $%s" % (employee.name, employee.salary)
-
-# load bonus
-for employee in sorted_employees:
- if bonus(employee.ssn):
- print employee.name, "got a bonus!"
-#-----------------------------
-sorted_employees = sorted(employees, key=lambda x: (x.name, x.age)):
-#-----------------------------
-# NOTE: Python should allow access to the pwd fields by name
-# as well as by position.
-import pwd
-# fetch all users
-users = pwd.getpwall()
-for user in sorted(users, key=lambda x: x[0]):
- print user[0]
-#-----------------------------
-sorted_list = sorted(names, key=lambda x: x[:1])
-#-----------------------------
-sorted_list = sorted(strings, key=len)
-#-----------------------------
-# DON'T DO THIS.
-temp = [(len(s), s) for s in strings]
-temp.sort(lambda a, b: cmp(a[0], b[0]))
-sorted_list = [x[1] for x in temp]
-#-----------------------------
-# DON'T DO THIS.
-def functional_sort(mylist, function):
- mylist.sort(function)
- return mylist
-
-sorted_fields = [v for k,v in functional_sort(
- [(int(re.search(r"(\d+)", x).group(1)), x) for x in fields],
- lambda a, b: cmp(a[0], b[0]))]
-#-----------------------------
-entries = [line[:-1].split() for line in open("/etc/passwd")]
-
-for entry in sorted(entries, key=lambda x: (x[3], x[2], x[0])):
- print entry
-#-----------------------------
-
-# @@PLEAC@@_4.16
-#-----------------------------
-import itertools
-for process in itertools.cycle([1, 2, 3, 4, 5]):
- print "Handling process", process
- time.sleep(1)
-
-# pre 2.3:
-import time
-class Circular(object):
- def __init__(self, data):
- assert len(data) >= 1, "Cannot use an empty list"
- self.data = data
-
- def __iter__(self):
- while True:
- for elem in self.data:
- yield elem
-
-circular = Circular([1, 2, 3, 4, 5])
-
-for process in circular:
- print "Handling process", process
- time.sleep(1)
-
-# DON'T DO THIS. All those pops and appends mean that the list needs to be
-# constantly reallocated. This is rather bad if your list is large:
-import time
-class Circular(object):
- def __init__(self, data):
- assert len(data) >= 1, "Cannot use an empty list"
- self.data = data
-
- def next(self):
- head = self.data.pop(0)
- self.data.append(head)
- return head
-
-circular = Circular([1, 2, 3, 4, 5])
-while True:
- process = circular.next()
- print "Handling process", process
- time.sleep(1)
-#-----------------------------
-
-# @@PLEAC@@_4.17
-#-----------------------------
-# generate a random permutation of mylist in place
-import random
-random.shuffle(mylist)
-#-----------------------------
-
-# @@PLEAC@@_4.18
-#-----------------------------
-import sys
-
-def make_columns(mylist, screen_width=78):
- if mylist:
- maxlen = max([len(elem) for elem in mylist])
- maxlen += 1 # to make extra space
-
- cols = max(1, screen_width/maxlen)
- rows = 1 + len(mylist)/cols
-
- # pre-create mask for faster computation
- mask = "%%-%ds " % (maxlen-1)
-
- for n in range(rows):
- row = [mask%elem
- for elem in mylist[n::rows]]
- yield "".join(row).rstrip()
-
-for row in make_columns(sys.stdin.readlines(), screen_width=50):
- print row
-
-
-# A more literal translation
-import sys
-
-# subroutine to check whether at last item on line
-def EOL(item):
- return (item+1) % cols == 0
-
-# Might not be portable to non-linux systems
-def getwinsize():
- # Use the curses module if installed
- try:
- import curses
- stdscr = curses.initscr()
- rows, cols = stdscr.getmaxyx()
- return cols
- except ImportError:
- pass
-
- # Nope, so deal with ioctl directly. What value for TIOCGWINSZ?
- try:
- import termios
- TIOCGWINSZ = termios.TIOCGWINSZ
- except ImportError:
- TIOCGWINSZ = 0x40087468 # This is Linux specific
-
- import struct, fcntl
- s = struct.pack("HHHH", 0, 0, 0, 0)
- try:
- x = fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ, s)
- except IOError:
- return 80
- rows, cols = struct.unpack("HHHH", x)[:2]
- return cols
-
-cols = getwinsize()
-
-data = [s.rstrip() for s in sys.stdin.readlines()]
-if not data:
- maxlen = 1
-else:
- maxlen = max(map(len, data))
-
-maxlen += 1 # to make extra space
-
-# determine boundaries of screen
-cols = (cols / maxlen) or 1
-rows = (len(data)+cols) / cols
-
-# pre-create mask for faster computation
-mask = "%%-%ds " % (maxlen-1)
-
-# now process each item, picking out proper piece for this position
-for item in range(rows * cols):
- target = (item % cols) * rows + (item/cols)
- if target < len(data):
- piece = mask % data[target]
- else:
- piece = mask % ""
- if EOL(item):
- piece = piece.rstrip() # don't blank-pad to EOL
- sys.stdout.write(piece)
- if EOL(item):
- sys.stdout.write("\n")
-
-if EOL(item):
- sys.stdout.write("\n")
-#-----------------------------
-
-# @@PLEAC@@_4.19
-#-----------------------------
-def factorial(n):
- s = 1
- while n:
- s *= n
- n -= 1
- return s
-#-----------------------------
-def permute(alist, blist=[]):
- if not alist:
- yield blist
- for i, elem in enumerate(alist):
- for elem in permute(alist[:i] + alist[i+1:], blist + [elem]):
- yield elem
-
-for permutation in permute(range(4)):
- print permutation
-#-----------------------------
-# DON'T DO THIS
-import fileinput
-
-# Slightly modified from
-# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66463
-def print_list(alist, blist=[]):
- if not alist:
- print ' '.join(blist)
- for i in range(len(alist)):
- blist.append(alist.pop(i))
- print_list(alist, blist)
- alist.insert(i, blist.pop())
-
-for line in fileinput.input():
- words = line.split()
- print_list(words)
-#-----------------------------
-class FactorialMemo(list):
- def __init__(self):
- self.append(1)
-
- def __call__(self, n):
- try:
- return self[n]
- except IndexError:
- ret = n * self(n-1)
- self.append(ret)
- return ret
-
-factorial = FactorialMemo()
-
-import sys
-import time
-sys.setrecursionlimit(10000)
-
-start = time.time()
-factorial(2000)
-f1 = time.time() - start
-factorial(2100) # First 2000 values are cached already
-f2 = time.time() - f1 - start
-print "Slow first time:", f1
-print "Quicker the second time:", f2
-#-----------------------------
-
-class MemoizedPermutations(list):
- def __init__(self, alist):
- self.permute(alist, [])
-
- def permute(self, alist, blist):
- if not alist:
- self.append(blist)
- for i, elem in enumerate(alist):
- self.permute(alist[:i] + alist[i+1:], blist + [elem])
-
- def __call__(self, seq, idx):
- return [seq[n] for n in self[idx]]
-
-
-p5 = MemoizedPermutations(range(5))
-
-words = "This sentence has five words".split()
-print p5(words, 17)
-print p5(words, 81)
-#-----------------------------
-
-# @@PLEAC@@_5.0
-#-----------------------------
-# dictionaries
-age = {"Nat": 24,
- "Jules": 24,
- "Josh": 17}
-#-----------------------------
-age = {}
-age["Nat"] = 24
-age["Jules"] = 25
-age["Josh"] = 17
-#-----------------------------
-food_color = {"Apple": "red",
- "Banana": "yellow",
- "Lemon": "yellow",
- "Carrot": "orange"
- }
-#-----------------------------
-# NOTE: keys must be quoted in Python
-
-
-# @@PLEAC@@_5.1
-mydict[key] = value
-#-----------------------------
-# food_color defined per the introduction
-food_color["Raspberry"] = "pink"
-print "Known foods:"
-for food in food_color:
- print food
-
-#=> Known foods:
-#=> Raspberry
-#=> Carrot
-#=> Lemon
-#=> Apple
-#=> Banana
-#-----------------------------
-
-# @@PLEAC@@_5.2
-# does mydict have a value for key?
-if key in mydict:
- pass # it exists
-else:
- pass # it doesn't
-
-#-----------------------------
-# food_color per the introduction
-for name in ("Banana", "Martini"):
- if name in food_color:
- print name, "is a food."
- else:
- print name, "is a drink."
-
-#=> Banana is a food.
-#=> Martini is a drink.
-#-----------------------------
-age = {}
-age["Toddler"] = 3
-age["Unborn"] = 0
-age["Phantasm"] = None
-
-for thing in ("Toddler", "Unborn", "Phantasm", "Relic"):
- print ("%s:"%thing),
- if thing in age:
- print "Exists",
- if age[thing] is not None:
- print "Defined",
- if age[thing]:
- print "True",
- print
-#=> Toddler: Exists Defined True
-#=> Unborn: Exists Defined
-#=> Phantasm: Exists
-#=> Relic:
-#-----------------------------
-# Get file sizes for the requested filenames
-import fileinput, os
-size = {}
-for line in fileinput.input():
- filename = line.rstrip()
- if filename in size:
- continue
- size[filename] = os.path.getsize(filename)
-
-
-# @@PLEAC@@_5.3
-# remove key and its value from mydict
-del mydict[key]
-#-----------------------------
-# food_color as per Introduction
-def print_foods():
- foods = food_color.keys()
-
- print "Keys:", " ".join(foods)
- print "Values:",
-
- for food in foods:
- color = food_color[food]
- if color is not None:
- print color,
- else:
- print "(undef)",
- print
-
-print "Initially:"
-print_foods()
-
-print "\nWith Banana set to None"
-food_color["Banana"] = None
-print_foods()
-
-print "\nWith Banana deleted"
-del food_color["Banana"]
-print_foods()
-
-#=> Initially:
-#=> Keys: Carrot Lemon Apple Banana
-#=> Values: orange yellow red yellow
-#=>
-#=> With Banana set to None
-#=> Keys: Carrot Lemon Apple Banana
-#=> Values: orange yellow red (undef)
-#=>
-#=> With Banana deleted
-#=> Keys: Carrot Lemon Apple
-#=> Values: orange yellow red
-#-----------------------------
-for key in ["Banana", "Apple", "Cabbage"]:
- del food_color[key]
-#-----------------------------
-
-
-# @@PLEAC@@_5.4
-#-----------------------------
-for key, value in mydict.items():
- pass # do something with key and value
-
-# If mydict is large, use iteritems() instead
-for key, value in mydict.iteritems():
- pass # do something with key and value
-
-#-----------------------------
-# DON'T DO THIS:
-for key in mydict.keys():
- value = mydict[key]
- # do something with key and value
-#-----------------------------
-# food_color per the introduction
-for food, color in food_color.items():
- print "%s is %s." % (food, color)
-
-# DON'T DO THIS:
-for food in food_color:
- color = food_color[food]
- print "%s is %s." % (food, color)
-
-#-----------------------------
-print """%(food)s
-
-is
-
-%(color)s.
-""" % vars()
-#-----------------------------
-for food, color in sorted(food_color.items()):
- print "%s is %s." % (food, color)
-
-#-----------------------------
-#!/usr/bin/env python
-# countfrom - count number of messages from each sender
-
-import sys
-if len(sys.argv) > 1:
- infile = open(sys.argv[1])
-else:
- infile = sys.stdin
-
-counts = {}
-for line in infile:
- if line.startswith("From: "):
- name = line[6:-1]
- counts[name] = counts.get(name, 0) + 1
-
-for (name, count) in sorted(counts.items()):
- print "%s: %s" % (name, count)
-
-#-----------------------------
-
-
-# @@PLEAC@@_5.5
-for key, val in mydict.items():
- print key, "=>", val
-#-----------------------------
-print "\n".join([("%s => %s" % item) for item in mydict.items()])
-#-----------------------------
-print mydict
-#=> {'firstname': 'Andrew', 'login': 'dalke', 'state': 'New Mexico', 'lastname': 'Dalke'}
-#-----------------------------
-import pprint
-pprint.pprint(dict)
-#=> {'firstname': 'Andrew',
-#=> 'lastname': 'Dalke',
-#=> 'login': 'dalke',
-#=> 'state': 'New Mexico'}
-#-----------------------------
-
-
-# @@PLEAC@@_5.6
-#-----------------------------
-class SequenceDict(dict):
- """
- Dictionary that remembers the insertion order.
- The lists returned by keys(), values() and items() are
- in the insertion order.
- """
- def __init__(self, *args):
- self._keys={} # key --> id
- self._ids={} # id --> key
- self._next_id=0
-
- def __setitem__(self, key, value):
- self._keys[key]=self._next_id
- self._ids[self._next_id]=key
- self._next_id+=1
- return dict.__setitem__(self, key, value)
-
- def __delitem__(self, key):
- id=self._keys[key]
- del(self._keys[key])
- del(self._ids[id])
- return dict.__delitem__(self, key)
-
- def values(self):
- values=[]
- ids=list(self._ids.items())
- ids.sort()
- for id, key in ids:
- values.append(self[key])
- return values
-
- def items(self):
- items=[]
- ids=list(self._ids.items())
- ids.sort()
- for id, key in ids:
- items.append((key, self[key]))
- return items
-
- def keys(self):
- ids=list(self._ids.items())
- ids.sort()
- keys=[]
- for id, key in ids:
- keys.append(key)
- return keys
-
- def update(self, d):
- for key, value in d.items():
- self[key]=value
-
- def clear(self):
- dict.clear(self)
- self._keys={}
- self._ids={}
- self._next_id=0
-
-def testSequenceDict():
- sd=SequenceDict()
-
- # First Test
- sd[3]="first"
- sd[2]="second"
- sd[1]="third"
- print sd.keys()
- print sd.items()
- print sd.values()
-
- del(sd[1])
- del(sd[2])
- del(sd[3])
-
- print sd.keys(), sd.items(), sd.values()
- print sd._ids, sd._keys
-
- print "---------------"
- # Second Test
- sd["b"]="first"
- sd["a"]="second"
- sd.update({"c": "third"})
- print sd.keys()
- print sd.items()
- print sd.values()
-
- del(sd["b"])
- del(sd["a"])
- del(sd["c"])
-
- print sd.keys(), sd.items(), sd.values()
- print sd._ids, sd._keys
-
-def likePerlCookbook():
- food_color=SequenceDict()
- food_color["Banana"]="Yellow";
- food_color["Apple"]="Green";
- food_color["Lemon"]="Yellow"
- print "In insertion order, the foods' color are:"
- for food, color in food_color.items():
- print "%s is colored %s" % (food, color)
-
-if __name__=="__main__":
- #testSequenceDict()
- likePerlCookbook()
-
-
-# @@PLEAC@@_5.7
-import os
-ttys = {}
-
-who = os.popen("who")
-
-for line in who:
- user, tty = line.split()[:2]
- ttys.setdefault(user, []).append(tty)
-
-for (user, tty_list) in sorted(ttys.items()):
- print user + ": " + " ".join(tty_list)
-#-----------------------------
-import pwd
-for (user, tty_list) in ttys.items():
- print user + ":", len(tty_list), "ttys."
- for tty in sorted(tty_list):
- try:
- uid = os.stat("/dev/" + tty).st_uid
- user = pwd.getpwuid(uid)[0]
- except os.error:
- user = "(not available)"
- print "\t%s (owned by %s)" % (tty, user)
-
-# @@PLEAC@@_5.8
-# lookup_dict maps keys to values
-reverse = dict([(val, key) for (key, val) in lookup_dict.items()])
-#-----------------------------
-surname = {"Mickey": "Mantle", "Babe": "Ruth"}
-first_name = dict([(last, first) for (first, last) in surname.items()])
-
-print first_name["Mantle"]
-#=> Mickey
-#-----------------------------
-#!/usr/bin/perl -w
-# foodfind - find match for food or color
-
-import sys
-if not sys.argv[1:]:
- raise SystemExit("usage: foodfind food_or_color")
-given = sys.argv[1]
-
-color_dict = {"Apple": "red",
- "Banana": "yellow",
- "Lemon": "yellow",
- "Carrot": "orange",
- }
-food_dict = dict([(color, food) for (food, color) in color_dict.items()])
-
-if given in color_dict:
- print given, "is a food with color", color_dict[given]
-elif given in food_dict:
- print food_dict[given], "is a food with color", given
-#-----------------------------
-# food_color as per the introduction
-foods_with_color = {}
-for food, color in food_color.items():
- foods_with_color.setdefault(color, []).append(food)
-
-print " ".join(foods_with_color["yellow"]), "were yellow foods."
-#-----------------------------
-
-# @@PLEAC@@_5.9
-#-----------------------------
-# mydict is the hash to sort
-for key, value in sorted(mydict.items()):
- # do something with key, value
-#-----------------------------
-# food_color as per section 5.8
-for food, color in sorted(food_color.items()):
- print "%s is %s." % (food, color)
-#-----------------------------
-# NOTE: alternative version
-for item in sorted(food_color.items()):
- print "%s is %s." % item
-#-----------------------------
-# NOTE: alternative version showing a user-defined function
-def food_cmp(x, y):
- return cmp(x, y)
-
-for food, color in sorted(food_color, cmp=food_cmp):
- print "%s is %s." % (food, color)
-#-----------------------------
-def food_len_cmp(x, y):
- return cmp(len(x), len(y))
-
-for food in sorted(food_color, cmp=food_len_cmp):
- print "%s is %s." % (food, food_color[food])
-
-# In this instance, however, the following is both simpler and faster:
-for food in sorted(food_color, key=len):
- print "%s is %s." % (food, food_color[food])
-#-----------------------------
-
-
-# @@PLEAC@@_5.10
-#-----------------------------
-merged = {}
-merged.update(a_dict)
-merged.update(b_dict)
-
-#-----------------------------
-# NOTE: alternative version
-merged = a_dict.copy()
-merged.update(b_dict)
-#-----------------------------
-# DON'T DO THIS:
-
-merged = {}
-for k, v in a_dict.items():
- merged[k] = v
-for k, v in b_dict.items():
- merged[k] = v
-#-----------------------------
-# food_color as per section 5.8
-drink_color = {"Galliano": "yellow",
- "Mai Tai": "blue"}
-
-ingested_color = drink_color.copy()
-ingested_color.update(food_color)
-#-----------------------------
-# DON'T DO THIS:
-drink_color = {"Galliano": "yellow",
- "Mai Tai": "blue"}
-
-substance_color = {}
-for k, v in food_color.items():
- substance_color[k] = v
-for k, v in drink_color.items():
- substance_color[k] = v
-#-----------------------------
-# DON'T DO THIS:
-substance_color = {}
-for mydict in (food_color, drink_color):
- for k, v in mydict:
- substance_color[k] = v
-#-----------------------------
-# DON'T DO THIS:
-substance_color = {}
-for item in food_color.items() + drink_color.items():
- for k, v in mydict:
- substance_color[k] = v
-#-----------------------------
-substance_color = {}
-for mydict in (food_color, drink_color):
- for k, v in mydict.items():
- if substance_color.has_key(k):
- print "Warning:", k, "seen twice. Using the first definition."
- continue
- substance_color[k] = v
-
-# I think it's a copy, in which case
-all_colors = new_colors.copy()
-
-
-# @@PLEAC@@_5.11
-common = [k for k in dict1 if k in dict2]
-#-----------------------------
-this_not_that = [k for k in dict1 if k not in dict2]
-#-----------------------------
-# citrus_color is a dict mapping citrus food name to its color.
-citrus_color = {"Lemon": "yellow",
- "Orange": "orange",
- "Lime": "green"}
-
-# build up a list of non-citrus foods
-non_citrus = [k for k in food_color if k not in citruscolor]
-#-----------------------------
-
-# @@PLEAC@@_5.12
-#-----------------------------
-# references as keys of dictionaries is no pb in python
-
-name = {}
-for filename in ("/etc/termcap", "/vmunix", "/bin/cat"):
- try:
- myfile = open(filename)
- except IOError:
- pass
- else:
- names[myfile] = filename
-
-print "open files:", ", ".join(name.values())
-for f, fname in name.items():
- f.seek(0, 2) # seek to the end
- print "%s is %d bytes long." % (fname, f.tell())
-#-----------------------------
-
-# @@PLEAC@@_5.13
-# Python doesn't allow presizing of dicts, but hashing is efficient -
-# it only re-sizes at intervals, not every time an item is added.
-
-# @@PLEAC@@_5.14
-count = {}
-for element in mylist:
- count[element] = count.get(element, 0) + 1
-
-# @@PLEAC@@_5.15
-#-----------------------------
-import fileinput
-
-father = {'Cain': 'Adam',
- 'Abel': 'Adam',
- 'Seth': 'Adam',
- 'Enoch': 'Cain',
- 'Irad': 'Enoch',
- 'Mehujael': 'Irad',
- 'Methusael': 'Mehujael',
- 'Lamech': 'Methusael',
- 'Jabal': 'Lamech',
- 'Tubalcain': 'Lamech',
- 'Enos': 'Seth',
- }
-
-for line in fileinput.input():
- person = line.rstrip()
- while person: # as long as we have people,
- print person, # print the current name
- person = father.get(person) # set the person to the person's father
- print
-
-#-----------------------------
-import fileinput
-
-children = {}
-for k, v in father.items():
- children.setdefault(v, []).append(k)
-
-for line in fileinput.input():
- person = line.rstrip()
- kids = children.get(person, ["nobody"])
- print person, "begat", ", ".join(kids)
-
-#-----------------------------
-import sys, re
-pattern = re.compile(r'^\s*#\s*include\s*<([^>]+)')
-includes = {}
-for filename in filenames:
- try:
- infile = open(filename)
- except IOError, err:
- print>>sys.stderr, err
- continue
- for line in infile:
- match = pattern.match(line)
- if match:
- includes.setdefault(match.group(1), []).append(filename)
-#-----------------------------
-# list of files that don't include others
-mydict = {}
-for e in reduce(lambda a,b: a + b, includes.values()):
- if not includes.has_key(e):
- mydict[e] = 1
-include_free = mydict.keys()
-include_free.sort()
-
-# @@PLEAC@@_5.16
-#-----------------------------
-#!/usr/bin/env python -w
-# dutree - print sorted indented rendition of du output
-import os, sys
-
-def get_input(args):
- # NOTE: This is insecure - use only from trusted code!
- cmd = "du " + " ".join(args)
- infile = os.popen(cmd)
-
- dirsize = {}
- kids = {}
- for line in infile:
- size, name = line[:-1].split("\t", 1)
- dirsize[name] = int(size)
- parent = os.path.dirname(name)
- kids.setdefault(parent, []).append(name)
- # Remove the last field added, which is the root
- kids[parent].pop()
- if not kids[parent]:
- del kids[parent]
-
- return name, dirsize, kids
-
-def getdots(root, dirsize, kids):
- size = cursize = dirsize[root]
- if kids.has_key(root):
- for kid in kids[root]:
- cursize -= dirsize[kid]
- getdots(kid, dirsize, kids)
- if size != cursize:
- dot = root + "/."
- dirsize[dot] = cursize
- kids[root].append(dot)
-
-def output(root, dirsize, kids, prefix = "", width = 0):
- path = os.path.basename(root)
- size = dirsize[root]
- fmt = "%" + str(width) + "d %s"
- line = fmt % (size, path)
- print prefix + line
-
- prefix += (" " * (width-1)) + "| " + (" " * len(path))
-
- if kids.has_key(root):
- kid_list = kids[root]
- kid_list.sort(lambda x, y, dirsize=dirsize:
- cmp(dirsize[x], dirsize[y]))
- width = len(str(dirsize[kid_list[-1]]))
- for kid in kid_list:
- output(kid, dirsize, kids, prefix, width)
-
-def main():
- root, dirsize, kids = get_input(sys.argv[1:])
- getdots(root, dirsize, kids)
- output(root, dirsize, kids)
-
-if __name__ == "__main__":
- main()
-
-
-# @@PLEAC@@_6.0
-# Note: regexes are used less often in Python than in Perl as tasks are often
-# covered by string methods, or specialised objects, modules, or packages.
-
-import re # "re" is the regular expression module.
-re.search("sheep",meadow) # returns a MatchObject is meadow contains "sheep".
-if not re.search("sheep",meadow):
- print "no sheep on this meadow only a fat python."
-# replacing strings is not done by "re"gular expressions.
-meadow = meadow.replace("old","new") # replace "old" with "new" and assign result.
-#-----------------------------
-re.search("ovine",meadow)
-
-meadow = """Fine bovines demand fine toreadors.
-Muskoxen are polar ovibovine species.
-Grooviness went out of fashion decades ago."""
-
-meadow = "Ovines are found typically in ovaries."
-
-if re.search(r"\bovines\b",meadow,re.I) : print "Here be sheep!"
-#-----------------------------
-# The tricky bit
-mystr = "good food"
-re.sub("o*","e",mystr,1) # gives 'egood food'
-
-echo ababacaca | python -c "import sys,re; print re.search('(a|ba|b)+(a|ac)+',sys.stdin.read()).group()"
-#-----------------------------
-# pattern matching modifiers
-# assume perl code iterates over some file
-import re, fileinput
-for ln = fileinput.input():
- fnd = re.findall("(\d+)",ln)
- if len(fnd) > 0:
- print "Found number %s" % (fnd[0])
-# ----------------------------
-digits = "123456789"
-nonlap = re.findall("(\d\d\d)", digits)
-yeslap = ["not yet"]
-print "Non-overlapping:",",".join(nonlap)
-print "Overlapping :",",".join(yeslap)
-# ----------------------------
-mystr = "And little lambs eat ivy"
-fnd = re.search("(l[^s]*s)", mystr)
-print "(%s) (%s) (%s)" % (mystr[:fnd.start()], fnd.group(), mystr[fnd.end():])
-# (And ) (little lambs) ( eat ivy)
-
-
-# @@PLEAC@@_6.1
-import re
-dst = re.sub("this","that",src)
-#-----------------------------
-# strip to basename
-basename = re.sub(".*/(?=[^/]+)","",progname)
-
-# Make All Words Title-Cased
-# DON'T DO THIS - use str.title() instead
-def cap(mo): return mo.group().capitalize()
-re.sub("(?P<n>\w+)",cap,"make all words title-cased")
-
-# /usr/man/man3/foo.1 changes to /usr/man/cat3/foo.1
-manpage = "/usr/man/man3/foo.1"
-catpage = re.sub("man(?=\d)","cat",manpage)
-#-----------------------------
-bindirs = "/usr/bin /bin /usr/local/bin".split()
-libdirs = [d.replace("bin", "lib") for d in bindirs]
-
-print " ".join(libdirs)
-#=> /usr/lib /lib /usr/local/lib
-#-----------------------------
-# strings are never modified in place.
-#-----------------------------
-
-# @@PLEAC@@_6.2
-##---------------------------
-
-# DON'T DO THIS. use line[:-1].isalpha() [this probably goes for the
-# remainder of this section too!]
-import re
-if re.match("^[A-Za-z]+$",line):
- print "pure alphabetic"
-##---------------------------
-if re.match(r"^[^\W\d_]+$", line, re.LOCALE):
- print "pure alphabetic"
-##---------------------------
-import re
-import locale
-
-try:
- locale.setlocale(locale.LC_ALL, 'fr_CA.ISO8859-1')
-except:
- print "couldn't set locale to French Cnadian"
- raise SystemExit
-
-DATA="""
-silly
-façade
-coöperate
-niño
-Renée
-Molière
-hæmoglobin
-naïve
-tschüß
-random!stuff#here
-"""
-
-for ln in DATA.split():
- ln = ln.rstrip()
- if re.match(r"^[^\W\d_]+$",ln,re.LOCALE):
- print "%s: alphabetic" % (ln)
- else:
- print "%s: line noise" % (ln)
-# although i dont think "coöperate" should be in canadian
-##---------------------------
-
-# @@PLEAC@@_6.3
-# Matching Words
-"\S+" # as many non-whitespace bytes as possible
-"[A-Za-z'-]+" # as many letters, apostrophes, and hyphens
-
-# string split is similar to splitting on "\s+"
-"A text with some\tseparator".split()
-
-"\b*([A-Za-z]+)\b*" # word boundaries
-"\s*([A-Za-z]+)\s*" # might work too as on letters are allowed.
-
-re.search("\Bis\B","this thistle") # matches on thistle not on this
-re.search("\Bis\B","vis-a-vis") # does not match
-
-# @@PLEAC@@_6.4
-#-----------------------------
-#!/usr/bin/python
-# resname - change all "foo.bar.com" style names in the input stream
-# into "foo.bar.com [204.148.40.9]" (or whatever) instead
-
-import socket # load inet_addr
-import fileinput
-import re
-
-match = re.compile("""(?P<hostname> # capture hostname
- (?: # these parens for grouping only
- [\w-]+ # hostname component
- \. # ant the domain dot
- ) + # now repeat that whole thing a bunch of times
- [A-Za-z] # next must be a letter
- [\w-] + # now trailing domain part
- ) # end of hostname capture
- """,re.VERBOSE) # for nice formatting
-
-def repl(match_obj):
- orig_hostname = match_obj.group("hostname")
- try:
- addr = socket.gethostbyname(orig_hostname)
- except socket.gaierror:
- addr = "???"
- return "%s [%s]" % (orig_hostname, addr)
-
-for ln in fileinput.input():
- print match.sub(repl, ln)
-#-----------------------------
-re.sub("""(?x) # nicer formatting
- \# # a pound sign
- (\w+) # the variable name
- \# # another pound sign
- """,
- lambda m: eval(m.group(1)), # replace with the value of the global variable
- line
- )
-##-----------------------------
-re.sub("""(?x) # nicer formatting
- \# # a pound sign
- (\w+) # the variable name
- \# # another pound sign
- """,
- lambda m: eval(eval(m.group(1))), # replace with the value of *any* variable
- line
- )
-##-----------------------------
-
-# @@PLEAC@@_6.5
-import re
-pond = "one fish two fish red fish blue fish"
-fishes = re.findall(r"(?i)(\w+)\s+fish\b",pond)
-if len(fishes)>2:
- print "The third fish is a %s one." % (fishes[2])
-##-----------------------------
-re.findall(r"(?i)(?:\w+\s+fish\s+){2}(\w+)\s+fish",pond)
-##-----------------------------
-count = 0
-for match_object in re.finditer(r"PAT", mystr):
- count += 1 # or whatever you want to do here
-
-# "progressive" matching might be better if one wants match 5 from 50.
-# to count use
-count = len(re.findall(r"PAT",mystr))
-count = len(re.findall(r"aba","abaababa"))
-
-# "count" overlapping matches
-count = len(re.findall(r"(?=aba)","abaababa"))
-
-# FASTEST non-overlapping might be str.count
-"abaababa".count("aba")
-##-----------------------------
-pond = "one fish two fish red fish blue fish"
-colors = re.findall(r"(?i)(\w+)\s+fish\b",pond) # get all matches
-color = colors[2] # then the one we want
-
-# or without a temporary list
-color = re.findall(r"(?i)(\w+)\s+fish\b",pond)[2] # just grab element 3
-
-print "The third fish in the pond is %s." % (color)
-##-----------------------------
-import re
-
-pond = "one fish two fish red fish blue fish"
-matches = re.findall(r"(\w+)\s+fish\b",pond)
-evens = [fish for (i, fish) in enumerate(matches) if i%2]
-print "Even numbered fish are %s." % (" ".join(evens))
-##-----------------------------
-count = 0
-def four_is_sushi(match_obj):
- global count
- count += 1
- if count==4:
- return "sushi%s" % (match_obj.group(2))
- return "".join(match_obj.groups())
-
-re.sub(r"""(?x) # VERBOSE
- \b # makes next \w more efficient
- ( \w+ ) # this is what we'll be changing
- (
- \s+ fish \b
- )""",
- four_is_sushi,
- pond)
-# one fish two fish red fish sushi fish
-##-----------------------------
-# greedily
-last_fish = re.findall(r"(?i).*\b(\w+)\s+fish\b",pond)
-##-----------------------------
-pond = "One fish two fish red fish blue fish swim here"
-color = re.findall(r"(?i)\b(\w+)\s+fish\b",pond)[-1]
-print "Last fish is "+color+"."
-# FASTER using string.
-lastfish = pond.rfind("fish")
-color = pond[:lastfish].split()[-1]
-##-----------------------------
-r"""(?x)
- A # find some pattern A
- (?! # mustn't be able to find
- .* # something
- A # and A
- )
- $ # through the end of string
- """
-
-pond = "One fish two fish red fish blue fish swim here"
-fnd = re.findall(r"""(?xis) # VERBOSE, CASEINSENSITIVE, DOTALL
- \b ( \w+ ) \s+ fish \b
- (?! .* \b fish \b )""",
- pond)
-if len(fnd):
- print "Last fish is %s." % (fnd[0])
-else:
- print "Failed!"
-
-
-# @@PLEAC@@_6.6
-# Matching Multiple Lines
-#
-#!/usr/bin/python
-# killtags - very bad html tag killer
-import re
-import sys
-
-text = open(sys.argv[1]).read() # read the whole file
-text = re.sub("(?ms)<.*?>","",text) # strip tags (terrible
-print text
-## ----------------------------
-#!/usr/bin/python
-# headerfy: change certain chapter headers to html
-import sys, re
-
-match = re.compile(r"""(?xms) # re.VERBOSE, re.MULTILINE, and re.DOTALL
- \A # start of the string
- (?P<chapter> # capture in g<chapter>
- Chapter # literal string
- \s+ # mandatory whitespace
- \d+ # decimal number
- \s* # optional whitespace
- : # a real colon
- . * # anything not a newline till end of line
- )
- """)
-text = open(sys.argv[1]).read() # read the whole file
-for paragraph in text.split("\n"): # split on unix end of lines
- p = match.sub("<h1>\g<chapter></h1>",paragraph)
- print p
-## ----------------------------
-# the one liner does not run.
-# python -c 'import sys,re; for p in open(sys.argv[1]).read().split("\n\n"): print re.sub(r"(?ms)\A(Chapter\s+\d+\s*:.*)","<h1>\g0</h1>",p)'
-## ----------------------------
-match = re.compile(r"(?ms)^START(.*?)^END")
- # s makes . span line boundaries
- # m makes ^ match at the beginning of the string and at the beginning of each line
-
-chunk = 0
-for paragraph in open(sys.argv[1]).read().split("\n\n"):
- chunk += 1
- fnd = match.findall(paragraph)
- if fnd:
- print "chunk %d in %s has <<%s>>" % (chunk,sys.argv[1],">>,<<".join(fnd))
-## ----------------------------
-
-# @@PLEAC@@_6.7
-import sys
-# Read the whole file and split
-chunks = open(sys.argv[1]).read().split() # on whitespace
-chunks = open(sys.argv[1]).read().split("\n") # on line ends
-
-# splitting on pattern
-import re
-pattern = r"x"
-chunks = re.split(pattern, open(sys.argv[1]).read())
-##-----------------------------
-chunks = re.split(r"(?m)^\.(Ch|Se|Ss)$",open(sys.argv[1]).read())
-print "I read %d chunks." % (len(chunks))
-# without delimiters
-chunks = re.split(r"(?m)^\.(?:Ch|Se|Ss)$",open(sys.argv[1]).read())
-
-# with delimiters
-chunks = re.split(r"(?m)^(\.(?:Ch|Se|Ss))$",open(sys.argv[1]).read())
-
-# with delimiters at chunkstart
-chunks = re.findall(r"""(?xms) # multiline, dot matches lineend, allow comments
- ((?:^\.)? # consume the separator if present
- .*?) # match everything but not greedy
- (?= # end the match on this but dont consume it
- (?: # dont put into group [1]
- ^\.(?:Ch|Se|Ss)$ # either end on one of the roff commands
- |\Z # or end of text
- )
- )""",
- open(sys.argv[1]).read())
-# [1] if "?:" is removed the result holds tuples: ('.Ch\nchapter x','.Ch')
-# which might be more usefull.
-
-# @@PLEAC@@_6.8
-##-----------------------------
-# Python doesn't have perl's range operators
-# If you want to only use a selected line range, use enumerate
-# (though note that indexing starts at zero:
-for i, line in enumerate(myfile):
- if firstlinenum <= i < lastlinenum:
- dosomethingwith(line)
-
-# Using patterned ranges is slightly trickier -
-# You need to search for the first pattern then
-# search for the next pattern:
-import re
-for line in myfile:
- if re.match(pat1, line):
- break
-
-dosomethingwith(line) # Only if pat1 can be on same line as pat2
-
-for line in myfile:
- if re.match(pat2, line):
- break
- dosomethingwith(line)
-##-----------------------------
-# If you need to extract ranges a lot, the following generator funcs
-# may be useful:
-def extract_range(myfile, start, finish):
- for i, line in enumerate(myfile):
- if start <= i < finish:
- yield line
- elif i == finish:
- break
-
-for line in extract_range(open("/etc/passwd"), 3, 5):
- print line
-
-def patterned_range(myfile, startpat, endpat=None):
- startpat = re.compile(startpat)
- if endpat is not None:
- endpat = re.compile(endpat)
- in_range = False
- for line in myfile:
- if re.match(startpat, line):
- in_range = True
- if in_range:
- yield line
- if endpat is not None and re.match(endpat, line):
- break
-
-# DO NOT DO THIS. Use the email module instead
-for line in patterned_range(msg, "^From:?", "^$"):
- pass #...
-
-
-# @@PLEAC@@_6.9
-tests = (("list.?",r"^list\..$"),
- ("project.*",r"^project\..*$"),
- ("*old",r"^.*old$"),
- ("type*.[ch]",r"^type.*\.[ch]$"),
- ("*.*",r"^.*\..*$"),
- ("*",r"^.*$"),
- )
-
-# The book says convert "*","?","[","]" all other characters will be quoted.
-# The book uses "\Q" which escapes any characters that would otherwise be
-# treated as regular expression.
-# Escaping every char fails as "\s" is not "s" in a regex.
-
-def glob2pat(globstr):
- pat = globstr.replace("\\",r"\\")
- pat = pat.replace(".",r"\.").replace("?",r".").replace("*",r".*")
-
- return "^"+pat+"$"
-
-for globstr, patstr in tests:
- g2p = glob2pat(globstr)
- if g2p != patstr:
- print globstr, "failed! Should be", patstr, "but was", g2p
-
-
-# @@PLEAC@@_6.10
-
-# download the following standalone program
-#!/usr/bin/python
-# popgrep1 - grep for abbreviations of places that say "pop"
-# version 1: slow but obvious way
-import fileinput
-import re
-popstates = ["CO","ON","MI","WI","MN"]
-for line in fileinput.input():
- for state in popstates:
- if re.search(r"\b"+state+r"\b",line):
- print line
-
-
-
-#-----------------------------
-# download the following standalone program
-#!/usr/bin/python
-# popgrep2 - grep for abbreviations of places that say "pop"
-# version 2: compile the patterns
-import fileinput
-import re
-popstates = ["CO","ON","MI","WI","MN"]
-state_re = []
-for state in popstates:
- state_re.append(re.compile(r"\b"+state+r"\b"))
-for line in fileinput.input():
- for state in state_re:
- if state.search(line):
- print line
-
-
-#-----------------------------
-# download the following standalone program
-#!/usr/bin/python
-# popgrep3 - grep for abbreviations of places that say "pop"
-# version 3: compile a single pattern
-import fileinput
-import re
-popstates = ["CO","ON","MI","WI","MN"]
-state_re = re.compile(r"\b(?:"+"|".join(popstates)+r")\b")
-for line in fileinput.input():
- if state_re.search(line):
- print line
-
-
-#-----------------------------
-# download the following standalone program
-#!/usr/bin/python
-# grepauth - print lines that mention both Tom and Nat
-import fileinput
-import re
-
-def build_match_any(words):
- return re.compile("|".join(words))
-def uniq(arr):
- seen = {}
- for item in arr:
- seen[item] = seen.get(item, 0) + 1
- return seen.keys()
-def build_match_all(words):
- r = re.compile("|".join(words))
- c = lambda line: len(uniq(r.findall(line)))>=len(words)
- return c
-
-any = build_match_any(("Tom","Nat"))
-all = build_match_all(("Tom","Nat"))
-for line in fileinput.input():
- if any.search(line):
- print "any:", line
- if all(line):
- print "all:", line
-
-
-
-#-----------------------------
-
-
-# @@PLEAC@@_6.11
-# Testing for a Valid Pattern
-
-import re
-while True:
- pat = raw_input("Pattern? ")
- try:
- re.compile(pat)
- except re.error, err:
- print "INVALID PATTERN", err
- continue
- break
-
-# ----
-def is_valid_pattern(pat):
- try:
- re.compile(pat)
- except re.error:
- return False
- return True
-
-# ----
-
-# download the following standalone program
-#!/usr/bin/python
-# paragrep - trivial paragraph grepper
-#
-# differs from perl version in parano.
-# python version displays paragraph in current file.
-
-import sys, os.path, re
-if len(sys.argv)<=1:
- print "usage: %s pat [files]\n" % sys.argv[0]
- sys.exit(1)
-
-pat = sys.argv[1]
-try:
- pat_re = re.compile(pat)
-except:
- print "%s: bad pattern %s: %s" % (sys.argv[1], pat, sys.exc_info()[1])
- sys.exit(1)
-for filename in filter(os.path.isfile,sys.argv[2:]):
- parano = 0
- for para in open(filename).read().split("\n\n"):
- parano += 1
- if pat_re.search(para):
- print filename, parano, para, "\n"
-
-
-
-# ----
-
-# as we dont evaluate patterns the attack ::
-#
-# $pat = "You lose @{[ system('rm -rf *']} big here";
-#
-# does not work.
-
-
-# @@PLEAC@@_6.12
-
-# download the following standalone program
-#!/usr/bin/python
-# localeg - demonstrates locale effects
-#
-# re must be told to respect locale either in the regexp
-# "(?L)" or as flag to the call (python 2.4) "re.LOCALE".
-
-import sys
-import re, string
-from locale import LC_CTYPE, setlocale, getlocale
-
-name = "andreas k\xF6nig"
-locale = {"German" : "de_DE.ISO_8859-1", "English" : "en_US"}
-# us-ascii is not supported on linux py23
-# none works in activestate py24
-
-try:
- setlocale(LC_CTYPE, locale["English"])
-except:
- print "Invalid locale %s" % locale["English"]
- sys.exit(1)
-english_names = []
-for n in re.findall(r"(?L)\b(\w+)\b",name):
- english_names.append(n.capitalize())
-
-try:
- setlocale(LC_CTYPE, locale["German"])
-except:
- print "Invalid locale %s" % locale["German"]
- sys.exit(1)
-german_names = map(string.capitalize, re.findall(r"(?L)\b(\w+)\b",name))
-
-print "English names: %s" % " ".join(english_names)
-print "German names: %s" % " ".join(german_names)
-
-
-# @@PLEAC@@_6.13
-##-----------------------------
-import difflib
-matchlist = ["ape", "apple", "lapel", "peach", "puppy"]
-print difflib.get_close_matches("appel", matchlist)
-#=> ['lapel', 'apple', 'ape']
-##-----------------------------
-# Also see:
-# http://www.personal.psu.edu/staff/i/u/iua1/python/apse/
-# http://www.bio.cam.ac.uk/~mw263/pyagrep.html
-
-# @@PLEAC@@_6.14
-##-----------------------------
-# To search (potentially) repeatedly for a pattern, use re.finditer():
-
-# DO NOT DO THIS. Split on commas and convert elems using int()
-mystr = "3,4,5,9,120"
-for match in re.finditer("(\d+)", mystr):
- n = match.group(0)
- if n == "9":
- break # '120' will never be matched
- print "Found number", n
-
-# matches know their end position
-mystr = "The year 1752 lost 10 days on the 3rd of September"
-x = re.finditer("(\d+)", mystr)
-for match in x:
- n = match.group(0)
- print "Found number", n
-
-tail = re.match("(\S+)", mystr[match.end():])
-if tail:
- print "Found %s after the last number."%tail.group(0)
-
-
-# @@PLEAC@@_6.15
-# Python's regexes are based on Perl's, so it has the non-greedy
-# '*?', '+?', and '??' versions of '*', '+', and '?'.
-# DO NOT DO THIS. import htmllib, formatter, etc, instead
-#-----------------------------
-# greedy pattern
-txt = re.sub("<.*>", "", txt) # try to remove tags, very badly
-
-# non-greedy pattern
-txt = re.sub("<.*?>", "", txt) # try to remove tags, still rather badly
-#-----------------------------
-txt = "<b><i>this</i> and <i>that</i> are important</b> Oh, <b><i>me too!</i></b>"
-
-print re.findall("<b><i>(.*?)</i></b>", txt
-##-----------------------------
-print re.findall("/BEGIN((?:(?!BEGIN).)*)END/", txt)
-##-----------------------------
-print re.findall("<b><i>((?:(?!<b>|<i>).)*)</i></b>", txt)
-##-----------------------------
-print re.findall("<b><i>((?:(?!<[ib]>).)*)</i></b>", txt)
-##-----------------------------
-print re.findall("""
- <b><i>
- [^<]* # stuff not possibly bad, and not possibly the end.
- (?: # at this point, we can have '<' if not part of something bad
- (?! </?[ib]> ) # what we can't have
- < # okay, so match the '<'
- [^<]* # and continue with more safe stuff
- ) *
- </i></b>
- """, re.VERBOSE, txt)
-##-----------------------------
-
-# @@PLEAC@@_6.16
-##-----------------------------
-text = """
-This is a test
-test of the duplicate word finder.
-"""
-words = text.split()
-for curr, next in zip(words[:-1], words[1:]):
- if curr.upper() == next.upper():
- print "Duplicate word '%s' found." % curr
-
-# DON'T DO THIS
-import re
-pat = r"""
- \b # start at a word boundary (begin letters)
- (\S+) # find chunk of non-whitespace
- \b # until another word boundary (end letters)
- (
- \s+ # separated by some whitespace
- \1 # and that very same chunk again
- \b # until another word boundary
- ) + # one or more sets of those
- """
-for match in re.finditer(pat, text, flags=re.VERBOSE|re.IGNORECASE):
- print "Duplicate word '%s' found." % match.group(1)
-##-----------------------------
-a = 'nobody';
-b = 'bodysnatcher';
-
-text = a+" "+b
-pat = r"^(\w+)(\w+) \2(\w+)$"
-for match in re.finditer(pat, text):
- m1, m2, m3 = match.groups()
- print m2, "overlaps in %s-%s-%s"%(m1, m2, m3)
-##-----------------------------
-pat = r"^(\w+?)(\w+) \2(\w+)$"
-##-----------------------------
-try:
- while True:
- factor = re.match(r"^(oo+?)\1+$", n).group(1)
- n = re.sub(factor, "o", n)
- print len(factor)
-except AttributeError:
- print len(n)
-##-----------------------------
-def diaphantine(n, x, y, z):
- pat = r"^(o*)\1{%s}(o*)\2{%s}(o*)\3{%s}$"%(x-1, y-1, z-1)
- text = "o"*n
- try:
- vals = [len(v) for v in re.match(pat, text).groups()]
- except ValueError:
- print "No solutions."
- else:
- print "One solution is: x=%s, y=%s, z=%s."%tuple(vals)
-
-diaphantine(n=281, x=12, y=15, z=16)
-
-# @@PLEAC@@_6.17
-##-----------------------------
-# Pass any of the following patterns to re.match(), etc
-pat = "ALPHA|BETA"
-pat = "^(?=.*ALPHA)(?=.*BETA)"
-pat = "ALPHA.*BETA|BETA.*ALPHA"
-pat = "^(?:(?!PAT).)*$"
-pat = "(?=^(?:(?!BAD).)*$)GOOD"
-##-----------------------------
-if not re.match(pattern, text):
- something()
-##-----------------------------
-if re.match(pat1, text) and re.match(pat2, text):
- something()
-##-----------------------------
-if re.match(pat1, text) or re.match(pat2, text):
- something()
-##-----------------------------
-# DON'T DO THIS.
-"""minigrep - trivial grep"""
-import sys, re
-
-pat = sys.argv[1]
-for line in sys.stdin:
- if re.match(pat, line):
- print line[:-1]
-##-----------------------------
-if re.match(r"^(?=.*bell)(?=.*lab)", "labelled"):
- something()
-##-----------------------------
-if re.search("bell", s) and re.search("lab", s):
- something()
-##-----------------------------
-if re.match("""
- ^ # start of string
- (?= # zero-width lookahead
- .* # any amount of intervening stuff
- bell # the desired bell string
- ) # rewind, since we were only looking
- (?= # and do the same thing
- .* # any amount of intervening stuff
- lab # and the lab part
- )
- """,
- murray_hill,
- re.DOTALL | re.VERBOSE):
- print "Looks like Bell Labs might be in Murray Hill!"
-##-----------------------------
-if re.match(r"(?:^.*bell.*lab)|(?:^.*lab.*bell)", "labelled"):
- something()
-##-----------------------------
-brand = "labelled"
-if re.match("""
- (?: # non-capturing grouper
- ^ .*? # any amount of stuff at the front
- bell # look for a bell
- .*? # followed by any amount of anything
- lab # look for a lab
- ) # end grouper
- | # otherwise, try the other direction
- (?: # non-capturing grouper
- ^ .*? # any amount of stuff at the front
- lab # look for a lab
- .*? # followed by any amount of anything
- bell # followed by a bell
- ) # end grouper
- """,
- brand,
- re.DOTALL | re.VERBOSE):
- print "Our brand has bell and lab separate."
-##-----------------------------
-x = "odlaw"
-if re.match("^(?:(?!waldo).)*$", x):
- print "There's no waldo here!"
-##-----------------------------
-if re.match("""
- ^ # start of string
- (?: # non-capturing grouper
- (?! # look ahead negation
- waldo # is he ahead of us now?
- ) # is so, the negation failed
- . # any character (cuzza /s)
- ) * # repeat that grouping 0 or more
- $ # through the end of the string
- """,
- x,
- re.VERBOSE | re.DOTALL):
- print "There's no waldo here!\n";
-##-----------------------------
-
-# @@PLEAC@@_6.18
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_6.19
-##-----------------------------
-from email._parseaddr import AddressList
-
-print AddressList("fred&barney@stonehenge.com").addresslist[0]
-
-print AddressList("fred&barney@stonehenge.com (Hanna Barbara)").addresslist[0]
-
-name, address = AddressList("Mr Fooby Blah <me@nowhere.com>").addresslist[0]
-print "%s's address is '%s'"%(name, address)
-
-# @@PLEAC@@_6.20
-##-----------------------------
-# Assuming the strings all start with different letters, or you don't
-# mind there being precedence, use the startswith string method:
-
-def get_action(answer):
- answer = answer.lower()
- actions = ["send", "stop", "abort", "list", "end"]
- for action in actions:
- if action.startswith(answer):
- return action
-
-print "Action is %s."%get_action("L")
-#=> Action is list.
-##-----------------------------
-#DON'T DO THIS:
-import re
-answer = "ab"
-answer = re.escape(answer.strip())
-for action in ("SEND", "STOP", "ABORT", "LIST", "EDIT"):
- if re.match(answer, action, flags=re.IGNORECASE):
- print "Action is %s."%action.lower()
-##-----------------------------
-import re, sys
-def handle_cmd(cmd):
- cmd = re.escape(cmd.strip())
- for name, action in {"edit": invoke_editor,
- "send": deliver_message,
- "list": lambda: system(pager, myfile),
- "abort": sys.exit,
- }
- if re.match(cmd, name, flags=re.IGNORECASE):
- action()
- break
- else:
- print "Unknown command:", cmd
-handle_cmd("ab")
-
-# @@PLEAC@@_6.21
-##-----------------------------
-# urlify - wrap HTML links around URL-like constructs
-import re, sys, fileinput
-
-def urlify_string(s):
- urls = r'(http|telnet|gopher|file|wais|ftp)'
-
- ltrs = r'\w';
- gunk = r'/#~:.?+=&%@!\-'
- punc = r'.:?\-'
- any = ltrs + gunk + punc
-
- pat = re.compile(r"""
- \b # start at word boundary
- ( # begin \1 {
- %(urls)s : # need resource and a colon
- [%(any)s] +? # followed by one or more
- # of any valid character, but
- # be conservative and take only
- # what you need to....
- ) # end \1 }
- (?= # look-ahead non-consumptive assertion
- [%(punc)s]* # either 0 or more punctuation
- [^%(any)s] # followed by a non-url char
- | # or else
- $ # then end of the string
- )
- """%locals(), re.VERBOSE | re.IGNORECASE)
- return re.sub(pat, r"<A HREF=\1>\1</A>", s)
-
-if __name__ == "__main__":
- for line in fileinput.input():
- print urlify_string(line)
-
-
-# @@PLEAC@@_6.22
-##-----------------------------
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_6.23
-# The majority of regexes in this section are either partially
-# or completely The Wrong Thing to Do.
-##-----------------------------
-# DON'T DO THIS. Use a Roman Numeral module, etc. (since
-# you need one anyway to calculate values)
-pat = r"^m*(d?c{0,3}|c[dm])(l?x{0,3}|x[lc])(v?i{0,3}|i[vx])$"
-re.match(pat, "mcmlxcvii")
-##-----------------------------
-txt = "one two three four five"
-
-# If the words are cleanly delimited just split and rejoin:
-word1, word2, rest = txt.split(" ", 2)
-print " ".join([word2, word1, rest])
-
-# Otherwise:
-frompat = r"(\S+)(\s+)(\S+)"
-topat = r"\3\2\1"
-print re.sub(frompat, topat, txt)
-
-##-----------------------------
-print str.split("=")
-
-# DON'T DO THIS
-pat = r"(\w+)\s*=\s*(.*)\s*$"
-print re.match(pat, "key=val").groups()
-##-----------------------------
-line = "such a very very very very very very very very very very very very very long line"
-if len(line) > 80:
- process(line)
-
-# DON'T DO THIS
-pat = ".{80,}"
-if re.match(pat, line):
- process(line)
-##-----------------------------
-dt = time.strptime("12/11/05 12:34:56", "%d/%m/%y %H:%M:%S")
-
-# DON'T DO THIS
-pat = r"(\d+)/(\d+)/(\d+) (\d+):(\d+):(\d+)"
-dt = re.match(pat, "12/11/05 12:34:56").groups()
-##-----------------------------
-txt = "/usr/bin/python"
-print txt.replace("/usr/bin", "/usr/local/bin")
-# Alternatively for file operations use os.path, shutil, etc.
-
-# DON'T DO THIS
-print re.sub("/usr/bin", "/usr/local/bin", txt)
-##-----------------------------
-import re
-
-def unescape_hex(matchobj):
- return chr(int(matchobj.groups(0)[0], 16))
-txt = re.sub(r"%([0-9A-Fa-f][0-9A-Fa-f])", unescape_hex, txt)
-
-# Assuming that the hex escaping is well-behaved, an alternative is:
-def unescape_hex(seg):
- return chr(int(seg[:2], 16)) + seg[2:]
-
-segs = txt.split("%")
-txt = segs[0] + "".join(unescape_hex(seg) for seg in segs[1:])
-##-----------------------------
-txt = re.sub(r"""
- /\* # Match the opening delimiter
- .*? # Match a minimal number of characters
- \*/ # Match the closing delimiter
- """, "", txt, re.VERBOSE)
-##-----------------------------
-txt.strip()
-
-# DON'T DO THIS
-txt = re.sub(r"^\s+", "", txt)
-txt = re.sub(r"\s+$", "", txt)
-##-----------------------------
-txt.replace("\\n", "\n")
-
-# DON'T DO THIS
-txt = re.sub("\\n", "\n", txt)
-##-----------------------------
-txt = re.sub("^.*::", "")
-##-----------------------------
-import socket
-socket.inet_aton(txt) # Will raise an error if incorrect
-
-# DON'T DO THIS.
-octseg =r"([01]?\d\d|2[0-4]\d|25[0-5])"
-dot = r"\."
-pat = "^" + octseg + dot + octseg + dot + octseg + dot + octseg + "$"
-
-if not re.match(pat, txt, re.VERBOSE)
- raise ValueError
-
-# Defitely DON'T DO THIS.
-pat = r"""^([01]?\d\d|2[0-4]\d|25[0-5])\.([01]?\d\d|2[0-4]\d|25[0-5])\.
- ([01]?\d\d|2[0-4]\d|25[0-5])\.([01]?\d\d|2[0-4]\d|25[0-5])$"""
-##-----------------------------
-fname = os.path.basename(path)
-
-# DON'T DO THIS.
-fname = re.sub("^.*/", "", path)
-##-----------------------------
-import os
-try:
- tc = os.environ["TERMCAP"]
-except KeyError:
- cols = 80
-else:
- cols = re.match(":co#(\d+):").groups(1)
-##-----------------------------
-# (not quite equivalent to the Perl version)
-name = os.path.basename(sys.argv[0])
-
-# DON'T DO THIS.
-name = re.sub("^.*/", "", sys.argv[0])
-##-----------------------------
-if sys.platform != "linux":
- raise SystemExit("This isn't Linux")
-##-----------------------------
-txt = re.sub(r"\n\s+", " ", txt)
-
-# In many cases you could just use:
-txt = txt.replace("\n", " ")
-##-----------------------------
-nums = re.findall(r"\d+\.?\d*|\.\d+", txt)
-##-----------------------------
-# If the words are clearly delimited just use:
-capwords = [word for word in txt.split() if word.isupper()]
-
-# Otherwise
-capwords = [word for word in re.findall(r"\b(\S+)\b", txt) if word.isupper()]
-
-# (probably) DON'T DO THIS.
-capwords = re.findall(r"(\b[^\Wa-z0-9_]+\b)", txt)
-##-----------------------------
-# If the words are clearly delimited just use:
-lowords = [word for word in txt.split() if word.islower()]
-
-# Otherwise
-lowords = [word for word in re.findall(r"\b(\S+)\b", txt) if word.islower()]
-
-# (probably) DON'T DO THIS.
-lowords = re.findall(r"(\b[^\WA-Z0-9_]+\b)", txt)
-##-----------------------------
-# If the words are clearly delimited just use:
-icwords = [word for word in txt.split() if word.istitle()]
-
-# Otherwise
-icwords = [word for word in re.finditer(r"\b(\S+)\b") if word.istitle()]
-
-# DON'T DO THIS.
-icwords = re.findall(r"(\b[^\Wa-z0-9_][^\WA-Z0-9_]*\b)", txt)
-##-----------------------------
-# DON'T DO THIS - use HTMLParser, etc.
-links = re.findall(r"""<A[^>]+?HREF\s*=\s*["']?([^'" >]+?)[ '"]?>""", txt)
-##-----------------------------
-names = txt.split()
-if len(names) == 3:
- initial = names[1][0]
-else:
- initial = ""
-
-# DON'T DO THIS.
-pat = "^\S+\s+(\S)\S*\s+\S"
-try:
- initial = re.match(pat, txt).group(1)
-except AttributeError:
- initial = ""
-##-----------------------------
-txt = re.sub('"([^"]*)"', "``\1''", txt)
-##-----------------------------
-sentences = [elem[0] for elem in re.findall(r"(.*?[!?.])( |\Z)", s)]
-##-----------------------------
-import time
-dt = time.strptime(txt, "%Y-%m-%d")
-
-# DON'T DO THIS.
-year, month, day = re.match(r"(\d{4})-(\d\d)-(\d\d)", txt).groups()
-##-----------------------------
-pat = r"""
- ^
- (?:
- 1 \s (?: \d\d\d \s)? # 1, or 1 and area code
- | # ... or ...
- \(\d\d\d\) \s # area code with parens
- | # ... or ...
- (?: \+\d\d?\d? \s)? # optional +country code
- \d\d\d ([\s\-]) # and area code
- )
- \d\d\d (\s|\1) # prefix (and area code separator)
- \d\d\d\d # exchange
- $
- """
-re.match(pat, txt, re.VERBOSE)
-##-----------------------------
-re.match(r"\boh\s+my\s+gh?o(d(dess(es)?|s?)|odness|sh)\b", txt, re.IGNORECASE)
-##-----------------------------
-for line in file(fname, "Ur"): #Universal newlines
- process(line)
-
-# DON'T DO THIS
-lines = [re.sub(r"^([^\012\015]*)(\012\015?|\015\012?)", "", line)
- for line in file(fname)]
-##-----------------------------
-
-
-# @@PLEAC@@_7.0
-for line in open("/usr/local/widgets/data"):
- if blue in line:
- print line[:-1]
-#---------
-import sys, re
-pattern = re.compile(r"\d")
-for line in sys.stdin:
- if not pattern.search(line):
- sys.stderr.write("No digit found.\n")
- sys.stdout.write("Read: " + line)
-sys.stdout.close()
-#---------
-logfile = open("/tmp/log", "w")
-#---------
-logfile.close()
-#---------
-print>>logfile, "Countdown initiated ..."
-print "You have 30 seconds to reach minimum safety distance."
-
-# DONT DO THIS
-import sys
-old_output, sys.stdout = sys.stdout, logfile
-print "Countdown initiated ..."
-sys.stdout = old_output
-print "You have 30 seconds to reach minimum safety distance."
-#---------
-
-# @@PLEAC@@_7.1
-# Python's open() function somewhat covers both perl's open() and
-# sysopen() as it has optional arguments for mode and buffering.
-source = open(path)
-sink = open(path, "w")
-#---------
-# NOTE: almost no one uses the low-level os.open and os.fdopen
-# commands, so their inclusion here is just silly. If
-# os.fdopen(os.open(...)) were needed often, it would be turned
-# into its own function. Instead, I'll use 'fd' to hint that
-# os.open returns a file descriptor
-import os
-source_fd = os.open(path, os.O_RDONLY)
-source = os.fdopen(fd)
-sink_fd = os.open(path, os.O_WRONLY)
-sink = os.fdopen(sink_fd)
-#---------
-myfile = open(filename, "w")
-fd = os.open(filename, os.O_WRONLY | os.O_CREAT)
-myfile = open(filename, "r+")
-#---------
-fd = os.open(name, flags)
-fd = os.open(name, flags, mode)
-#---------
-myfile = open(path)
-fd = os.open(path, os.O_RDONLY)
-#-----------------------------
-myfile = open(path, "w")
-fd = os.open(path, os.O_WRONLY|os.O_TRUNC|os.O_CREAT)
-fd = os.open(path, os.O_WRONLY|os.O_TRUNC|os.O_CREAT, 0600)
-#-----------------------------
-fd = os.open(path, os.O_WRONLY|os.O_EXCL|os.O_CREAT)
-fd = os.open(path, os.O_WRONLY|os.O_EXCL|os.O_CREAT, 0600)
-#-----------------------------
-myfile = open(path, "a")
-fd = os.open(path, os.O_WRONLY|os.O_APPEND|os.O_CREAT)
-fd = os.open(path, os.O_WRONLY|os.O_APPEND|s.O_CREAT, 0600)
-#-----------------------------
-fd = os.open(path, os.O_WRONLY|os.O_APPEND)
-#-----------------------------
-myfile = open(path, "rw")
-fd = os.open(path, os.O_RDWR)
-#-----------------------------
-fd = os.open(path, os.O_RDWR|os.O_CREAT)
-fd = os.open(path, os.O_RDWR|os.O_CREAT, 0600)
-#-----------------------------
-fd = os.open(path, os.O_RDWR|os.O_EXCL|os.O_CREAT)
-fd = os.open(path, os.O_RDWR|os.O_EXCL|os.O_CREAT, 0600)
-#-----------------------------
-
-# @@PLEAC@@_7.2
-# Nothing different needs to be done with Python
-
-# @@PLEAC@@_7.3
-import os
-filename = os.path.expanduser(filename)
-
-# @@PLEAC@@_7.4
-myfile = open(filename) # raise an exception on error
-
-try:
- myfile = open(filename)
-except IOError, err:
- raise AssertionError("Couldn't open %s for reading : %s" %
- (filename, err.strerror))
-
-# @@PLEAC@@_7.5
-import tempfile
-
-myfile = tempfile.TemporaryFile()
-
-#-----------------------------
-# NOTE: The TemporaryFile() call is much more appropriate
-# I would not suggest using this code for real work.
-import os, tempfile
-
-while True:
- name = os.tmpnam()
- try:
- fd = os.open(name, os.O_RDWR|os.O_CREAT|os.O_EXCL)
- break
- except os.error:
- pass
-myfile = tempfile.TemporaryFileWrapper(os.fdopen(fd), name)
-
-# now go on to use the file ...
-#-----------------------------
-import os
-while True:
- tmpname = os.tmpnam()
- fd = os.open(tmpnam, os.O_RDWR | os.O_CREAT | os.O_EXCL)
- if fd:
- tmpfile = os.fdopen(fd)
- break
-
-os.remove(tmpnam)
-
-#-----------------------------
-import tempfile
-
-myfile = tempfile.TemporaryFile(bufsize = 0)
-for i in range(10):
- print>>myfile, i
-myfile.seek(0)
-print "Tmp file has:", myfile.read()
-#-----------------------------
-
-# @@PLEAC@@_7.6
-DATA = """\
-your data goes here
-"""
-for line in DATA.split("\n"):
- pass # process the line
-
-# @@PLEAC@@_7.7
-
-for line in sys.stdin:
- pass # do something with the line
-
-# processing a list of files from commandline
-import fileinput
-for line in fileinput.input():
- do something with the line
-
-#-----------------------------
-import sys
-
-def do_with(myfile):
- for line in myfile:
- print line[:-1]
-
-filenames = sys.argv[1:]
-if filenames:
- for filename in filenames:
- try:
- do_with(open(filename))
- except IOError, err:
- sys.stderr.write("Can't open %s: %s\n" % (filename, err.strerror))
- continue
-else:
- do_with(sys.stdin)
-
-#-----------------------------
-import sys, glob
-ARGV = sys.argv[1:] or glob.glob("*.[Cch]")
-#-----------------------------
-# NOTE: the getopt module is the prefered mechanism for reading
-# command line arguments
-import sys
-args = sys.argv[1:]
-chop_first = 0
-
-if args and args[0] == "-c":
- chop_first += 1
- args = args[1:]
-
-# arg demo 2: Process optional -NUMBER flag
-
-# NOTE: You just wouldn't process things this way for Python,
-# but I'm trying to preserve the same semantics.
-
-import sys, re
-digit_pattern = re.compile(r"-(\d+)$")
-
-args = sys.argv[1:]
-if args:
- match = digit_pattern.match(args[0])
- if match:
- columns = int(match.group(1))
- args = args[1:]
-
-# NOTE: here's the more idiomatic way, which also checks
-# for the "--" or a non "-" argument to stop processing
-
-args = sys.argv[1:]
-for i in range(len(args)):
- arg = args[i]
- if arg == "--" or not arg.startwith("-"):
- break
- if arg[1:].isdigit():
- columns = int(arg[1:])
- continue
-
-
-
-# arg demo 3: Process clustering -a, -i, -n, or -u flags
-import sys, getopt
-try:
- args, filenames = getopt.getopt(sys.argv[1:], "ainu")
-except getopt.error:
- raise SystemExit("usage: %s [-ainu] [filenames] ..." % sys.argv[0])
-
-append = ignore_ints = nostdout = unbuffer = 0
-for k, v in args:
- if k == "-a": append += 1
- elif k == "-i": ignore_ints += 1
- elif k == "-n": nostdout += 1
- elif k == "-u": unbuffer += 1
- else:
- raise AssertionError("Unexpected argument: %s" % k)
-
-#-----------------------------
-# Note: Idiomatic Perl get translated to idiomatic Python
-import fileinput
-for line in fileinput.input():
- sys.stdout.write("%s:%s:%s" %
- (fileinput.filename(), fileinput.filelineno(), line))
-#-----------------------------
-#!/usr/bin/env python
-# findlogin1 - print all lines containing the string "login"
-for line in fileinput.input(): # loop over files on command line
- if line.find("login") != -1:
- sys.stdout.write(line)
-
-#-----------------------------
-#!/usr/bin/env python
-# lowercase - turn all lines into lowercase
-### NOTE: I don't know how to do locales in Python
-for line in fileinput.input(): # loop over files on command line
- sys.stdout.write(line.lower())
-
-#-----------------------------
-#!/usr/bin/env python
-# NOTE: The Perl code appears buggy, in that "Q__END__W" is considered
-# to be a __END__ and words after the __END__ on the same line
-# are included in the count!!!
-# countchunks - count how many words are used.
-# skip comments, and bail on file if __END__
-# or __DATA__ seen.
-chunks = 0
-for line in fileinput.input():
- for word in line.split():
- if word.startswith("#"):
- continue
- if word in ("__DATA__", "__END__"):
- fileinput.close()
- break
- chunks += 1
-print "Found", chunks, "chunks"
-
-
-# @@PLEAC@@_7.8
-import shutil
-
-old = open("old")
-new = open("new","w")
-
-for line in old:
- new.writeline(line)
-new.close()
-old.close()
-
-shutil.copyfile("old", "old.orig")
-shutil.copyfile("new", "old")
-
-# insert lines at line 20:
-for i, line in enumerate(old):
- if i == 20:
- print>>new, "Extra line 1\n"
- print>>new, "Extra line 2\n"
- print>>new, line
-
-
-# or delete lines 20 through 30:
-for i, line in enumerate(old):
- if 20 <= i <= 30:
- continue
- print>>new, line
-
-
-# @@PLEAC@@_7.9
-# modifying with "-i" commandline switch is a perl feature
-# python has fileinput
-import fileinput, sys, time
-today = time.strftime("%Y-%m-%d",time.localtime())
-for line in fileinput.input(inplace=1, backup=".orig"):
- sys.stdout.write(line.replace("DATE",today))
-
-# set up to iterate over the *.c files in the current directory,
-# editing in place and saving the old file with a .orig extension.
-import glob, re
-match = re.compile("(?<=[pP])earl")
-files = fileinput.FileInput(glob.glob("*.c"), inplace=1, backup=".orig")
-while True:
- line = files.readline()
- sys.stderr.write(line)
- if not line:
- break
- if files.isfirstline():
- sys.stdout.write("This line should appear at the top of each file\n")
- sys.stdout.write(match.sub("erl",line))
-
-
-# @@PLEAC@@_7.10
-#-----------------------------
-myfile = open(filename, "r+")
-data = myfile.read()
-# change data here
-myfile.seek(0, 0)
-myfile.write(data)
-myfile.truncate(myfile.tell())
-myfile.close()
-#-----------------------------
-myfile = open(filename, "r+")
-data = [process(line) for line in myfile]
-myfile.seek(0, 0)
-myfile.writelines(data)
-myfile.truncate(myfile.tell())
-myfile.close()
-#-----------------------------
-
-# @@PLEAC@@_7.11
-
-import fcntl
-myfile = open(somepath, 'r+')
-fcntl.flock(myfile, fcntl.LOCK_EX)
-# update file, then...
-myfile.close()
-#-----------------------------
-fcntl.LOCK_SH
-fcntl.LOCK_EX
-fcntl.LOCK_NB
-fcntl.LOCK_UN
-#-----------------------------
-import warnings
-try:
- fcntl.flock(myfile, fcntl.LOCK_EX|fcntl.LOCK_NB)
-except IOError:
- warnings.warn("can't immediately write-lock the file ($!), blocking ...")
- fcntl.flock(myfile, fcntl.LOCK_EX)
-#-----------------------------
-fcntl.flock(myfile, fcntl.LOCK_UN)
-#-----------------------------
-# option "r+" instead "w+" stops python from truncating the file on opening
-# when another process might well hold an advisory exclusive lock on it.
-myfile = open(somepath, "r+")
-fcntl.flock(myfile, fcntl.LOCK_EX)
-myfile.seek(0, 0)
-myfile.truncate(0)
-print>>myfile, "\n" # or myfile.write("\n")
-myfile.close()
-#-----------------------------
-
-# @@PLEAC@@_7.12
-# Python doesn't have command buffering. Files can have buffering set,
-# when opened:
-myfile = open(filename, "r", buffering=0) #Unbuffered
-myfile = open(filename, "r", buffering=1) #Line buffered
-myfile = open(filename, "r", buffering=100) #Use buffer of (approx) 100 bytes
-myfile = open(filename, "r", buffering=-1) #Use system default
-
-myfile.flush() # Flush the I/O buffer
-
-# stdout is treated as a file. If you ever need to flush it, do so:
-import sys
-sys.stdout.flush()
-
-# DON'T DO THIS. Use urllib, etc.
-import socket
-mysock = socket.socket()
-mysock.connect(('www.perl.com', 80))
-# mysock.setblocking(True)
-mysock.send("GET /index.html http/1.1\n\n")
-f = mysock.makefile()
-print "Doc is:"
-for line in f:
- print line[:-1]
-
-# @@PLEAC@@_7.13
-import select
-while True:
- rlist, wlist, xlist = select.select([file1, file2, file3], [], [], 0)
- for r in rlist:
- pass # Do something with the file handle
-
-# @@PLEAC@@_7.14
-# @@SKIP@@ Use select.poll() on Unix systems.
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_7.15
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_7.16
-# NOTE: this is all much easier in Python
-def subroutine(myfile):
- print>>myfile, "Hello, file"
-
-variable = myfile
-subroutine(variable)
-
-# @@PLEAC@@_7.17
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_7.18
-for myfile in files:
- print>>myfile, stuff_to_print
-
-# NOTE: This is unix specific
-import os
-file = os.popen("tee file1 file2 file3 >/dev/null", "w")
-print>>myfile, "whatever"
-
-# NOTE: the "make STDOUT go to three files" is bad programming style
-import os, sys
-sys.stdout.file = os.popen("tee file1 file2 file3", "w")
-print "whatever"
-sys.stdout.close()
-
-# You could use a utility object to redirect writes:
-class FileDispatcher(object):
- def __init__(self, *files):
- self.files = files
-
- def write(self, msg):
- for f in self.files:
- f.write(msg)
-
- def close(self):
- for f in self.files:
- f.close()
-
-x = open("C:/test1.txt", "w")
-y = open("C:/test2.txt", "w")
-z = open("C:/test3.txt", "w")
-
-fd = FileDispatcher(x, y, z)
-print>>fd, "Foo" # equiv to fd.write("Foo"); fd.write("\n")
-print>>fd, "Testing"
-fd.close()
-
-# @@PLEAC@@_7.19
-import os
-myfile = os.fdopen(fdnum) # open the descriptor itself
-myfile = os.fdopen(os.dup(fdnum)) # open to a copy of the descriptor
-
-###
-outcopy = os.fdopen(os.dup(sys.stdin.fileno()), "w")
-incopy = os.fdopen(os.dup(sys.stdin.fileno()), "r")
-
-# @@PLEAC@@_7.20
-original = open("C:/test.txt")
-alias = original
-alias.close()
-print original.closed
-#=>True
-
-import copy
-
-original = open("C:/test.txt")
-dupe = copy.copy(original)
-dupe.close()
-print original.closed
-#=>False
-
-# DON'T DO THIS.
-import sys
-oldstderr = sys.stderr
-oldstdout = sys.stdout
-
-sys.stderr = open("C:/stderrfile.txt")
-sys.stdout = open("C:/stdoutfile.txt")
-
-print "Blah" # Will be written to C:/stdoutfile.txt
-sys.stdout.close()
-
-sys.stdout = oldstdout
-sys.stderr = oldstderr
-
-
-# @@PLEAC@@_7.21
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_7.22
-# On Windows:
-import msvcrt
-myfile.seek(5, 0)
-msvcrt.locking(myfile.fileno(), msvcrt.LK_NBLCK, 3)
-
-# On Unix:
-import fcntl
-fcntl.lockf(myfile.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB, 3, 5)
-
-
-# ^^PLEAC^^_8.0
-#-----------------------------
-for line in DATAFILE:
- line = line.rstrip()
- size = len(line)
- print size # output size of line
-
-#-----------------------------
-for line in datafile:
- print length(line.rstrip()) # output size of line
-#-----------------------------
-lines = datafile.readlines()
-#-----------------------------
-whole_file = myfile.read()
-#-----------------------------
-## No direct equivalent in Python
-#% perl -040 -e '$word = <>; print "First word is $word\n";'
-#-----------------------------
-## No direct equivalent in Python
-#% perl -ne 'BEGIN { $/="%%\n" } chomp; print if /Unix/i' fortune.dat
-#-----------------------------
-print>>myfile, "One", "two", "three" # "One two three"
-print "Baa baa black sheep." # Sent to default output file
-#-----------------------------
-buffer = myfile.read(4096)
-rv = len(buffer)
-#-----------------------------
-myfile.truncate(length)
-open("/tmp/%d.pid" % os.getpid(), "a").truncate(length)
-#-----------------------------
-pos = myfile.tell()
-print "I'm", pos, "bytes from the start of DATAFILE."
-#-----------------------------
-logfile.seek(0, 2) # Seek to the end
-datafile.seek(pos) # Seek to a given byte
-outfile.seek(-20, 1) # Seek back 20 bytes
-#-----------------------------
-written = os.write(datafile.fileno(), mystr)
-if written != len(mystr):
- warnings.warn("only read %s bytes, not %s" % (written, len(mystr)))
-#-----------------------------
-pos = os.lseek(myfile.fileno(), 0, 1) # don't change position
-#-----------------------------
-
-
-# ^^PLEAC^^_8.1
-def ContReader(infile):
- lines = []
- for line in infile:
- line = line.rstrip()
- if line.endswith("\\"):
- lines.append(line[:-1])
- continue
- lines.append(line)
- yield "".join(lines)
- lines = []
- if lines:
- yield "".join(lines)
-
-for line in ContReader(datafile):
- pass # process full record in 'line' here
-
-# ^^PLEAC^^_8.2
-import os
-count = int(os.popen("wc -l < " + filename).read())
-#-----------------------------
-for count, line in enumerate(open(filename)):
- pass
-count += 1 # indexing is zero based
-#-----------------------------
-myfile = open(filename)
-count = 0
-for line in myfile:
- count += 1
-# 'count' now holds the number of lines read
-#-----------------------------
-myfile = open(filename)
-count = 0
-while True:
- line = myfile.readline()
- if not line:
- break
- count += 1
-#-----------------------------
-count = 0
-while True:
- s = myfile.read(2**16)
- count += s.count("\n")
-#-----------------------------
-for line, count in zip(open(filename), xrange(1, sys.maxint)):
- pass
-# 'count' now holds the number of lines read
-#-----------------------------
-import fileinput
-fi = fileinput.FileInput(filename)
-while fi.readline(): pass
-
-count = fi.lineno()
-#-----------------------------
-def SepReader(infile, sep = "\n\n"):
- text = infile.read(10000)
- if not text:
- return
- while True:
- fields = text.split(sep)
- for field in fields[:-1]:
- yield field
- text = fields[-1]
- new_text = infile.read(10000)
- if not new_text:
- yield text
- break
- text += new_text
-
-para_count = 0
-for para in SepReader(open(filename)):
- para_count += 1
-# FIXME: For my test case (Python-pre2.2 README from CVS) this
-# returns 175 paragraphs while Perl returns 174.
-#-----------------------------
-
-
-# ^^PLEAC^^_8.3
-for line in sys.stdin:
- for word in line.split():
- pass # do something with 'chunk'
-#-----------------------------
-pat = re.compile(r"(\w[\w'-]*)")
-for line in sys.stdin:
- pos = 0
- while True:
- match = pat.search(line, pos)
- if not match:
- break
- pos = match.end(1)
- # do something with match.group(1)
-
-# EXPERIMENTAL in the sre implementation but
-# likely to be included in future (post-2.2) releases.
-pat = re.compile(r"(\w[\w'-]*)")
-for line in sys.stdin:
- scanner = pat.scanner(line)
- while True:
- match = scanner.search()
- if not match:
- break
- # do something with match.group(1)
-
-
-#-----------------------------
-# Make a word frequency count
-import fileinput, re
-pat = re.compile(r"(\w[\w'-]*)")
-seen = {}
-for line in fileinput.input():
- pos = 0
- while True:
- match = pat.search(line, pos)
- if not match:
- break
- pos = match.end(1)
- text = match.group(1).lower()
- seen[text] = seen.get(text, 0) + 1
-
-# output dict in a descending numeric sort of its values
-for text, count in sorted(seen.items, key=lambda item: item[1]):
- print "%5d %s" % (count, text)
-
-#-----------------------------
-# Line frequency count
-import fileinput, sys
-seen = {}
-for line in fileinput.input():
- text = line.lower()
- seen[text] = seen.get(text, 0) + 1
-
-for text, count in sorted(seen.items, key=lambda item: item[1]):
- sys.stdout.write("%5d %s" % (count, text))
-
-#-----------------------------
-
-
-# ^^PLEAC^^_8.4
-lines = myfile.readlines()
-while lines:
- line = lines.pop()
- # do something with 'line'
-
-#-----------------------------
-for line in reversed(myfile):
- pass # do something with line
-#-----------------------------
-for i in range(len(lines)):
- line = lines[-i]
-#-----------------------------
-for paragraph in sorted(SepReader(infile)):
- pass # do something
-#-----------------------------
-
-
-
-# ^^PLEAC^^_8.5
-import time
-while True:
- for line in infile:
- pass # do something with the line
- time.sleep(SOMETIME)
- infile.seek(0, 1)
-#-----------------------------
-import time
-naptime = 1
-
-logfile = open("/tmp/logfile")
-while True:
- for line in logfile:
- print line.rstrip()
- time.sleep(naptime)
- infile.seek(0, 1)
-#-----------------------------
-while True:
- curpos = logfile.tell()
- while True:
- line = logfile.readline()
- if not line:
- break
- curpos = logfile.tell()
- sleep(naptime)
- logfile.seek(curpos, 0) # seek to where we had been
-#-----------------------------
-import os
-if os.stat(LOGFILENAME).st_nlink == 0:
- raise SystemExit
-#-----------------------------
-
-
-# ^^PLEAC^^_8.6
-import random, fileinput
-text = None
-for line in fileinput.input():
- if random.randrange(fileinput.lineno()) == 0:
- text = line
-# 'text' is the random line
-#-----------------------------
-# XXX is the perl code correct? Where is the fortunes file opened?
-import sys
-adage = None
-for i, rec in enumerate(SepReader(open("/usr/share/games/fortunes"), "%\n")):
- if random.randrange(i+1) == 0:
- adage = rec
-print adage
-#-----------------------------
-
-
-# ^^PLEAC^^_8.7
-import random
-lines = data.readlines()
-random.shuffle(lines)
-for line in lines:
- print line.rstrip()
-#-----------------------------
-
-
-
-# ^^PLEAC^^_8.8
-# using efficient caching system
-import linecache
-linecache.getline(filename, DESIRED_LINE_NUMBER)
-
-# or doing it more oldskool
-lineno = 0
-while True:
- line = infile.readline()
- if not line or lineno == DESIRED_LINE_NUMBER:
- break
- lineno += 1
-#-----------------------------
-lines = infile.readlines()
-line = lines[DESIRED_LINE_NUMBER]
-#-----------------------------
-for i in range(DESIRED_LINE_NUMBER):
- line = infile.readline()
- if not line:
- break
-#-----------------------------
-
-## Not sure what this thing is doing. Allow fast access to a given
-## line number?
-
-# usage: build_index(*DATA_HANDLE, *INDEX_HANDLE)
-
-# ^^PLEAC^^_8.9
-# given $RECORD with field separated by PATTERN,
-# extract @FIELDS.
-fields = re.split(pattern_string, text)
-#-----------------------------
-pat = re.compile(pattern_string)
-fields = pat.split(text)
-#-----------------------------
-re.split(r"([+-])", "3+5-2")
-#-----------------------------
-[3, '+', 5, '-', 2]
-#-----------------------------
-fields = record.split(":")
-#-----------------------------
-fields = re.split(r":", record)
-#-----------------------------
-fields = re.split(r"\s+", record)
-#-----------------------------
-fields = record.split(" ")
-#-----------------------------
-
-
-# ^^PLEAC^^_8.10
-myfile = open(filename, "r")
-prev_pos = pos = 0
-while True:
- line = myfile.readline()
- if not line:
- break
- prev_pos = pos
- pos = myfile.tell()
-myfile = open(filename, "a")
-myfile.truncate(prev_pos)
-#-----------------------------
-
-
-
-# ^^PLEAC^^_8.11
-open(filename, "rb")
-open(filename, "wb")
-#-----------------------------
-gifname = "picture.gif"
-gif_file = open(gifname, "rb")
-
-# Don't think there's an equivalent for these in Python
-#binmode(GIF); # now DOS won't mangle binary input from GIF
-#binmode(STDOUT); # now DOS won't mangle binary output to STDOUT
-
-#-----------------------------
-while True:
- buff = gif.read(8 * 2**10)
- if not buff:
- break
- sys.stdout.write(buff)
-#-----------------------------
-
-
-
-# ^^PLEAC^^_8.12
-address = recsize * recno
-myfile.seek(address, 0)
-buffer = myfile.read(recsize)
-#-----------------------------
-address = recsize * (recno-1)
-#-----------------------------
-
-
-
-# ^^PLEAC^^_8.13
-import posixfile
-address = recsize * recno
-myfile.seek(address)
-buffer = myfile.read(recsize)
-# ... work with the buffer, then turn it back into a string and ...
-myfile.seek(-recsize, posixfile.SEEK_CUR)
-myfile.write(buffer)
-myfile.close()
-#-----------------------------
-## Not yet implemented
-# weekearly -- set someone's login date back a week
-# @@INCOMPLETE@@
-
-
-# ^^PLEAC^^_8.14
-## Note: this isn't optimal -- the 's+=c' may go O(N**2) so don't
-## use for large strings.
-myfile.seek(addr)
-s = ""
-while True:
- c = myfile.read(1)
- if not c or c == "\0":
- break
- s += c
-#-----------------------------
-myfile.seek(addr)
-offset = 0
-while True:
- s = myfile.read(1000)
- x = s.find("\0")
- if x != -1:
- offset += x
- break
- offset += len(s)
- if len(s) != 1000: # EOF
- break
-myfile.seek(addr)
-s = myfile.read(offset - 1)
-myfile.read(1)
-
-#-----------------------------
-## Not Implemented
-# bgets - get a string from an address in a binary file
-#-----------------------------
-#!/usr/bin/perl
-# strings - pull strings out of a binary file
-import re, sys
-
-## Assumes SepReader from above
-
-pat = re.compile(r"([\040-\176\s]{4,})")
-for block in SepReader(sys.stdin, "\0"):
- pos = 0
- while True:
- match = pat.search(block, pos)
- if not match:
- break
- print match.group(1)
- pos = match.end(1)
-#-----------------------------
-
-
-# @@PLEAC@@_8.15
-
-# RECORDSIZE is the length of a record, in bytes.
-# TEMPLATE is the unpack template for the record
-# FILE is the file to read from
-# FIELDS is a tuple, one element per field
-import struct
-RECORDSIZE= struct.calcsize(TEMPLATE)
-while True:
- record = FILE.read(RECORDSIZE):
- if len(record)!=RECORDSIZE:
- raise "short read"
- FIELDS = struct.unpack(TEMPLATE, record)
-# ----
-
-
-# ^^PLEAC^^_8.16
-# NOTE: to parse INI file, see the stanard ConfigParser module.
-import re
-pat = re.compile(r"\s*=\s*")
-for line in config_file:
- if "#" in line: # no comments
- line = line[:line.index("#")]
- line = line.strip() # no leading or trailing white
- if not line: # anything left?
- continue
- m = pat.search(line)
- var = line[:m.start()]
- value = line[m.end():]
- User_Preferences[var] = value
-
-
-# ^^PLEAC^^_8.17
-import os
-
-mode, ino, dev, nlink, uid, gid, size, \
-atime, mtime, ctime = os.stat(filename)
-
-mode &= 07777 # discard file type info
-
-#-----------------------------
-info = os.stat(filename)
-if info.st_uid == 0:
- print "Superuser owns", filename
-if info.st_atime > info.st_mtime:
- print filename, "has been read since it was written."
-#-----------------------------
-import os
-def is_safe(path):
- info = os.stat(path)
-
- # owner neither superuser nor me
- # the real uid is in stored in the $< variable
- if info.st_uid not in (0, os.getuid()):
- return False
-
- # check whether group or other can write file.
- # use 066 to detect either reading or writing
- if info.st_mode & 022: # someone else can write this
- if not os.path.isdir(path): # non-directories aren't safe
- return False
- # but directories with the sticky bit (01000) are
- if not (info.st_mode & 01000):
- return False
- return True
-#-----------------------------
-## XXX What is '_PC_CHOWN_RESTRICTED'?
-
-def is_verysafe(path):
- terms = []
- while True:
- path, ending = os.path.split(path)
- if not ending:
- break
- terms.insert(0, ending)
- for term in terms:
- path = os.path.join(path, term)
- if not is_safe(path):
- return False
- return True
-#-----------------------------
-
-# Program: tctee
-# Not Implemented (requires reimplementing Perl's builtin '>>', '|',
-# etc. semantics)
-
-# @@PLEAC@@_8.18
-#!/usr/bin/python
-# tailwtmp - watch for logins and logouts;
-# uses linux utmp structure, from /usr/include/bits/utmp.h
-
-# /* The structure describing an entry in the user accounting database. */
-# struct utmp
-# {
-# short int ut_type; /* Type of login. */
-# pid_t ut_pid; /* Process ID of login process. */
-# char ut_line[UT_LINESIZE]; /* Devicename. */
-# char ut_id[4]; /* Inittab ID. */
-# char ut_user[UT_NAMESIZE]; /* Username. */
-# char ut_host[UT_HOSTSIZE]; /* Hostname for remote login. */
-# struct exit_status ut_exit; /* Exit status of a process marked
-# as DEAD_PROCESS. */
-# long int ut_session; /* Session ID, used for windowing. */
-# struct timeval ut_tv; /* Time entry was made. */
-# int32_t ut_addr_v6[4]; /* Internet address of remote host. */
-# char __unused[20]; /* Reserved for future use. */
-# };
-
-# /* Values for the `ut_type' field of a `struct utmp'. */
-# #define EMPTY 0 /* No valid user accounting information. */
-#
-# #define RUN_LVL 1 /* The system's runlevel. */
-# #define BOOT_TIME 2 /* Time of system boot. */
-# #define NEW_TIME 3 /* Time after system clock changed. */
-# #define OLD_TIME 4 /* Time when system clock changed. */
-#
-# #define INIT_PROCESS 5 /* Process spawned by the init process. */
-# #define LOGIN_PROCESS 6 /* Session leader of a logged in user. */
-# #define USER_PROCESS 7 /* Normal process. */
-# #define DEAD_PROCESS 8 /* Terminated process. */
-#
-# #define ACCOUNTING 9
-
-import time
-import struct
-import os
-
-class WTmpRecord:
- fmt = "hI32s4s32s256siili4l20s";
- _fieldnames = ["type","PID","Line","inittab","User","Hostname",
- "exit_status", "session", "time", "addr" ]
- def __init__(self):
- self._rec_size = struct.calcsize(self.fmt)
- def size(self):
- return self._rec_size
- def unpack(self, bin_data):
- rec = struct.unpack(self.fmt, bin_data)
- self._rec = []
- for i in range(len(rec)):
- if i in (2,3,4,5):
- # remove character zeros from strings
- self._rec.append( rec[i].split("\0")[0] )
- else:
- self._rec.append(rec[i])
- return self._rec
- def fieldnames(self):
- return self._fieldnames
- def __getattr__(self,name):
- return self._rec[self._fieldnames.index(name)]
-
-rec = WTmpRecord()
-f = open("/var/log/wtmp","rb")
-f.seek(0,2)
-while True:
- while True:
- bin = f.read(rec.size())
- if len(bin) != rec.size():
- break
- rec.unpack(bin)
- if rec.type != 0:
- print " %1d %-8s %-12s %-24s %-20s %5d %08x" % \
- (rec.type, rec.User, rec.Line,
- time.strftime("%a %Y-%m-%d %H:%M:%S",time.localtime(rec.time)),
- rec.Hostname, rec.PID, rec.addr)
- time.sleep(1)
-f.close()
-
-# @@PLEAC@@_8.19
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_8.20
-#!/usr/bin/python
-# laston - find out when given user last logged on
-import sys
-import struct
-import pwd
-import time
-import re
-
-f = open("/var/log/lastlog","rb")
-
-fmt = "L32s256s"
-rec_size = struct.calcsize(fmt)
-
-for user in sys.argv[1:]:
- if re.match(r"^\d+$", user):
- user_id = int(user)
- else:
- try:
- user_id = pwd.getpwnam(user)[2]
- except:
- print "no such uid %s" % (user)
- continue
- f.seek(rec_size * user_id)
- bin = f.read(rec_size)
- if len(bin) == rec_size:
- data = struct.unpack(fmt, bin)
- if data[0]:
- logged_in = "at %s" % (time.strftime("%a %H:%M:%S %Y-%m-%d",
- time.localtime(data[0])))
- line = " on %s" % (data[1])
- host = " from %s" % (data[2])
- else:
- logged_in = "never logged in"
- line = ""
- host = ""
- print "%-8s UID %5d %s%s%s" % (user, user_id, logged_in, line, host)
- else:
- print "Read failed."
-f.close()
-
-
-# ^^PLEAC^^_9.0
-#-----------------------------
-entry = os.stat("/usr/bin/vi")
-#-----------------------------
-entry = os.stat("/usr/bin")
-#-----------------------------
-entry = os.stat(INFILE.name)
-#-----------------------------
-entry = os.stat("/usr/bin/vi")
-ctime = entry.st_ino
-size = entry.st_size
-#-----------------------------
-f = open(filename)
-
-f.seek(0, 2)
-if not f.tell():
- raise SystemExit("%s doesn't have text in it."%filename)
-#-----------------------------
-
-for filename in os.listdir("/usr/bin"):
- print "Inside /usr/bin is something called", filename
-#-----------------------------
-
-# ^^PLEAC^^_9.1
-#-----------------------------
-fstat = os.stat(filename)
-readtime = fstat.st_atime
-writetime = fstat.st_mtime
-
-os.utime(filename, (newreadtime, newwritetime))
-
-#DON'T DO THIS:
-readtime, writetime = os.stat(filename)[7:9]
-#-----------------------------
-SECONDS_PER_DAY = 60 * 60 * 24
-fstat = os.stat(filename)
-atime = fstat.st_atime - 7 * SECONDS_PER_DAY
-mtime = fstat.st_mtime - 7 * SECONDS_PER_DAY
-
-os.utime(filename, (atime, mtime))
-#-----------------------------
-mtime = os.stat(filename).st_mtime
-utime(filename, (time.time(), mtime))
-#-----------------------------
-#!/usr/bin/perl -w
-# uvi - vi a file without changing its access times
-
-import sys, os
-if len(sys.argv) != 2:
- raise SystemExit("usage: uvi filename")
-filename = argv[1]
-fstat = os.stat(filename)
-# WARNING: potential security risk
-os.system( (os.environ.get("EDITOR") or "vi") + " " + filename)
-os.utime(filename, (fstat.st_atime, fstat.st_mtime))
-#-----------------------------
-
-# ^^PLEAC^^_9.2
-#-----------------------------
-os.remove(filename)
-
-err_flg = 0
-for filename in filenames:
- try:
- os.remove(filename)
- except OSError, err:
- err_flg = 1
-if err_flg:
- raise OSError("Couldn't remove all of %s: %s" % (filenames, err))
-#-----------------------------
-os.remove(filename)
-#-----------------------------
-success = 0
-for filename in filenames:
- try:
- os.remove(filename)
- success += 1
- except OSError, err:
- pass
-if success != len(filenames):
- sys.stderr.write("could only delete %d of %d files" % \
- (success, len(filenames)))
-
-#-----------------------------
-
-# ^^PLEAC^^_9.3
-#-----------------------------
-import shutil
-shutil.copy(oldfile, newfile)
-#-----------------------------
-## NOTE: this doesn't do the same thing as the Perl code,
-## eg, handling of partial writes.
-infile = open(oldfile)
-outfile = open(newfile, "w")
-
-blksize = 16384 # preferred block size?
-
-while True:
- buf = infile.read(blksize)
- if not buf:
- break
- outfile.write(buf)
-
-infile.close()
-outfile.close()
-#-----------------------------
-# WARNING: these are insecure - do not use in hostile environments
-os.system("cp %s %s" % (oldfile, newfile)) # unix
-os.system("copy %s %s" % (oldfile, newfile)) # dos, vms
-#-----------------------------
-import shutil
-
-shutil.copy("datafile.dat", "datafile.bak")
-
-shutil.copy("datafile.new", "datafile.dat")
-os.remove("datafile.new")
-
-#-----------------------------
-
-# ^^PLEAC^^_9.4
-#-----------------------------
-import os
-seen = {}
-
-def do_my_thing(filename):
- fstat = os.stat(filename)
- key = (fstat.st_ino, fstat.st_dev)
- if not seen.get(key):
- # do something with filename because we haven't
- # seen it before
- pass
- seen[key] = seen.get(key, 0 ) + 1
-
-#-----------------------------
-for filename in files:
- fstat = os.stat(filename)
- key = (fstat.st_ino, fstat.st_dev)
- seen.setdefault(key, []).append(filename)
-
-keys = seen.keys()
-keys.sort()
-for inodev in keys:
- ino, dev = inodev
- filenames = seen[inodev]
- if len(filenames) > 1:
- # 'filenames' is a list of filenames for the same file
- pass
-#-----------------------------
-
-# ^^PLEAC^^_9.5
-#-----------------------------
-for filename in os.listdir(dirname):
- # do something with "$dirname/$file"
- pass
-#-----------------------------
-# XXX No -T equivalent in Python
-#-----------------------------
-# 'readir' always skipes '.' and '..' on OSes where those are
-# standard directory names
-for filename in os.listdir(dirname):
- pass
-#-----------------------------
-# XX Not Implemented -- need to know what DirHandle does
-# use DirHandle;
-
-#-----------------------------
-
-# ^^PLEAC^^_9.6
-#-----------------------------
-import glob
-filenames = glob.glob("*.c")
-#-----------------------------
-filenames = [filename for filename in os.listdir(path) if filename.endswith(".c")]
-#-----------------------------
-import re
-allowed_name = re.compile(r"\.[ch]$", re.I).search
-filenames = [f for f in os.listdir(path) if allowed_name(f)]
-#-----------------------------
-import re, os
-allowed_name = re.compile(r"\.[ch]$", re.I).search
-
-fnames = [os.path.join(dirname, fname)
- for fname in os.listdir(dirname)
- if allowed_name(fname)]
-#-----------------------------
-dirs = [os.path.join(path, f)
- for f in os.listdir(path) if f.isdigit()]
-dirs = [d for d in dirs if os.path.isdir(d)]
-dirs = sorted(dirs, key=int) # Sort by numeric value - "9" before "11"
-#-----------------------------
-
-# @@PLEAC@@_9.7
-# Processing All Files in a Directory Recursively
-
-# os.walk is new in 2.3.
-
-# For pre-2.3 code, there is os.path.walk, which is
-# little harder to use.
-
-#-----------------------------
-import os
-for root, dirs, files in os.walk(top):
- pass # do whatever
-
-#-----------------------------
-import os, os.path
-for root, dirs, files in os.walk(top):
- for name in dirs:
- print os.path.join(root, name) + '/'
- for name in files:
- print os.path.join(root, name)
-
-#-----------------------------
-import os, os.path
-numbytes = 0
-for root, dirs, files in os.walk(top):
- for name in files:
- path = os.path.join(root, name)
- numbytes += os.path.getsize(path)
-print "%s contains %s bytes" % (top, numbytes)
-
-#-----------------------------
-import os, os.path
-saved_size, saved_name = -1, ''
-for root, dirs, files in os.walk(top):
- for name in files:
- path = os.path.join(root, name)
- size = os.path.getsize(path)
- if size > saved_size:
- saved_size = size
- saved_name = path
-print "Biggest file %s in %s is %s bytes long" % (
- saved_name, top, saved_size)
-
-#-----------------------------
-import os, os.path, time
-saved_age, saved_name = None, ''
-for root, dirs, files in os.walk(top):
- for name in files:
- path = os.path.join(root, name)
- age = os.path.getmtime(path)
- if saved_age is None or age > saved_age:
- saved_age = age
- saved_name = path
-print "%s %s" % (saved_name, time.ctime(saved_age))
-
-#-----------------------------
-#!/usr/bin/env python
-# fdirs - find all directories
-import sys, os, os.path
-argv = sys.argv[1:] or ['.']
-for top in argv:
- for root, dirs, files in os.walk(top):
- for name in dirs:
- path = os.path.join(root, name)
- print path
-
-
-# ^^PLEAC^^_9.8
-#-----------------------------
-# DeleteDir - remove whole directory trees like rm -r
-import shutil
-shutil.rmtree(path)
-
-# DON'T DO THIS:
-import os, sys
-def DeleteDir(dir):
- for name in os.listdir(dir):
- file = os.path.join(dir, name)
- if not os.path.islink(file) and os.path.isdir(file):
- DeleteDir(file)
- else:
- os.remove(file)
- os.rmdir(dir)
-
-# @@PLEAC@@_9.9
-# Renaming Files
-
-# code sample one to one from my perlcookbook
-# looks strange to me.
-import os
-for fname in fnames:
- newname = fname
- # change the file's name
- try:
- os.rename(fname, newname)
- except OSError, err:
- print "Couldn't rename %s to %s: %s!" % \
- (fname, newfile, err)
-
-# use os.renames if newname needs directory creation.
-
-#A vaguely Pythonic solution is:
-import glob
-def rename(files, transfunc)
- for fname in fnames:
- newname = transfunc(fname)
- try:
- os.rename(fname, newname)
- except OSError, err:
- print "Couldn't rename %s to %s: %s!" % \
- (fname, newfile, err)
-
-def transfunc(fname):
- return fname[:-5]
-rename(glob.glob("*.orig"), transfunc)
-
-def transfunc(fname):
- return fname.lower()
-rename([f for f in glob.glob("*") if not f.startswith("Make)], transfunc)
-
-def transfunc(fname):
- return fname + ".bad"
-rename(glob.glob("*.f"), transfunc)
-
-def transfunc(fname):
- answer = raw_input(fname + ": ")
- if answer.upper().startswith("Y"):
- return fname.replace("foo", "bar")
-rename(glob.glob("*"), transfunc)
-
-def transfunc(fname):
- return ".#" + fname[:-1]
-rename(glob.glob("/tmp/*~"), transfunc)
-
-# This _could_ be made to eval code taken directly from the command line,
-# but it would be fragile
-#-----------------------------
-
-# ^^PLEAC^^_9.10
-#-----------------------------
-import os
-
-base = os.path.basename(path)
-dirname = os.path.dirname(path)
-dirname, filename = os.path.split(path)
-base, ext = os.path.splitext(filename)
-
-#-----------------------------
-path = '/usr/lib/libc.a'
-filename = os.path.basename(path)
-dirname = os.path.dirname(path)
-
-print "dir is %s, file is %s" % (dirname, filename)
-# dir is /usr/lib, file is libc.a
-#-----------------------------
-path = '/usr/lib/libc.a'
-dirname, filename = os.path.split(path)
-name, ext = os.path.splitext(filename)
-
-print "dir is %s, name is %s, extension is %s" % (dirname, name, ext)
-# NOTE: The Python code prints
-# dir is /usr/lib, name is libc, extension is .a
-# while the Perl code prints a '/' after the directory name
-# dir is /usr/lib/, name is libc, extension is .a
-#-----------------------------
-import macpath
-path = "Hard%20Drive:System%20Folder:README.txt"
-dirname, base = macpath.split(path)
-name, ext = macpath.splitext(base)
-
-print "dir is %s, name is %s, extension is %s" % (dirname, name, ext)
-# dir is Hard%20Drive:System%20Folder, name is README, extension is .txt
-#-----------------------------
-# DON'T DO THIS - it's not portable.
-def extension(path):
- pos = path.find(".")
- if pos == -1:
- return ""
- ext = path[pos+1:]
- if "/" in ext:
- # wasn't passed a basename -- this is of the form 'x.y/z'
- return ""
- return ext
-#-----------------------------
-
-# @@PLEAC@@_9.11
-
-#!/usr/bin/python
-# sysmirror - build spectral forest of symlinks
-import sys, os, os.path
-
-pgmname = sys.argv[0]
-if len(sys.argv)!=3:
- print "usage: %s realdir mirrordir" % pgmname
- raise SystemExit
-
-(srcdir, dstdir) = sys.argv[1:3]
-if not os.path.isdir(srcdir):
- print "%s: %s is not a directory" % (pgmname,srcdir)
- raise SystemExit
-if not os.path.isdir(dstdir):
- try:
- os.mkdir(dstdir)
- except OSError:
- print "%s: can't make directory %s" % (pgmname,dstdir)
- raise SystemExit
-
-# fix relative paths
-srcdir = os.path.abspath(srcdir)
-dstdir = os.path.abspath(dstdir)
-
-def wanted(arg, dirname, names):
- for direntry in names:
- relname = "%s/%s" % (dirname, direntry)
- if os.path.isdir(relname):
- mode = os.stat(relname).st_mode
- try:
- os.mkdir("%s/%s" % (dstdir,relname), mode)
- except:
- print "can't mkdir %s/%s" % (dstdir,relname)
- raise SystemExit
- else:
- if relname[:2] == "./":
- relname = relname[2:]
- os.symlink("%s/%s" % (srcdir, relname), "%s/%s" % (dstdir,relname))
-
-os.chdir(srcdir)
-os.path.walk(".",wanted,None)
-
-# @@PLEAC@@_9.12
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-
-# ^^PLEAC^^_10.0
-#-----------------------------
-# DO NOT DO THIS...
-greeted = 0
-def hello():
- global greeted
- greeted += 1
- print "hi there"
-
-#... as using a callable object to save state is cleaner
-# class hello
-# def __init__(self):
-# self.greeted = 0
-# def __call__(self):
-# self.greeted += 1
-# print "hi there"
-# hello = hello()
-#-----------------------------
-hello() # call subroutine hello with no arguments/parameters
-#-----------------------------
-
-# ^^PLEAC^^_10.1
-#-----------------------------
-import math
-# Provided for demonstration purposes only. Use math.hypot() instead.
-def hypotenuse(side1, side2):
- return math.sqrt(side1**2 + side2**2)
-
-diag = hypotenuse(3, 4) # diag is 5.0
-#-----------------------------
-print hypotenuse(3, 4) # prints 5.0
-
-a = (3, 4)
-print hypotenuse(*a) # prints 5.0
-#-----------------------------
-both = men + women
-#-----------------------------
-nums = [1.4, 3.5, 6.7]
-# Provided for demonstration purposes only. Use:
-# ints = [int(num) for num in nums]
-def int_all(nums):
- retlist = [] # make new list for return
- for n in nums:
- retlist.append(int(n))
- return retlist
-ints = int_all(nums) # nums unchanged
-#-----------------------------
-nums = [1.4, 3.5, 6.7]
-
-def trunc_em(nums):
- for i,elem in enumerate(nums):
- nums[i] = int(elem)
-trunc_em(nums) # nums now [1,3,6]
-
-#-----------------------------
-# By convention, if a method (or function) modifies an object
-# in-place, it returns None rather than the modified object.
-# None of Python's built-in functions modify in-place; methods
-# such as list.sort() are somewhat more common.
-mylist = [3,2,1]
-mylist = mylist.sort() # incorrect - returns None
-mylist = sorted(mylist) # correct - returns sorted copy
-mylist.sort() # correct - sorts in-place
-#-----------------------------
-
-# ^^PLEAC^^_10.2
-#-----------------------------
-# Using global variables is discouraged - by default variables
-# are visible only at and below the scope at which they are declared.
-# Global variables modified by a function or method must be declared
-# using the "global" keyword if they are modified
-def somefunc():
- variable = something # variable is invisible outside of somefunc
-#-----------------------------
-import sys
-name, age = sys.args[1:] # assumes two and only two command line parameters
-start = fetch_time()
-#-----------------------------
-a, b = pair
-c = fetch_time()
-
-def check_x(x):
- y = "whatever"
- run_check()
- if condition:
- print "got", x
-#-----------------------------
-def save_list(*args):
- Global_List.extend(args)
-#-----------------------------
-
-# ^^PLEAC^^_10.3
-#-----------------------------
-## Python allows static nesting of scopes for reading but not writing,
-## preferring to use objects. The closest equivalent to:
-#{
-# my $counter;
-# sub next_counter { return ++$counter }
-#}
-## is:
-def next_counter(counter=[0]): # default lists are created once only.
- counter[0] += 1
- return counter[0]
-
-# As that's a little tricksy (and can't make more than one counter),
-# many Pythonistas would prefer either:
-def make_counter():
- counter = 0
- while True:
- counter += 1
- yield counter
-next_counter = make_counter().next
-
-# Or:
-class Counter:
- def __init__(self):
- self.counter = 0
- def __call__(self):
- self.counter += 1
- return self.counter
-next_counter = Counter()
-
-#-----------------------------
-## A close equivalent of
-#BEGIN {
-# my $counter = 42;
-# sub next_counter { return ++$counter }
-# sub prev_counter { return --$counter }
-#}
-## is to use a list (to save the counter) and closured functions:
-def make_counter(start=0):
- counter = [start]
- def next_counter():
- counter[0] += 1
- return counter[0]
- def prev_counter():
- counter[0] -= 1
- return counter[0]
- return next_counter, prev_counter
-next_counter, prev_counter = make_counter()
-
-## A clearer way uses a class:
-class Counter:
- def __init__(self, start=0):
- self.value = start
- def next(self):
- self.value += 1
- return self.value
- def prev(self):
- self.value -= 1
- return self.value
- def __int__(self):
- return self.value
-
-counter = Counter(42)
-next_counter = counter.next
-prev_counter = counter.prev
-#-----------------------------
-
-# ^^PLEAC^^_10.4
-## This sort of code inspection is liable to change as
-## Python evolves. There may be cleaner ways to do this.
-## This also may not work for code called from functions
-## written in C.
-#-----------------------------
-import sys
-this_function = sys._getframe(0).f_code.co_name
-#-----------------------------
-i = 0 # how far up the call stack to look
-module = sys._getframe(i).f_globals["__name__"]
-filename = sys._getframe(i).f_code.co_filename
-line = sys._getframe(i).f_lineno
-subr = sys._getframe(i).f_code.co_name
-has_args = bool(sys._getframe(i+1).f_code.co_argcount)
-
-# 'wantarray' is Perl specific
-
-#-----------------------------
-me = whoami()
-him = whowasi()
-
-def whoami():
- sys._getframe(1).f_code.co_name
-def whowasi():
- sys._getframe(2).f_code.co_name
-#-----------------------------
-
-# ^^PLEAC^^_10.5
-#-----------------------------
-# Every variable name is a reference to an object, thus nothing special
-# needs to be done to pass a list or a dict as a parameter.
-list_diff(list1, list2)
-#-----------------------------
-# Note: if one parameter to zip() is longer it will be truncated
-def add_vecpair(x, y):
- return [x1+y1 for x1, y1 in zip(x, y)]
-
-a = [1, 2]
-b = [5, 8]
-print " ".join([str(n) for n in add_vecpair(a, b)])
-#=> 6 10
-#-----------------------------
-# DO NOT DO THIS:
-assert isinstance(x, type([])) and isinstance(y, type([])), \
- "usage: add_vecpair(list1, list2)"
-#-----------------------------
-
-# ^^PLEAC^^_10.6
-#-----------------------------
-# perl return context is not something standard in python...
-# but still you can achieve something alike if you really need it
-# (but you must really need it badly since you should never use this!!)
-#
-# see http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/284742 for more
-#
-# NB: it has been tested under Python 2.3.x and no guarantees can be given
-# that it works under any future Python version.
-import inspect,dis
-
-def expecting():
- """Return how many values the caller is expecting"""
- f = inspect.currentframe().f_back.f_back
- bytecode = f.f_code.co_code
- i = f.f_lasti
- instruction = ord(bytecode[i+3])
- if instruction == dis.opmap['UNPACK_SEQUENCE']:
- howmany = ord(bytecode[i+4])
- return howmany
- elif instruction == dis.opmap['POP_TOP']:
- return 0
- return 1
-
-def cleverfunc():
- howmany = expecting()
- if howmany == 0:
- print "return value discarded"
- if howmany == 2:
- return 1,2
- elif howmany == 3:
- return 1,2,3
- return 1
-
-cleverfunc()
-x = cleverfunc()
-print x
-x,y = cleverfunc()
-print x,y
-x,y,z = cleverfunc()
-print x,y,z
-
-# ^^PLEAC^^_10.7
-#-----------------------------
-thefunc(increment= "20s", start="+5m", finish="+30m")
-thefunc(start= "+5m",finish="+30m")
-thefunc(finish= "+30m")
-thefunc(start="+5m", increment="15s")
-#-----------------------------
-def thefunc(increment='10s',
- finish='0',
- start='0'):
- if increment.endswith("m"):
- pass
-#-----------------------------
-
-# ^^PLEAC^^_10.8
-#-----------------------------
-a, _, c = func() # Use _ as a placeholder...
-a, ignore, c = func() # ...or assign to an otherwise unused variable
-#-----------------------------
-
-# ^^PLEAC^^_10.9
-#-----------------------------
-def somefunc():
- mylist = []
- mydict = {}
- # ...
- return mylist, mydict
-
-mylist, mydict = somefunc()
-#-----------------------------
-def fn():
- return a, b, c
-
-#-----------------------------
-h0, h1, h2 = fn()
-tuple_of_dicts = fn() # eg: tuple_of_dicts[2]["keystring"]
-r0, r1, r2 = fn() # eg: r2["keystring"]
-
-#-----------------------------
-
-# ^^PLEAC^^_10.10
-#-----------------------------
-# Note: Exceptions are almost always preferred to error values
-return
-#-----------------------------
-def empty_retval():
- return None
-
-def empty_retval():
- return # identical to return None
-
-def empty_retval():
- pass # None returned by default (empty func needs pass)
-#-----------------------------
-a = yourfunc()
-if a:
- pass
-#-----------------------------
-a = sfunc()
-if not a:
- raise AssertionError("sfunc failed")
-
-assert sfunc(), "sfunc failed"
-#-----------------------------
-
-# ^^PLEAC^^_10.11
-# Prototypes are inapplicable to Python as Python disallows calling
-# functions without using brackets, and user functions are able to
-# mimic built-in functions with no special actions required as they
-# only flatten lists (and convert dicts to named arguments) if
-# explicitly told to do so. Python functions use named parameters
-# rather than shifting arguments:
-
-def myfunc(a, b, c=4):
- print a, b, c
-
-mylist = [1,2]
-
-mydict1 = {"b": 2, "c": 3}
-mydict2 = {"b": 2}
-
-myfunc(1,2,3)
-#=> 1 2 3
-
-myfunc(1,2)
-#=> 1 2 4
-
-myfunc(*mylist)
-#=> 1 2 4
-
-myfunc(5, *mylist)
-#=> 5, 1, 2
-
-myfunc(5, **mydict1)
-#=> 5, 2, 3
-
-myfunc(5, **mydict2)
-#=> 5, 2, 4
-
-myfunc(c=3, b=2, a=1)
-#=> 1, 2, 3
-
-myfunc(b=2, a=1)
-#=> 1, 2, 4
-
-myfunc(mylist, mydict1)
-#=> [1, 2] {'c': 3, 'b': 2} 4
-
-# For demonstration purposes only - don't do this
-def mypush(mylist, *vals):
- mylist.extend(vals)
-
-mylist = []
-mypush(mylist, 1, 2, 3, 4, 5)
-print mylist
-#=> [1, 2, 3, 4, 5]
-
-# ^^PLEAC^^_10.12
-#-----------------------------
-raise ValueError("some message") # specific exception class
-raise Exception("use me rarely") # general exception
-raise "don't use me" # string exception (deprecated)
-#-----------------------------
-# Note that bare excepts are considered bad style. Normally you should
-# trap specific exceptions. For instance these bare excepts will
-# catch KeyboardInterrupt, SystemExit, and MemoryError as well as
-# more common errors. In addition they force you to import sys to
-# get the error message.
-import warnings, sys
-try:
- func()
-except:
- warnings.warn("func raised an exception: " + str(sys.exc_info()[1]))
-#-----------------------------
-try:
- func()
-except:
- warnings.warn("func blew up: " + str(sys.exc_info()[1]))
-#-----------------------------
-class MoonPhaseError(Exception):
- def __init__(self, phase):
- self.phase = phase
-class FullMoonError(MoonPhaseError):
- def __init__(self):
- MoonPhaseError.__init__("full moon")
-
-def func():
- raise FullMoonError()
-
-# Ignore only FullMoonError exceptions
-try:
- func()
-except FullMoonError:
- pass
-#-----------------------------
-# Ignore only MoonPhaseError for a full moon
-try:
- func()
-except MoonPhaseError, err:
- if err.phase != "full moon":
- raise
-#-----------------------------
-
-# ^^PLEAC^^_10.13
-# There is no direct equivalent to 'local' in Python, and
-# it's impossible to write your own. But then again, even in
-# Perl it's considered poor style.
-
-# DON'T DO THIS (You probably shouldn't use global variables anyway):
-class Local(object):
- def __init__(self, globalname, val):
- self.globalname = globalname
- self.globalval = globals()[globalname]
- globals()[globalname] = val
-
- def __del__(self):
- globals()[self.globalname] = self.globalval
-
-foo = 4
-
-def blah():
- print foo
-
-def blech():
- temp = Local("foo", 6)
- blah()
-
-blah()
-blech()
-blah()
-
-#-----------------------------
-
-# ^^PLEAC^^_10.14
-#-----------------------------
-grow = expand
-grow() # calls expand()
-
-#-----------------------------
-one.var = two.table # make one.var the same as two.table
-one.big = two.small # make one.big the same as two.small
-#-----------------------------
-fred = barney # alias fred to barney
-#-----------------------------
-s = red("careful here")
-print s
-#> <FONT COLOR='red'>careful here</FONT>
-#-----------------------------
-# Note: the 'text' should be HTML escaped if it can contain
-# any of the characters '<', '>' or '&'
-def red(text):
- return "<FONT COLOR='red'>" + text + "</FONT>"
-#-----------------------------
-def color_font(color, text):
- return "<FONT COLOR='%s'>%s</FONT>" % (color, text)
-
-def red(text): return color_font("red", text)
-def green(text): return color_font("green", text)
-def blue(text): return color_font("blue", text)
-def purple(text): return color_font("purple", text)
-# etc
-#-----------------------------
-# This is done in Python by making an object, instead of
-# saving state in a local anonymous context.
-class ColorFont:
- def __init__(self, color):
- self.color = color
- def __call__(self, text):
- return "<FONT COLOR='%s'>%s</FONT>" % (self.color, text)
-
-colors = "red blue green yellow orange purple violet".split(" ")
-for name in colors:
- globals()[name] = ColorFont(name)
-#-----------------------------
-# If you really don't want to make a new class, you can
-# fake it somewhat by passing in default args.
-colors = "red blue green yellow orange purple violet".split(" ")
-for name in colors:
- def temp(text, color = name):
- return "<FONT COLOR='%s'>%s</FONT>" % (color, text)
- globals()[name] = temp
-
-#-----------------------------
-
-# ^^PLEAC^^_10.15
-
-# Python has the ability to derive from ModuleType and add
-# new __getattr__ and __setattr__ methods. I don't know the
-# expected way to use them to emulate Perl's AUTOLOAD. Instead,
-# here's how something similar would be done in Python. This
-# uses the ColorFont defined above.
-
-#-----------------------------
-class AnyColor:
- def __getattr__(self, name):
- return ColorFont(name)
-
-colors = AnyColor()
-
-print colors.chartreuse("stuff")
-
-#-----------------------------
-## Skipping this translation because 'local' is too Perl
-## specific, and there isn't enough context to figure out
-## what this is supposed to do.
-#{
-# local *yellow = \&violet;
-# local (*red, *green) = (\&green, \&red);
-# print_stuff();
-#}
-#-----------------------------
-
-# ^^PLEAC^^_10.16
-#-----------------------------
-def outer(arg1):
- x = arg1 + 35
- def inner():
- return x * 19
- return x + inner()
-#-----------------------------
-
-# ^^PLEAC^^_10.17
-#-----------------------------
-import mailbox, sys
-mbox = mailbox.PortableUnixMailbox(sys.stdin)
-
-def extract_data(msg, idx):
- subject = msg.getheader("Subject", "").strip()
- if subject[:3].lower() == "re:":
- subject = subject[3:].lstrip()
- text = msg.fp.read()
- return subject, idx, msg, text
-messages = [extract_data(idx, msg) for idx, msg in enumerate(mbox)]
-
-#-----------------------------
-# Sorts by subject then by original position in the list
-for subject, pos, msg, text in sorted(messages):
- print "%s\n%s"%(msg, text)
-
-#-----------------------------
-# Sorts by subject then date then original position
-def subject_date_position(elem):
- return (elem[0], elem[2].getdate("Date"), elem[1])
-messages.sort(key=subject_date_position)
-
-# Pre 2.4:
-messages = sorted(messages, key=subject_date_position)
-#-----------------------------
-
-# @@PLEAC@@_11.0
-#Introduction.
-# In Python, all names are references.
-# All objects are inherently anonymous, they don't know what names refer to them.
-print ref # prints the value that the name ref refers to.
-ref = 3 # assigns the name ref to the value 3.
-#-----------------------------
-aref = mylist
-#-----------------------------
-aref = [3, 4, 5] # aref is a name for this list
-href = {"How": "Now", "Brown": "Cow"} # href is a name for this dictionary
-#-----------------------------
-# Python doesn't have autovivification as (for simple types) there is no difference between a name and a reference.
-# If we try the equivalent of the Perl code we get the list, not a reference to the list.
-#-----------------------------
-# To handle multidimensional arrays, you should use an extension to Python,
-# such as numarray (http://www.stsci.edu/resources/software_hardware/numarray)
-#-----------------------------
-# In Python, assignment doesn't return anything.
-#-----------------------------
-Nat = { "Name": "Leonhard Euler",
- "Address": "1729 Ramanujan Lane\nMathworld, PI 31416",
- "Birthday": 0x5bb5580
-}
-#-----------------------------
-
-# @@PLEAC@@_11.1
-aref = mylist
-anon_list = [1, 3, 5, 7, 9]
-anon_copy = anon_list
-implicit_creation = [2, 4, 6, 8, 10]
-#-----------------------------
-anon_list.append(11)
-#-----------------------------
-two = implicit_creation[0]
-#-----------------------------
-# To get the last index of a list, you can use len()
-# [or list.__len__() - but don't] directly
-last_idx = len(aref) - 1
-
-# Normally, though, you'd use an index of -1 for the last
-# element, -2 for the second last, etc.
-print implicit_creation[-1]
-#=> 10
-
-num_items = len(aref)
-#-----------------------------
-last_idx = aref.__len__() - 1
-num_items = aref.__len__()
-#-----------------------------
-if not isinstance(someVar, type([])):
- print "Expected a list"
-#-----------------------------
-print list_ref
-#-----------------------------
-# sort is in place.
-list_ref.sort()
-#-----------------------------
-list_ref.append(item)
-#-----------------------------
-def list_ref():
- return []
-
-aref1 = list_ref()
-aref2 = list_ref()
-# aref1 and aref2 point to different lists.
-#-----------------------------
-list_ref[N] # refers to the Nth item in the list_ref list.
-#-----------------------------
-# The following two statements are equivalent and return up to 3 elements
-# at indices 3, 4, and 5 (if they exist).
-pie[3:6]
-pie[3:6:1]
-#-----------------------------
-# This will insert 3 elements, overwriting elements at indices 3,4, or 5 - if they exist.
-pie[3:6] = ["blackberry", "blueberry", "pumpkin"]
-#-----------------------------
-for item in pie:
- print item
-
-# DON'T DO THIS (this type of indexing should be done with enumerate)
-# xrange does not create a list 0..len(pie) - 1, it creates an object
-# that returns one index at a time.
-for idx in xrange(len(pie)):
- print pie[idx]
-
-# @@PLEAC@@_11.2
-# Making Hashes of Arrays
-
-hash["KEYNAME"].append("new value")
-
-for mystr in hash.keys():
- print "%s: %s" % (mystr, hash[mystr])
-
-hash["a key"] = [3, 4, 5]
-
-values = hash["a key"]
-
-hash["a key"].append(value)
-
-# autovivification also does not work in python.
-residents = phone2name[number]
-# do this instead
-residents = phone2name.get(number, [])
-
-
-# @@PLEAC@@_11.3
-# Taking References to Hashes
-
-href = hash
-anon_hash = { "key1":"value1", "key2" : "value2 ..." }
-anon_hash_copy = anon_hash.copy()
-
-hash = href
-value = href[key]
-slice = [href[k] for k in (key1, key2, key3)]
-keys = hash.keys()
-
-import types
-if type(someref) != types.DictType:
- raise "Expected a dictionary, not %s" % type(someref)
-if isinstance(someref,dict):
- raise "Expected a dictionary, not %s" % type(someref)
-
-for href in ( ENV, INC ):
- for key in href.keys():
- print "%s => %s" % (key, href[key])
-
-values = [hash_ref[k] for k in (key1, key2, key3)]
-
-for key in ("key1", "key2", "key3"):
- hash_ref[k] += 7 # not like in perl but the same result.
-#-----------------------------
-
-# @@PLEAC@@_11.4
-#-----------------------------
-cref = func
-cref = lambda a, b: ...
-#-----------------------------
-returned = cref(arguments)
-#-----------------------------
-funcname = "thefunc"
-locals()[funcname]();
-#-----------------------------
-commands = {
- 'happy': joy,
- 'sad': sullen,
- 'done': (lambda : sys.exit()), # In this case "done: sys.exit" would suffice
- 'mad': angry,
- }
-
-print "How are you?",
-cmd = raw_input()
-if cmd in commands:
- commands[cmd]()
-else:
- print "No such command: %s" % cmd
-#-----------------------------
-def counter_maker():
- start = [0]
- def counter_function():
- # start refers to the variable defined in counter_maker, but
- # we can't reassign or increment variables in parent scopes.
- # By using a one-element list we can modify the list without
- # reassigning the variable. This way of using a list is very
- # like a reference.
- start[0] += 1
- return start[0]-1
- return counter_function
-
-counter = counter_maker()
-for i in range(5):
- print counter()
-#-----------------------------
-counter1 = counter_maker()
-counter2 = counter_maker()
-
-for i in range(5):
- print counter1()
-print counter1(), counter2()
-#=> 0
-#=> 1
-#=> 2
-#=> 3
-#=> 4
-#=> 5 0
-#-----------------------------
-import time
-def timestamp():
- start_time = time.time()
- def elapsed():
- return time.time() - start_time
- return elapsed
-early = timestamp()
-time.sleep(20)
-later = timestamp()
-time.sleep(10)
-print "It's been %d seconds since early" % early()
-print "It's been %d seconds since later" % later()
-#=> It's been 30 seconds since early.
-#=> It's been 10 seconds since later.
-#-----------------------------
-
-# @@PLEAC@@_11.5
-# A name is a reference to an object and an object can be referred to
-# by any number of names. There is no way to manipulate pointers or
-# an object's id. This section is thus inapplicable.
-x = 1
-y = x
-print x, id(x), y, id(y)
-x += 1 # "x" now refers to a different object than y
-print x, id(x), y, id(y)
-y = 4 # "y" now refers to a different object than it did before
-print x, id(x), y, id(y)
-
-# Some objects (including ints and strings) are immutable, however, which
-# can give the illusion of a by-value/by-reference distinction:
-a = x = [1]
-b = y = 1
-c = z = "s"
-print a, b, c
-#=> [1] 1 s
-
-x += x # calls list.__iadd__ which is inplace.
-y += y # can't find int.__iadd__ so calls int.__add__ which isn't inplace
-z += z # can't find str.__iadd__ so calls str.__add__ which isn't inplace
-print a, b, c
-#=> [1, 1] 1 s
-
-# @@PLEAC@@_11.6
-# As indicated by the previous section, everything is referenced, so
-# just create a list as normal, and beware that augmented assignment
-# works differently with immutable objects to mutable ones:
-mylist = [1, "s", [1]]
-print mylist
-#=> [1, s, [1]]
-
-for elem in mylist:
- elem *= 2
-print mylist
-#=> [1, s, [1, 1]]
-
-mylist[0] *= 2
-mylist[-1] *= 2
-print mylist
-#=> [1, s, [1, 1, 1, 1]]
-
-# If you need to modify every value in a list, you should use a list comprehension
-# which does NOT modify inplace:
-import math
-mylist = [(val**3 * 4/3*math.pi) for val in mylist]
-
-# @@PLEAC@@_11.7
-#-----------------------------
-c1 = mkcounter(20)
-c2 = mkcounter(77)
-
-print "next c1: %d" % c1['next']() # 21
-print "next c2: %d" % c2['next']() # 78
-print "next c1: %d" % c1['next']() # 22
-print "last c1: %d" % c1['prev']() # 21
-print "old c2: %d" % c2['reset']() # 77
-#-----------------------------
-# DON'T DO THIS. Use an object instead
-def mkcounter(start):
- count = [start]
- def next():
- count[0] += 1
- return count[0]
- def prev():
- count[0] -= 1
- return count[0]
- def get():
- return count[0]
- def set(value):
- count[0] = value
- return count[0]
- def bump(incr):
- count[0] += incr
- return count[0]
- def reset():
- count[0] = start
- return count[0]
- return {
- 'next': next, 'prev': prev, 'get': get, 'set': set,
- 'bump': bump, 'reset': reset, 'last': prev}
-#-----------------------------
-
-# @@PLEAC@@_11.8
-#-----------------------------
-mref = obj.meth
-# later...
-mref("args", "go", "here")
-#-----------------------------
-
-# @@PLEAC@@_11.9
-#-----------------------------
-record = {
- "name": "Jason",
- "empno": 132,
- "title": "deputy peon",
- "age": 23,
- "salary": 37000,
- "pals": ["Norbert", "Rhys", "Phineas"],
-}
-print "I am %s, and my pals are %s." % (record["name"],
- ", ".join(record["pals"]))
-#-----------------------------
-byname = {}
-byname[record["name"]] = record
-
-rp = byname.get("Aron")
-if rp:
- print "Aron is employee %d."% rp["empno"]
-
-byname["Jason"]["pals"].append("Theodore")
-print "Jason now has %d pals." % len(byname["Jason"]["pals"])
-
-for name, record in byname.items():
- print "%s is employee number %d." % (name, record["empno"])
-
-employees = {}
-employees[record["empno"]] = record;
-
-# lookup by id
-rp = employees.get(132)
-if (rp):
- print "Employee number 132 is %s." % rp["name"]
-
-byname["Jason"]["salary"] *= 1.035
-
-peons = [r for r in employees.values() if r["title"] == "peon"]
-tsevens = [r for r in employees.values() if r["age"] == 27]
-
-# Go through all records
-print employees.values()
-
-for rp in sorted(employees.values(), key=lambda x:x["age"]):
- print "%s is age %d."%(rp["name"], rp["age"])
-
-# use @byage, an array of arrays of records
-byage = {}
-byage[record["age"]] = byage.get(record["age"], []) + [record]
-
-for age, records in byage.items():
- print records
- print "Age %s:"%age,
- for rp in records:
- print rp["name"],
- print
-#-----------------------------
-
-# @@PLEAC@@_11.10
-#-----------------------------
-FieldName: Value
-#-----------------------------
-for record in list_of_records:
- # Note: sorted added in Python 2.4
- for key in sorted(record.keys()):
- print "%s: %s" % (key, record[key])
- print
-#-----------------------------
-import re
-list_of_records = [{}]
-while True:
- line = sys.stdin.readline()
- if not line:
- # EOF
- break
- # Remove trailing \n:
- line = line[:1]
- if not line.strip():
- # New record
- list_of_records.append({})
- continue
- key, value = re.split(r':\s*', line, 1)
- # Assign the key/value to the last item in the list_of_records:
- list_of_records[-1][key] = value
-#-----------------------------
-# @@PLEAC@@_11.11
-import pprint
-
-mylist = [[1,2,3], [4, [5,6,7], 8,9, [0,3,5]], 7, 8]
-mydict = {"abc": "def", "ghi":[1,2,3]}
-pprint.pprint(mylist, width=1)
-
-fmtdict = pprint.pformat(mydict, width=1)
-print fmtdict
-# "import pprint; help(pprint)" for more details
-
-# @@INCOMPLETE@@
-# Note that pprint does not currently handle user objects
-
-#-----------------------------
-# @@PLEAC@@_11.12
-newlist = list(mylist) # shallow copy
-newdict = dict(mydict) # shallow copy
-
-# Pre 2.3:
-import copy
-newlist = copy.copy(mylist) # shallow copy
-newdict = copy.copy(mydict) # shallow copy
-
-# shallow copies copy a data structure, but don't copy the items in those
-# data structures so if there are nested data structures, both copy and
-# original will refer to the same object
-mylist = ["1", "2", "3"]
-newlist = list(mylist)
-mylist[0] = "0"
-print mylist, newlist
-#=> ['0', '2', '3'] ['1', '2', '3']
-
-mylist = [["1", "2", "3"], 4]
-newlist = list(mylist)
-mylist[0][0] = "0"
-print mylist, newlist
-#=> [['0', '2', '3'], 4] [['0', '2', '3'], 4]
-#-----------------------------
-import copy
-newlist = copy.deepcopy(mylist) # deep copy
-newdict = copy.deepcopy(mydict) # deep copy
-
-# deep copies copy a data structure recursively:
-import copy
-
-mylist = [["1", "2", "3"], 4]
-newlist = copy.deepcopy(mylist)
-mylist[0][0] = "0"
-print mylist, newlist
-#=> [['0', '2', '3'], 4] [['1', '2', '3'], 4]
-#-----------------------------
-# @@PLEAC@@_11.13
-import pickle
-class Foo(object):
- def __init__(self):
- self.val = 1
-
-x = Foo()
-x.val = 3
-p_x = pickle.dumps(x) # Also pickle.dump(x, myfile) which writes to myfile
-del x
-x = pickle.loads(p_x) # Also x = pickle.load(myfile) which loads from myfile
-print x.val
-#=> 3
-#-----------------------------
-# @@PLEAC@@_11.14
-import os, shelve
-fname = "testfile.db"
-if not os.path.exists(fname):
- d = shelve.open("testfile.db")
- for i in range(100000):
- d[str(i)] = i
- d.close()
-
-d = shelve.open("testfile.db")
-print d["100"]
-print d["1212010201"] # KeyError
-#-----------------------------
-
-# @@PLEAC@@_11.15
-# bintree - binary tree demo program
-# Use the heapq module instead?
-import random
-import warnings
-
-class BTree(object):
- def __init__(self):
- self.value = None
-
- ### insert given value into proper point of
- ### the tree, extending this node if necessary.
- def insert(self, value):
- if self.value is None:
- self.left = BTree()
- self.right = BTree()
- self.value = value
- elif self.value > value:
- self.left.insert(value)
- elif self.value < value:
- self.right.insert(value)
- else:
- warnings.warn("Duplicate insertion of %s."%value)
-
- # recurse on left child,
- # then show current value,
- # then recurse on right child.
- def in_order(self):
- if self.value is not None:
- self.left.in_order()
- print self.value,
- self.right.in_order()
-
- # show current value,
- # then recurse on left child,
- # then recurse on right child.
- def pre_order(self):
- if self.value is not None:
- print self.value,
- self.left.pre_order()
- self.right.pre_order()
-
- # recurse on left child,
- # then recurse on right child,
- # then show current value.
- def post_order(self):
- if self.value is not None:
- self.left.post_order()
- self.right.post_order()
- print self.value,
-
- # find out whether provided value is in the tree.
- # if so, return the node at which the value was found.
- # cut down search time by only looking in the correct
- # branch, based on current value.
- def search(self, value):
- if self.value is not None:
- if self.value == value:
- return self
- if value < self.value:
- return self.left.search(value)
- else:
- return self.right.search(value)
-
-def test():
- root = BTree()
-
- for i in range(20):
- root.insert(random.randint(1, 1000))
-
- # now dump out the tree all three ways
- print "Pre order: ", root.pre_order()
- print "In order: ", root.in_order()
- print "Post order:", root.post_order()
-
- ### prompt until empty line
- while True:
- val = raw_input("Search? ").strip()
- if not val:
- break
- val = int(val)
- found = root.search(val)
- if found:
- print "Found %s at %s, %s"%(val, found, found.value)
- else:
- print "No %s in tree" % val
-
-if __name__ == "__main__":
- test()
-
-
-# ^^PLEAC^^_12.0
-#-----------------------------
-## Python's "module" is the closest equivalent to Perl's "package"
-
-
-#=== In the file "Alpha.py"
-name = "first"
-
-#=== End of file
-
-#=== In the file "Omega.py"
-
-name = "last"
-#=== End of file
-
-import Alpha, Omega
-print "Alpha is %s, Omega is %s." % (Alpha.name, Omega.name)
-#> Alpha is first, Omega is last.
-#-----------------------------
-# Python does not have an equivalent to "compile-time load"
-import sys
-
-# Depending on the implementation, this could use a builtin
-# module or load a file with the extension .py, .pyc, pyo, .pyd,
-# .so, .dll, or (with imputils) load from other files.
-import Cards.Poker
-
-#-----------------------------
-#=== In the file Cards/Poker.py
-__all__ = ["card_deck", "shuffle"] # not usually needed
-card_deck = []
-def shuffle():
- pass
-
-#-----------------------------
-
-# ^^PLEAC^^_12.1
-#-----------------------------
-#== In the file "YourModule.py"
-
-__version__ = (1, 0) # Or higher
-__all__ = ["...", "..."] # Override names included in "... import *"
- # Note: 'import *' is considered poor style
- # and it is rare to use this variable.
-########################
-# your code goes here
-########################
-
-#-----------------------------
-import YourModule # Import the module into my package
- # (does not import any of its symbols)
-
-import YourModule as Module # Use a different name for the module
-
-from YourModule import * # Import all module symbols not starting
- # with an underscore (default); if __all__
- # is defined, only imports those symbols.
- # Using this is discouraged unless the
- # module is specifically designed for it.
-
-from YourModule import name1, name2, xxx
- # Import the named symbols from the module
-
-from YourModule import name1 as name2
- # Import the named object, but use a
- # different name to access it locally.
-
-#-----------------------------
-__all__ = ["F1", "F2", "List"]
-#-----------------------------
-__all__ = ["Op_Func", "Table"]
-#-----------------------------
-from YourModule import Op_Func, Table, F1
-#-----------------------------
-from YourModule import Functions, Table
-#-----------------------------
-
-# ^^PLEAC^^_12.2
-#-----------------------------
-# no import
-mod = "module"
-try:
- __import__(mod)
-except ImportError, err:
- raise ImportError("couldn't load %s: %s" % (mod, err))
-
-# imports into current package
-try:
- import module
-except ImportError, err:
- raise ImportError("couldn't load 'module': %s" % (err, ))
-
-# imports into current package, if the name is known
-try:
- import module
-except ImportError, err:
- raise ImportError("couldn't load 'module': %s" % (err, ))
-
-# Use a fixed local name for a named module
-mod = "module"
-try:
- local_name = __import__(mod)
-except ImportError, err:
- raise ImportError("couldn't load %s: %s" % (mod, err))
-
-# Use the given name for the named module.
-# (You probably don't need to do this.)
-mod = "module"
-try:
- globals()[mod] = __import__(mod)
-except ImportError, err:
- raise ImportError("couldn't load %s: %s" % (mod, err))
-
-#-----------------------------
-DBs = "Giant.Eenie Giant.Meanie Mouse.Mynie Moe".split()
-for mod in DBs.split():
- try:
- loaded_module = __import__(mod)
- except ImportError:
- continue
- # __import__ returns a reference to the top-most module
- # Need to get the actual submodule requested.
- for term in mod.split(".")[:-1]:
- loaded_module = getattr(loaded_module, term)
- break
-else:
- raise ImportError("None of %s loaded" % DBs)
-#-----------------------------
-
-# ^^PLEAC^^_12.3
-#-----------------------------
-import sys
-if __name__ == "__main__":
- if len(sys.argv) != 3 or not sys.argv[1].isdigit() \
- or not sys.argv[2].isdigit():
- raise SystemExit("usage: %s num1 num2" % sys.argv[0])
-
-import Some.Module
-import More.Modules
-#-----------------------------
-if opt_b:
- import math
-#-----------------------------
-from os import O_EXCL, O_CREAT, O_RDWR
-
-#-----------------------------
-import os
-O_EXCL = os.O_EXCL
-O_CREAT = os.O_CREAT
-O_RDWR = os.O_RDWR
-#-----------------------------
-import os
-O_EXCL, O_CREAT, O_RDWR = os.O_EXCL, os.O_CREAT, os.O_RDWR
-#-----------------------------
-load_module('os', "O_EXCL O_CREAT O_RDWR".split())
-
-def load_module(module_name, symbols):
- module = __import__(module_name)
- for symbol in symbols:
- globals()[symbol] = getattr(module, symbol)
-#-----------------------------
-
-# ^^PLEAC^^_12.4
-#-----------------------------
-# Python doesn't have Perl-style packages
-
-# Flipper.py
-__version__ = (1, 0)
-
-__all__ = ["flip_boundary", "flip_words"]
-
-Separatrix = ' ' # default to blank
-
-def flip_boundary(sep = None):
- prev_sep = Separatrix
- if sep is not None:
- global Separatrix
- Separatrix = sep
- return prev_sep
-
-def flip_words(line):
- words = line.split(Separatrix)
- words.reverse()
- return Separatrix.join(words)
-#-----------------------------
-
-# ^^PLEAC^^_12.5
-#-----------------------------
-this_pack = __name__
-#-----------------------------
-that_pack = sys._getframe(1).f_globals.get("__name__", "<string>")
-#-----------------------------
-print "I am in package", __name__
-#-----------------------------
-def nreadline(count, myfile):
- if count <= 0:
- raise ValueError("Count must be > 0")
- return [myfile.readline() for i in range(count)]
-
-def main():
- myfile = open("/etc/termcap")
- a, b, c = nreadline(3, myfile)
- myfile.close()
-
-if __name__ == "__main__":
- main()
-
-# DON'T DO THIS:
-import sys
-
-def nreadline(count, handle_name):
- assert count > 0, "count must be > 0"
- locals = sys._getframe(1).f_locals
- if not locals.has_key(handle_name):
- raise AssertionError("need open filehandle")
- infile = locals[handle_name]
- retlist = []
- for line in infile:
- retlist.append(line)
- count -= 1
- if count == 0:
- break
- return retlist
-
-def main():
- FH = open("/etc/termcap")
- a, b, c = nreadline(3, "FH")
-
-if __name__ == "__main__":
- main()
-#-----------------------------
-
-# ^^PLEAC^^_12.6
-#-----------------------------
-## There is no direct equivalent in Python to an END block
-import time, os, sys
-
-# Tricks to ensure the needed functions exist during module cleanup
-def _getgmtime(asctime=time.asctime, gmtime=time.gmtime,
- t=time.time):
- return asctime(gmtime(t()))
-
-class Logfile:
- def __init__(self, file):
- self.file = file
-
- def _logmsg(self, msg, argv0=sys.argv[0], pid=os.getpid(),
- _getgmtime=_getgmtime):
- # more tricks to keep all needed references
- now = _getgmtime()
- print>>self.file, argv0, pid, now + ":", msg
-
- def logmsg(self, msg):
- self._logmsg(self.file, msg)
-
- def __del__(self):
- self._logmsg("shutdown")
- self.file.close()
-
- def __getattr__(self, attr):
- # forward everything else to the file handle
- return getattr(self.file, attr)
-
-# 0 means unbuffered
-LF = Logfile(open("/tmp/mylog", "a+", 0))
-logmsg = LF.logmsg
-
-#-----------------------------
-## It is more appropriate to use try/finally around the
-## main code, so the order of initialization and finalization
-## can be specified.
-if __name__ == "__main__":
- import logger
- logger.init("/tmp/mylog")
- try:
- main()
- finally:
- logger.close()
-
-#-----------------------------
-
-# ^^PLEAC^^_12.7
-#-----------------------------
-#% python -c 'import sys\
-for i, name in zip(xrange(sys.maxint), sys.path):\
- print i, repr(name)
-#> 0 ''
-#> 1 '/usr/lib/python2.2'
-#> 2 '/usr/lib/python2.2/plat-linux2'
-#> 3 '/usr/lib/python2.2/lib-tk'
-#-----------------------------
-# syntax for sh, bash, ksh, or zsh
-#$ export PYTHONPATH=$HOME/pythonlib
-
-# syntax for csh or tcsh
-#% setenv PYTHONPATH ~/pythonlib
-#-----------------------------
-import sys
-sys.path.insert(0, "/projects/spectre/lib")
-#-----------------------------
-import FindBin
-sys.path.insert(0, FindBin.Bin)
-#-----------------------------
-import FindBin
-Bin = "Name"
-bin = getattr(FindBin, Bin)
-sys.path.insert(0, bin + "/../lib")
-#-----------------------------
-
-# ^^PLEAC^^_12.8
-#-----------------------------
-#% h2xs -XA -n Planets
-#% h2xs -XA -n Astronomy::Orbits
-#-----------------------------
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-# Need a distutils example
-#-----------------------------
-
-# ^^PLEAC^^_12.9
-#-----------------------------
-# Python compiles a file to bytecode the first time it is imported and
-# stores this compiled form in a .pyc file. There is thus less need for
-# incremental compilation as once there is a .pyc file, the sourcecode
-# is only recompiled if it is modified.
-
-# ^^PLEAC^^_12.10
-#-----------------------------
-# See previous section
-
-# ^^PLEAC^^_12.11
-#-----------------------------
-## Any definition in a Python module overrides the builtin
-## for that module
-
-#=== In MyModule
-def open():
- pass # TBA
-#-----------------------------
-from MyModule import open
-file = open()
-#-----------------------------
-
-# ^^PLEAC^^_12.12
-#-----------------------------
-def even_only(n):
- if n & 1: # one way to test
- raise AssertionError("%s is not even" % (n,))
- #....
-
-#-----------------------------
-def even_only(n):
- if n % 2: # here's another
- # choice of exception depends on the problem
- raise TypeError("%s is not even" % (n,))
- #....
-
-#-----------------------------
-import warnings
-def even_only(n):
- if n & 1: # test whether odd number
- warnings.warn("%s is not even, continuing" % (n))
- n += 1
- #....
-#-----------------------------
-warnings.filterwarnings("ignore")
-#-----------------------------
-
-# ^^PLEAC^^_12.13
-#-----------------------------
-val = getattr(__import__(packname), varname)
-vals = getattr(__import__(packname), aryname)
-getattr(__import__(packname), funcname)("args")
-
-#-----------------------------
-# DON'T DO THIS [Use math.log(val, base) instead]
-import math
-def make_log(n):
- def logn(val):
- return math.log(val, n)
- return logn
-
-# Modifying the global dictionary - this could also be done
-# using locals(), or someobject.__dict__
-globaldict = globals()
-for i in range(2, 1000):
- globaldict["log%s"%i] = make_log(i)
-
-# DON'T DO THIS
-for i in range(2,1000):
- exec "log%s = make_log(i)"%i in globals()
-
-print log20(400)
-#=>2.0
-#-----------------------------
-blue = colours.blue
-someobject.blue = colours.azure # someobject could be a module...
-#-----------------------------
-
-# ^^PLEAC^^_12.14
-#-----------------------------
-# Python extension modules can be imported and used just like
-# a pure python module.
-#
-# See http://www.cosc.canterbury.ac.nz/~greg/python/Pyrex/ for
-# information on how to create extension modules in Pyrex [a
-# language that's basically Python with type definitions which
-# converts to compiled C code]
-#
-# See http://www.boost.org/libs/python/doc/ for information on how
-# to create extension modules in C++.
-#
-# See http://www.swig.org/Doc1.3/Python.html for information on how
-# to create extension modules in C/C++
-#
-# See http://docs.python.org/ext/ext.html for information on how to
-# create extension modules in C/C++ (manual reference count management).
-#
-# See http://cens.ioc.ee/projects/f2py2e/ for information on how to
-# create extension modules in Fortran
-#
-# See http://www.scipy.org/Weave for information on how to
-# include inline C code in Python code.
-#
-# @@INCOMPLETE@@ Need examples of FineTime extensions using the different methods...
-#-----------------------------
-
-# ^^PLEAC^^_12.15
-#-----------------------------
-# See previous section
-#-----------------------------
-
-# ^^PLEAC^^_12.16
-#-----------------------------
-# To document code, use docstrings. A docstring is a bare string that
-# is placed at the beginning of a module or immediately after the
-# definition line of a class, method, or function. Normally, the
-# first line is a brief description of the object; if a longer
-# description is needed, it commences on the third line (the second
-# line being left blank). Multiline comments should use triple
-# quoted strings.
-#
-# Docstrings are automagically assigned to an object's __doc__ property.
-#
-# In other words these three classes are identical:
-class Foo(object):
- "A class demonstrating docstrings."
-
-class Foo(object):
- __doc__ = "A class demonstrating docstrings."
-
-class Foo(object):
- pass
-Foo.__doc__ = "A class demonstrating docstrings."
-
-# as are these two functions:
-def foo():
- "A function demonstrating docstrings."
-
-def foo():
- pass
-foo.__doc__ = "A function demonstrating docstrings."
-
-# the pydoc module is used to display a range of information about
-# an object including its docstrings:
-import pydoc
-print pydoc.getdoc(int)
-pydoc.help(int)
-
-# In the interactive interpreter, objects' documentation can be
-# using the help function:
-help(int)
-
-#-----------------------------
-
-# ^^PLEAC^^_12.17
-#-----------------------------
-# Recent Python distributions are built and installed with disutils.
-#
-# To build and install under unix
-#
-# % python setup.py install
-#
-# If you want to build under one login and install under another
-#
-# % python setup.py build
-# $ python setup.py install
-#
-# A package may also be available prebuilt, eg, as an RPM or Windows
-# installer. Details will be specific to the operating system.
-
-#-----------------------------
-# % python setup.py --prefix ~/python-lib
-#-----------------------------
-
-
-# ^^PLEAC^^_12.18
-#-----------------------------
-#== File Some/Module.py
-
-# There are so many differences between Python and Perl that
-# it isn't worthwhile trying to come up with an equivalent to
-# this Perl code. The Python code is much smaller, and there's
-# no need to have a template.
-
-#-----------------------------
-
-# ^^PLEAC^^_12.19
-#-----------------------------
-#% pmdesc
-#-----------------------------
-import sys, pydoc
-
-def print_module_info(path, modname, desc):
- # Skip files starting with "test_"
- if modname.split(".")[-1].startswith("test_"):
- return
- try:
- # This assumes the modules are safe for importing,
- # in that they don't have side effects. Could also
- # grep the file for the __version__ line.
- mod = pydoc.safeimport(modname)
- except pydoc.ErrorDuringImport:
- return
- version = getattr(mod, "__version__", "unknown")
- if isinstance(version, type("")):
- # Use the string if it's given
- pass
- else:
- # Assume it's a list of version numbers, from major to minor
- ".".join(map(str, version))
- synopsis, text = pydoc.splitdoc(desc)
- print "%s (%s) - %s" % (modname, version, synopsis)
-
-scanner = pydoc.ModuleScanner()
-scanner.run(print_module_info)
-
-#-----------------------------
-
-
-# ^^PLEAC^^_13.0
-#-----------------------------
-# Inside a module named 'Data' / file named 'Data.py'
-class Encoder(object):
- pass
-#-----------------------------
-obj = [3, 5]
-print type(obj), id(obj), ob[1]
-
-## Changing the class of builtin types is not supported
-## in Python.
-
-#-----------------------------
-obj.Stomach = "Empty" # directly accessing an object's contents
-obj.NAME = "Thag" # uppercase field name to make it stand out
-(optional)
-#-----------------------------
-encoded = object.encode("data")
-#-----------------------------
-encoded = Data.Encoder.encode("data")
-#-----------------------------
-class Class(object):
- def __init__(self):
- pass
-#-----------------------------
-object = Class()
-#-----------------------------
-class Class(object):
- def class_only_method():
- pass # more code here
- class_only_method = staticmethod(class_only_method)
-
-#-----------------------------
-class Class(object):
- def instance_only_method(self):
- pass # more code here
-#-----------------------------
-lector = Human.Cannibal()
-lector.feed("Zak")
-lector.move("New York")
-#-----------------------------
-# NOTE: it is rare to use these forms except inside of
-# methods to call specific methods from a parent class
-lector = Human.Cannibal()
-Human.Cannibal.feed(lector, "Zak")
-Human.Cannibal.move(lector, "New York")
-#-----------------------------
-print>>sys.stderr, "stuff here\n"
-
-# ^^PLEAC^^_13.1
-#-----------------------------
-class Class(object):
- pass
-#-----------------------------
-import time
-class Class(object):
- def __init__(self):
- self.start = time.time() # init data fields
- self.age = 0
-#-----------------------------
-import time
-class Class(object):
- def __init__(self, **kwargs):
- # Sets self.start to the current time, and self.age to 0. If called
- # with arguments, interpret them as key+value pairs to
- # initialize the object with
- self.age = 0
- self.__dict__.update(kwargs)
-#-----------------------------
-
-# ^^PLEAC^^_13.2
-#-----------------------------
-import time
-class Class(object):
- def __del__(self):
- print self, "dying at", time.ctime()
-#-----------------------------
-## Why is the perl code introducing a cycle? I guess it's an
-## example of how to keep from calling the finalizer
-self.WHATEVER = self
-#-----------------------------
-
-# ^^PLEAC^^_13.3
-#-----------------------------
-# It is standard practice to access attributes directly:
-class MyClass(object)
- def __init__(self):
- self.name = "default"
- self.age = 0
-obj = MyClass()
-obj.name = "bob"
-print obj.name
-obj.age += 1
-
-# If you later find that you need to compute an attribute, you can always
-# retrofit a property(), leaving user code untouched:
-class MyClass(object):
- def __init__(self):
- self._name = "default"
- self._age = 0
-
- def get_name(self):
- return self._name
- def set_name(self, name):
- self._name = name.title()
- name = property(get_name, set_name)
-
- def get_age(self):
- return self._age
- def set_age(self, val):
- if val < 0:
- raise ValueError("Invalid age: %s" % val)
- self._age = val
- age = property(get_age, set_age)
-obj = MyClass()
-obj.name = "bob"
-print obj.name
-obj.age += 1
-
-# DON'T DO THIS - explicit getters and setters should not be used:
-class MyClass(object):
- def __init__(self):
- self.name = "default"
- def get_name(self):
- return self.name
- def set_name(self, name):
- self.name = name.title()
-obj = MyClass()
-obj.set_name("bob")
-print obj.get_name()
-#-----------------------------
-## DON'T DO THIS (It's complex, ugly, and unnecessary):
-class MyClass(object):
- def __init__(self):
- self.age = 0
- def name(self, *args):
- if len(args) == 0:
- return self.name
- elif len(args) == 1:
- self.name = args[0]
- else:
- raise TypeError("name only takes 0 or 1 arguments")
- def age(self, *args):
- prev = self.age
- if args:
- self.age = args[0]
- return prev
-
-# sample call of get and set: happy birthday!
-obj.age(1 + obj.age())
-
-#-----------------------------
-him = Person()
-him.NAME = "Sylvester"
-him.AGE = 23
-#-----------------------------
-# Here's another way to implement the 'obj.method()' is a getter
-# and 'obj.method(value)' is a settor. Again, this is not a
-# common Python idiom and should not be used. See below for a
-# more common way to do parameter checking of attribute assignment.
-
-import re, sys
-
-def carp(s):
- sys.stderr.write("WARNING: " + s + "\n")
-
-class Class:
- no_name = []
-
- def name(self, value = no_name):
- if value is Class.no_name:
- return self.NAME
- value = self._enforce_name_value(value)
- self.NAME = value
-
- def _enforce_name_value(self, value):
- if re.search(r"[^\s\w'-]", value):
- carp("funny characters in name")
- if re.search(r"\d", value):
- carp("numbers in name")
- if not re.search(r"\S+(\s+\S+)+", value):
- carp("prefer multiword name")
- if not re.search(r"\S", value):
- carp("name is blank")
- return value.upper() # enforce capitalization
-#-----------------------------
-# A more typical way to enforce restrictions on a value
-# to set
-class Class:
- def __setattr__(self, name, value):
- if name == "name":
- value = self._enforce_name_value(value) # Do any conversions
- self.__dict__[name] = value # Do the default __setattr__ action
-
- def _enforce_name_value(self, value):
- if re.search(r"[^\s\w'-]", value):
- carp("funny characters in name")
- if re.search(r"\d", value):
- carp("numbers in name")
- if not re.search(r"\S+(\s+\S+)+", value):
- carp("prefer multiword name")
- if not re.search(r"\S", value):
- carp("name is blank")
- return value.upper() # enforce capitalization
-
-#-----------------------------
-class Person:
- def __init__(self, name = None, age = None, peers = None):
- if peers is None: peers = [] # See Python FAQ 6.25
- self.name = name
- self.age = age
- self.peers = peers
-
- def exclaim(self):
- return "Hi, I'm %s, age %d, working with %s" % \
- (self.name, self.age, ", ".join(self.peers))
-
- def happy_birthday(self):
- self.age += 1
- return self.age
-#-----------------------------
-
-# ^^PLEAC^^_13.4
-#-----------------------------
-## In the module named 'Person' ...
-def population():
- return Person.body_count[0]
-
-class Person(object):
- body_count = [0] # class variable - shared across all instances
-
- def __init__(self):
- self.body_count[0] += 1
-
- def __del__(self): # Beware - may be non-deterministic (Jython)!
- self.body_count[0] -= 1
-
-# later, the user can say this:
-import Person
-people = []
-for i in range(10):
- people.append(Person.Person())
-print "There are", Person.population(), "people alive."
-
-#=> There are 10 people alive.
-#-----------------------------
-him = Person()
-him.gender = "male"
-
-her = Person()
-her.gender = "female"
-
-#-----------------------------
-FixedArray.max_bounds = 100 # set for whole class
-alpha = FixedArray.FixedArray()
-print "Bound on alpha is", alpha.max_bounds
-#=>100
-
-beta = FixedArray.FixedArray()
-beta.max_bounds = 50 # still sets for whole class
-print "Bound on alpha is", alpha.max_bounds
-#=>50
-#-----------------------------
-# In the module named 'FixedArray'
-
-class FixedArray(object):
- _max_bounds = [7] # Shared across whole class
-
- def __init__(self, bounds=None):
- if bounds is not None:
- self.max_bounds = bounds
-
- def get_max_bounds(self):
- return self._max_bounds[0]
- def set_max_bounds(self, val):
- self._max_bounds[0] = val
- max_bounds = property(get_max_bounds, set_max_bounds)
-#-----------------------------
-
-# ^^PLEAC^^_13.5
-#-----------------------------
-# There isn't the severe separation between scalar, arrays and hashs
-# in Python, so there isn't a direct equivalent to the Perl code.
-class Person:
- def __init__(self, name=None, age=None, peers=None):
- if peers is None:
- peers = []
- self.name = name
- self.age = age
- self.peers = peers
-
-p = Person("Jason Smythe", 13, ["Wilbur", "Ralph", "Fred"])
-
-# or this way. (This is not the prefered style as objects should
-# be constructed with all the appropriate data, if possible.)
-
-p = Person() # allocate an empty Person
-p.name = "Jason Smythe" # set its name field
-p.age = 13 # set its age field
-p.peers.extend( ["Wilbur", "Ralph", "Fred" ] ) # set its peers field
-
-p.peers = ["Wilbur", "Ralph", "Fred"]
-
-p.peers[:]= ["Wilbur", "Ralph", "Fred"]
-
-# fetch various values, including the zeroth friend
-print "At age %d, %s's first friend is %s." % \
- (p.age, p.name, p.peers[0])
-#-----------------------------
-# This isn't very Pythonic - should create objects with the
-# needed data, and not depend on defaults and modifing the object.
-import sys
-def carp(s):
- sys.stderr.write("WARNING: " + s + "\n")
-
-class Person:
- def __init__(self, name = "", age = 0):
- self.name = name
- self.age = age
- def __setattr__(self, name, value):
- if name == "age":
- # This is very unpythonic
- if not isinstance(value, type(0)):
- carp("age '%s' isn't numeric" % (value,))
- if value > 150: carp("age '%s' is unreasonable" % (value,))
- self.__dict__[name] = value
-
-class Family:
- def __init__(self, head = None, address = "", members = None):
- if members is None: members = []
- self.head = head or Person()
- self.address = address
- self.members = members
-
-folks = Family()
-
-dad = folks.head
-dad.name = "John"
-dad.age = 34
-
-print "%s's age is %d" % (folks.head.name, folks.head.age)
-#-----------------------------
-class Card:
- def __init__(self, name=None, color=None, cost=None,
- type=None, release=None, text=None):
- self.name = name
- self.color = color
- self.cost = cost
- self.type = type
- self.release = release
- self.type = type
-#-----------------------------
-# For positional args
-class Card:
- _names = ("name", "color", "cost", "type", "release", "type")
- def __init__(self, *args):
- assert len(args) <= len(self._names)
- for k, v in zip(self._names, args):
- setattr(self, k, None)
-#-----------------------------
-# For keyword args
-class Card:
- _names = ("name", "color", "cost", "type", "release", "type")
- def __init__(self, **kwargs):
- for k in self._names: # Set the defaults
- setattr(self, k, None)
- for k, v in kwargs.items(): # add in the kwargs
- assert k in self._names, "Unexpected kwarg: " + k
- setattr(self, k, v)
-#-----------------------------
-class hostent:
- def __init__(self, addr_list = None, length = None,
- addrtype = None, aliases = None, name = None):
- self.addr_list = addr_list or []
- self.length = length or 0
- self.addrtype = addrtype or ""
- self.aliases = aliases or []
- self.name = name or ""
-#-----------------------------
-## XXX What do I do with these?
-#define h_type h_addrtype
-#define h_addr h_addr_list[0]
-#-----------------------------
-# make (hostent object)->type() same as (hostent object)->addrtype()
-#
-# *hostent::type = \&hostent::addrtype;
-#
-# # make (hostenv object)->
-# addr()
-# same as (hostenv object)->addr_list(0)
-#sub hostent::addr { shift->addr_list(0,@_) }
-#-----------------------------
-# No equivalent to Net::hostent (Python uses an unnamed tuple)
-#package Extra::hostent;
-#use Net::hostent;
-#@ISA = qw(hostent);
-#sub addr { shift->addr_list(0,@_) }
-#1;
-#-----------------------------
-
-# ^^PLEAC^^_13.6
-#-----------------------------
-class Class(Parent):
- pass
-#-----------------------------
-## Note: this is unusual in Python code
-ob1 = SomeClass()
-# later on
-ob2 = ob1.__class__()
-#-----------------------------
-## Note: this is unusual in Python code
-ob1 = Widget()
-ob2 = ob1.__class__()
-#-----------------------------
-# XXX I do not know the intent of the original Perl code
-# Do not use this style of programming in Python.
-import time
-class Person(possible,base,classes):
- def __init__(self, *args, **kwargs):
- # Call the parents' constructors, if there are any
- for baseclass in self.__class__.__bases__:
- init = getattr(baseclass, "__init__")
- if init is not None:
- init(self, *args, **kwargs)
- self.PARENT = parent # init data fields
- self.START = time.time()
- self.AGE = 0
-#-----------------------------
-
-# ^^PLEAC^^_13.7
-#-----------------------------
-methname = "flicker"
-getattr(obj, methname)(10) # calls obj->flicker(10);
-
-# call three methods on the object, by name
-for m in ("start", "run", "stop"):
- getattr(obj, m)()
-#-----------------------------
-methods = ("name", "rank", "serno")
-his_info = {}
-for m in methods:
- his_info[m] = getattr(ob, m)()
-
-# same as this:
-
-his_info = {
- 'name': ob.name(),
- 'rank': ob.rank(),
- 'serno': ob.serno(),
-}
-#-----------------------------
-fnref = ob.method
-#-----------------------------
-fnref(10, "fred")
-#-----------------------------
-obj.method(10, "fred")
-#-----------------------------
-# XXX Not sure if this is the correct translation.
-# XXX Is 'can' special?
-if isinstance(obj_target, obj.__class__):
- obj.can('method_name')(obj_target, *arguments)
-#-----------------------------
-
-# ^^PLEAC^^_13.8
-#-----------------------------
-isinstance(obj, mimetools.Message)
-issubclass(obj.__class__, mimetools.Message)
-
-if hasattr(obj, "method_name"): # check method validity
- pass
-#-----------------------------
-## Explicit type checking is needed fewer times than you think.
-his_print_method = getattr(obj, "as_string", None)
-#-----------------------------
-__version__ = (3, 0)
-Some_Module.__version__
-
-# Almost never used, and doesn't work for builtin types, which don't
-# have a __module__.
-
-his_vers = obj.__module__.__version__
-#-----------------------------
-if Some_Module.__version__ < (3, 0):
- raise ImportError("Some_Module version %s is too old, expected (3, 0)" %
- (Some_Module.__version__,))
-# or more simply
-assert Some_Module.__version__ >= (3, 0), "version too old"
-
-#-----------------------------
-__VERSION__ = '1.01'
-#-----------------------------
-
-# ^^PLEAC^^_13.9
-#-----------------------------
-# Note: This uses the standard Python idiom of accessing the
-# attributes directly rather than going through a method call.
-# See earlier in this chapter for examples of how this does
-# not break encapsulation.
-class Person:
- def __init__(self, name = "", age = 0):
- self.name = name
- self.age = age
-#-----------------------------
-# Prefered: dude = Person("Jason", 23)
-dude = Person()
-dude.name = "Jason"
-dude.age = 23
-print "%s is age %d." % (dude.name, dude.age)
-#-----------------------------
-class Employee(Person):
- pass
-#-----------------------------
-# Prefered: empl = Employee("Jason", 23)
-emp = Employee()
-empl.name = "Jason"
-empl.age = 23
-print "%s is age %d." % (empl.name, empl.age)
-#-----------------------------
-
-# ^^PLEAC^^_13.10
-#-----------------------------
-# This doesn't need to be done since if 'method' doesn't
-# exist in the Class it will be looked for in its BaseClass(es)
-class Class(BaseClass):
- def method(self, *args, **kwargs):
- BaseClass.method(self, *args, **kwargs)
-
-# This lets you pick the specific method in one of the base classes
-class Class(BaseClass1, BaseClass2):
- def method(self, *args, **kwargs):
- BaseClass2.method(self, *args, **kwargs)
-
-# This looks for the first method in the base class(es) without
-# specifically knowing which base class. This reimplements
-# the default action so isn't really needed.
-class Class(BaseClass1, BaseClass2, BaseClass3):
- def method(self, *args, **kwargs):
- for baseclass in self.__class__.__bases__:
- f = getattr(baseclass, "method")
- if f is not None:
- return f(*args, **kwargs)
- raise NotImplementedError("method")
-
-#-----------------------------
-self.meth() # Call wherever first meth is found
-
-Where.meth(self) # Call in the base class "Where"
-
-# XXX Does Perl only have single inheritence? Or does
-# it check all base classes? No directly equivalent way
-# to do this in Python, but see above.
-#-----------------------------
-import time
-
-# The Perl code calls a private '_init' function, but in
-# Python there's need for the complexity of 'new' mechanism
-# so it's best just to put the '_init' code in '__init__'.
-class Class:
- def __init__(self, *args):
- # init data fields
- self.START = time.time()
- self.AGE = 0
- self.EXTRA = args # anything extra
-#-----------------------------
-obj = Widget(haircolor = "red", freckles = 121)
-#-----------------------------
-class Class(Base1, Base2, Base3):
- def __init__(self, *args, **kwargs):
- for base in self.__class__.__bases__:
- f = getattr(base, "__init__")
- if f is not None:
- f(self, *args, **kwargs)
-#-----------------------------
-
-# ^^PLEAC^^_13.11
-#-----------------------------
-# NOTE: Python prefers direct attribute lookup rather than
-# method calls. Python 2.2 will introduce a 'get_set' which
-# *may* be equivalent, but I don't know enough about it. So
-# instead I'll describe a class that lets you restrict access
-# to only specific attributes.
-
-class Private:
- def __init__(self, names):
- self.__names = names
- self.__data = {}
- def __getattr__(self, name):
- if name in self.__names:
- return self.__data[name]
- raise AttributeError(name)
- def __setattr__(self, name, value):
- if name.startswith("_Private"):
- self.__dict__[name] = value
- return
- if name in self.__names:
- self.__data[name] = value
- return
- raise TypeError("cannot set the attribute %r" % (name,))
-
-class Person(Private):
- def __init__(self, parent = None):
- Private.__init__(self, ["name", "age", "peers", "parent"])
- self.parent = parent
- def new_child(self):
- return Person(self)
-#-----------------------------
-dad = Person()
-dad.name = "Jason"
-dad.age = 23
-kid = dad.new_child()
-kid.name = "Rachel"
-kid.age = 2
-print "Kid's parent is", kid.parent.name
-#=>Kid's parent is Jason
-
-# ^^PLEAC^^_13.12
-#-----------------------------
-## XXX No clue on what this does. For that matter, what's
-## "The Data Inheritance Problem"?
-
-# ^^PLEAC^^_13.13
-#-----------------------------
-node.NEXT = node
-#-----------------------------
-# This is not a faithful copy of the Perl code, but it does
-# show how to have the container's __del__ remove cycles in
-# its contents. Note that Python 2.0 includes a garbage
-# collector that is able to remove these sorts of cycles, but
-# it's still best to prevent cycles in your code.
-class Node:
- def __init__(self, value = None):
- self.next = self
- self.prev = self
- self.value = value
-
-class Ring:
- def __init__(self):
- self.ring = None
- self.count = 0
-
- def __str__(self):
- # Helpful when debugging, to print the contents of the ring
- s = "#%d: " % self.count
- x = self.ring
- if x is None:
- return s
- values = []
- while True:
- values.append(x.value)
- x = x.next
- if x is self.ring:
- break
- return s + " -> ".join(map(str, values)) + " ->"
-
- def search(self, value):
- node = self.ring
- while True:
- if node.value == value:
- return node
- node = node.next
- if node is self.ring:
- break
-
- def insert_value(self, value):
- node = Node(value)
- if self.ring is not None:
- node.prev, node.next = self.ring.prev, self.ring
- self.ring.prev.next = self.ring.prev = node
- self.ring = node
- self.count += 1
-
- def delete_value(self, value):
- node = self.search(value)
- if node is not None:
- self.delete_node(node)
-
- def delete_node(self, node):
- if node is node.next:
- node.next = node.prev = None
- self.ring = None
- else:
- node.prev.next, node.next.prev = node.next, node.prev
- if node is self.ring:
- self.ring = node.next
- self.count -= 1
-
- def __del__(self):
- while self.ring is not None:
- self.delete_node(self.ring)
-
-COUNT = 1000
-for rep in range(20):
- r = Ring()
- for i in range(COUNT):
- r.insert_value(i)
-#-----------------------------
-
-# ^^PLEAC^^_13.14
-#-----------------------------
-import UserString
-class MyString(UserString.UserString):
- def __cmp__(self, other):
- return cmp(self.data.upper(), other.upper())
-
-class Person:
- def __init__(self, name, idnum):
- self.name = name
- self.idnum = idnum
- def __str__(self):
- return "%s (%05d)" % (self.name.lower().capitalize(), self.idnum)
-
-#-----------------------------
-class TimeNumber:
- def __init__(self, hours, minutes, seconds):
- assert minutes < 60 and seconds < 60
- self.hours = hours
- self.minutes = minutes
- self.seconds = seconds
- def __str__(self):
- return "%d:%02d:%02d" % (self.hours, self.minutes, self.seconds)
- def __add__(self, other):
- seconds = self.seconds + other.seconds
- minutes = self.minutes + other.minutes
- hours = self.hours + other.hours
- if seconds >= 60:
- seconds %= 60
- minutes += 1
- if minutes >= 60:
- minutes %= 60
- hours += 1
- return TimeNumber(hours, minutes, seconds)
-
- def __sub__(self, other):
- raise NotImplementedError
-
- def __mul__(self, other):
- raise NotImplementedError
-
- def __div__(self, other):
- raise NotImplementedError
-
-t1 = TimeNumber(0, 58, 59)
-sec = TimeNumber(0, 0, 1)
-min = TimeNumber(0, 1, 0)
-print t1 + sec + min + min
-# 1:01:00
-
-#-----------------------------
-# For demo purposes only - the StrNum class is superfluous in this
-# case as plain strings would give the same result.
-class StrNum:
- def __init__(self, value):
- self.value = value
-
- def __cmp__(self, other): # both <=> and cmp
- # providing <=> gives us <, ==, etc. for free.
- # __lt__, __eq__, and __gt__ can also be individually specified
- return cmp(self.value, other.value)
-
- def __str__(self): # ""
- return self.value
-
- def __nonzero__(self, other): # bool
- return bool(self.value)
-
- def __int__(self, other): # 0+
- return int(self.value)
-
- def __add__(self, other): # +
- return StrNum(self.value + other.value)
-
- def __radd__(self, other): # +, inverted
- return StrNum(other.value + self.value)
-
- def __mul__(self, other): # *
- return StrNum(self.value * other)
-
- def __rmul__(self, other): # *, inverted
- return StrNum(self.value * other)
-
-
-def demo():
- # show_strnum - demo operator overloading
- x = StrNum("Red")
- y = StrNum("Black")
- z = x + y
- r = z * 3
- print "values are %s, %s, %s, and %s" % (x, y, z, r)
- if x < y:
- s = "LT"
- else:
- s = "GE"
- print x, "is", s, y
-
-if __name__ == "__main__":
- demo()
-# values are Red, Black, RedBlack, and RedBlackRedBlackRedBlack
-# Red is GE Black
-
-#-----------------------------
-#!/usr/bin/env python
-# demo_fixnum - show operator overloading
-
-# sum of STRFixNum: 40 and STRFixNum: 12 is STRFixNum: 52
-# product of STRFixNum: 40 and STRFixNum: 12 is STRFixNum: 480
-# STRFixNum: 3 has 0 places
-# div of STRFixNum: 40 by STRFixNum: 12 is STRFixNum: 3.33
-# square of that is STRFixNum: 11.11
-
-# This isn't excatly the same as the original Perl code since
-# I couldn't figure out why the PLACES variable was used.
-#-----------------------------
-import re
-_places_re = re.compile(r"\.(\d+)")
-
-default_places = 0
-
-class FixNum:
- def __init__(self, value, places = None):
- self.value = value
- if places is None:
- # get from the value
- m = _places_re.search(str(value))
- if m:
- places = int(m.group(1))
- else:
- places = default_places
- self.places = places
-
- def __add__(self, other):
- return FixNum(self.value + other.value,
- max(self.places, other.places))
-
- def __mul__(self, other):
- return FixNum(self.value * other.value,
- max(self.places, other.places))
-
- def __div__(self, other):
- # Force to use floating point, since 2/3 in Python is 0
- # Don't use float() since that will convert strings
- return FixNum((self.value+0.0) / other.value,
- max(self.places, other.places))
-
- def __str__(self):
- return "STR%s: %.*f" % (self.__class__.__name__,
- self.places, self.value)
- def __int__(self):
- return int(self.value)
-
- def __float__(self):
- return self.value
-
-def demo():
- x = FixNum(40)
- y = FixNum(12, 0)
-
- print "sum of", x, "and", y, "is", x+y
- print "product of", x, "and", y, "is", x*y
-
- z = x/y
- print "%s has %d places" % (z, z.places)
- if not z.places:
- z.places = 2
-
- print "div of", x, "by", y, "is", z
- print "square of that is ", z*z
-
-if __name__ == "__main__":
- demo()
-
-
-# ^^PLEAC^^_13.15
-# You can't tie a variable, but you can use properties.
-import itertools
-class ValueRing(object):
- def __init__(self, colours):
- self.colourcycle = itertools.cycle(colours)
-
- def next_colour(self):
- return self.colourcycle.next()
- colour = property(next_colour)
-vr = ValueRing(["red", "blue"])
-for i in range(6):
- print vr.colour,
-print
-
-# Note that you MUST refer directly to the property
-x = vr.colour
-print x, x, x
-#-------------------------------------
-# Ties are generally unnecessary in Python because of its strong OO support -
-# The resulting code is MUCH shorter:
-class AppendDict(dict):
- def __setitem__(self, key, val):
- if key in self:
- self[key].append(val)
- else:
- super(AppendDict, self).__setitem__(key, [val])
-tab = AppendDict()
-tab["beer"] = "guinness"
-tab["food"] = "potatoes"
-tab["food"] = "peas"
-
-for key, val in tab.items():
- print key, "=>", val
-#-------------------------------------
-class CaselessDict(dict):
- def __setitem__(self, key, val):
- super(CaselessDict, self).__setitem__(key.lower(), val)
- def __getitem__(self, key):
- return super(CaselessDict, self).__getitem__(key.lower())
-
-tab = CaselessDict()
-tab["VILLAIN"] = "big "
-tab["herOine"] = "red riding hood"
-tab["villain"] = "bad wolf"
-
-for key, val in tab.items():
- print key, "is", val
-#=>villain is bad wolf
-#=>heroine is red riding hood
-#-------------------------------------
-class RevDict(dict):
- def __setitem__(self, key, val):
- super(RevDict, self).__setitem__(key, val)
- super(RevDict, self).__setitem__(val, key)
-
-tab = RevDict()
-tab["red"] = "rojo"
-tab["blue"] = "azul"
-tab["green"] = "verde"
-tab["evil"] = ("No Way!", "Way!")
-
-for key, val in tab.items():
- print key, "is", val
-#=>blue is azul
-#=>('No Way!', 'Way!') is evil
-#=>rojo is red
-#=>evil is ('No Way!', 'Way!')
-#=>azul is blue
-#=>verde is green
-#=>green is verde
-#=>red is rojo
-#-------------------------------------
-import itertools
-for elem in itertools.count():
- print "Got", elem
-#-------------------------------------
-# You could use FileDispatcher from section 7.18
-tee = FileDispatcher(sys.stderr, sys.stdout)
-#-------------------------------------
-# @@PLEAC@@_14.0
-
-# See http://www.python.org/doc/topics/database/ for Database Interfaces details.
-# currently listed on http://www.python.org/doc/topics/database/modules/
-#
-# DB/2, Informix, Interbase, Ingres, JDBC, MySQL, pyodbc, mxODBC, ODBC Interface,
-# DCOracle, DCOracle2, PyGresQL, psycopg, PySQLite, sapdbapi, Sybase, ThinkSQL.
-#
-
-# @@PLEAC@@_14.1
-#-------------------------------------
-import anydbm
-filename = "test.db"
-try:
- db = anydbm.open(filename)
-except anydbm, err:
- print "Can't open %s: %s!" % (filename, err)
-
-db["key"] = "value" # put value into database
-if "key" in db: # check whether in database
- val = db.pop("key") # retrieve and remove from database
-db.close() # close the database
-#-------------------------------------
-# download the following standalone program
-#!/usr/bin/python
-# userstats - generates statistics on who logged in.
-# call with an argument to display totals
-
-import sys, os, anydbm, re
-
-db_file = '/tmp/userstats.db' # where data is kept between runs
-
-try:
- db = anydbm.open(db_file,'c') # open, create if it does not exist
-except:
- print "Can't open db %s: %s!" % (db_file, sys.exc_info()[1])
- sys.exit(1)
-
-if len(sys.argv) > 1:
- if sys.argv[1] == 'ALL':
- userlist = db.keys()
- else:
- userlist = sys.argv[1:]
- userlist.sort()
- for user in userlist:
- if db.has_key(user):
- print "%s\t%s" % (user, db[user])
- else:
- print "%s\t%s" % (user, 0)
-else:
- who = os.popen('who').readlines() # run who(1)
- if len(who)<1:
- print "error running who" # exit
- sys.exit(1)
- # extract username (first thin on the line) and update
- user_re = re.compile("^(\S+)")
- for line in who:
- fnd = user_re.search(line)
- if not fnd:
- print "Bad line from who: %s" % line
- sys.exit(1)
- user = fnd.groups()[0]
- if not db.has_key(user):
- db[user] = "0"
- db[user] = str(int(db[user])+1) # only strings are allowed
-db.close()
-
-
-
-
-# @@PLEAC@@_14.2
-# Emptying a DBM File
-
-import anydbm
-
-try:
- db = anydbm.open(FILENAME,'w') # open, for writing
-except anydbm.error, err:
- print "Can't open db %s: %s!" % (filename, err)
- raise SystemExit(1)
-
-db.clear()
-db.close()
-# -------------------------------
-try:
- db = anydbm.open(filename,'n') # open, always create a new empty db
-except anydbm.error, err:
- print "Can't open db %s: %s!" % (filename, err)
- raise SystemExit(1)
-
-db.close()
-# -------------------------------
-import os
-try:
- os.remove(FILENAME)
-except OSError, err:
- print "Couldn't remove %s to empty the database: %s!" % (FILENAME,
- err)
- raise SystemExit
-
-try:
- db = anydbm.open(FILENAME,'n') # open, flways create a new empty db
-except anydbm.error, err:
- print "Couldn't create %s database: %s!" % (FILENAME, err)
- raise SystemExit
-
-# @@PLEAC@@_14.3
-# Converting Between DBM Files
-
-# download the following standalone program
-#!/usr/bin/python
-# db2gdbm: converts DB to GDBM
-
-import sys
-import dbm, gdbm
-
-if len(sys.argv)<3:
- print "usage: db2gdbm infile outfile"
- sys.exit(1)
-
-(infile, outfile) = sys.argv[1:]
-
-# open the files
-try:
- db_in = dbm.open(infile)
-except:
- print "Can't open infile %s: %s!" % (infile, sys.exc_info()[1])
- sys.exit(1)
-try:
- db_out = dbm.open(outfile,"n")
-except:
- print "Can't open outfile %s: %s!" % (outfile, sys.exc_info()[1])
- sys.exit(1)
-
-# copy (don't use db_out = db_in because it's slow on big databases)
-# is this also so for python ?
-for k in db_in.keys():
- db_out[k] = db_in[k]
-
-# these close happen automatically at program exit
-db_out.close()
-db_in.close()
-
-
-
-# @@PLEAC@@_14.4
-
-OUTPUT.update(INPUT1)
-OUTPUT.update(INPUT2)
-
-OUTPUT = anydbm.open("OUT","n")
-for INPUT in (INPUT1, INPUT2, INPUT1):
- for key, value in INPUT.iteritems():
- if OUTPUT.has_key(key):
- # decide which value to use and set OUTPUT[key] if necessary
- print "key %s already present: %s, new: %s" % (
- key, OUTPUT[key], value )
- else:
- OUTPUT[key] = value
-
-# @@PLEAC@@_14.5
-# On systems where the Berkeley DB supports it, dbhash takes an
-# "l" flag:
-import dbhash
-dbhash.open("mydb.db", "cl") # 'c': create if doesn't exist
-
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_14.6
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_14.7
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_14.8
-# shelve uses anydbm to access and chooses between DBMs.
-# anydbm detect file formats automatically.
-import shelve
-db = shelve.open("celebrities.db")
-
-name1 = "Greg Stein"
-name2 = "Greg Ward"
-
-# shelve uses pickle to convert objects into strings and back.
-# This is automatic.
-db[name1] = ["of ViewCVS fame", "gstein@lyra.org"]
-db[name2] = ["of Distutils fame", "gward@python.net"]
-
-greg1 = db[name1]
-greg2 = db[name2]
-
-print "Two Gregs: %x %x" % (id(greg1), id(greg2))
-
-if greg1 == greg2:
- print "You're having runtime fun with one Greg made two."
-else:
- print "No two Gregs are ever alike."
-
-# Changes to mutable entries are not written back by default.
-# You can get the copy, change it, and put it back.
-entry = db[name1]
-entry[0] = "of Subversion fame"
-db[name1] = entry
-
-# Or you can open shelve with writeback option. Then you can
-# change mutable entries directly. (New in 2.3)
-db = shelve.open("celebrities.db", writeback=True)
-db[name2][0] = "of Optik fame"
-
-# However, writeback option can consume vast amounts of memory
-# to do its magic. You can clear cache with sync().
-db.sync()
-#-----------------------------
-
-# @@PLEAC@@_14.9
-# DON'T DO THIS.
-import os as _os, shelve as _shelve
-
-_fname = "persist.db"
-if not _os.path.exists(_fname):
- var1 = "foo"
- var2 = "bar"
-_d = _shelve.open("persist.db")
-globals().update(_d)
-
-print "var1 is %s; var2 is %s"%(var1, var2)
-var1 = raw_input("New var1: ")
-var2 = raw_input("New var2: ")
-
-for key, val in globals().items():
- if not key.startswith("_"):
- _d[key] = val
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_14.10
-#-----------------------------
-import dbmodule
-
-dbconn = dbmodule.connect(arguments...)
-
-cursor = dbconn.cursor()
-cursor.execute(sql)
-
-while True:
- row = cursor.fetchone()
- if row is None:
- break
- ...
-
-cursor.close()
-dbconn.close()
-
-#-----------------------------
-import MySQLdb
-import pwd
-
-dbconn = MySQLdb.connect(db='dbname', host='mysqlserver.domain.com',
- port=3306, user='user', passwd='password')
-
-cursor = dbconn.cursor()
-cursor.execute("CREATE TABLE users (uid INT, login CHAR(8))")
-
-# Note: some databases use %s for parameters, some use ? or other
-# formats
-sql_fmt = "INSERT INTO users VALUES( %s, %s )"
-
-for userent in pwd.getpwall():
- # the second argument contains a list of parameters which will
- # be quoted before being put in the query
- cursor.execute(sql_fmt, (userent.pw_uid, userent.pw_name))
-
-cursor.execute("SELECT * FROM users WHERE uid < 50")
-
-for row in cursor.fetchall():
- # NULL will be displayed as None
- print ", ".join(map(str, row))
-
-cursor.execute("DROP TABLE users")
-cursor.close()
-dbconn.close()
-#-----------------------------
-
-# @@PLEAC@@_14.11
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_15.1
-#-----------------------------
-# Parsing program arguments
-# -- getopt way (All Python versions)
-
-#-----------------------------
-# Preamble
-
-import sys
-import getopt
-
-# getopt() explicitly receives arguments for it to process.
-# No magic. Explicit is better than implicit.
-
-# PERL: @ARGV
-argv = sys.argv[1:]
-
-# Note that sys.argv[0] is the script name, and need to be
-# stripped.
-
-#-----------------------------
-# Short options
-
-# PERL: getopt("vDo");
-# Polluting the caller's namespace is evil. Don't do that.
-
-# PERL: getopt("vDo:", \%opts);
-opts, rest = getopt.getopt(argv, "vDo:")
-
-# If you want switches to take arguments, you must say so.
-# Unlike PERL, which silently performs its magic, switches
-# specified without trailing colons are considered boolean
-# flags by default.
-
-# PERL: getopt("vDo", \%opts);
-opts, rest = getopt.getopt(argv, "v:D:o:")
-
-# PERL: getopts("vDo:", \%opts);
-# getopt/getopts distinction is not present in Python 'getopt'
-# module.
-
-#-----------------------------
-# getopt() return values, compared to PERL
-
-# getopt() returns two values. The first is a list of
-# (option, value) pair. (Not a dictionary, i.e. Python hash.)
-# The second is the list of arguments left unprocessed.
-
-# Example
-# >>> argv = "-v ARG1 -D ARG2 -o ARG3".split()
-# >>> opts, rest = getopt.getopt(argv, "v:D:o:")
-# >>> print opts
-# [('-v', 'ARG1'), ('-D', 'ARG2'), ('-o', 'ARG3')]
-
-#-----------------------------
-# Long options
-
-# getopt() handles long options too. Pass a list of option
-# names as the third argument. If an option takes an argument,
-# append an equal sign.
-
-opts, rest = getopt.getopt(argv, "", [
- "verbose", "Debug", "output="])
-
-#-----------------------------
-# Switch clustering
-
-# getopt() does switch clustering just fine.
-
-# Example
-# >>> argv1 = '-r -f /tmp/testdir'.split()
-# >>> argv2 = '-rf /tmp/testdir'.split()
-# >>> print getopt.getopt(argv1, 'rf')
-# ([('-r', ''), ('-f', '')], ['/tmp/testdir'])
-# >>> print getopt.getopt(argv2, 'rf')
-# ([('-r', ''), ('-f', '')], ['/tmp/testdir'])
-
-#-----------------------------
-# @@INCOMPLETE@@
-
-# TODO: Complete this section using 'getopt'. Show how to
-# use the parsed result.
-
-# http://www.python.org/doc/current/lib/module-getopt.html
-# Python library reference has a "typical usage" demo.
-
-# TODO: Introduce 'optparse', a very powerful command line
-# option parsing module. New in 2.3.
-
-
-# @@PLEAC@@_15.2
-##------------------
-import sys
-
-def is_interactive_python():
- try:
- ps = sys.ps1
- except:
- return False
- return True
-##------------------
-import sys
-def is_interactive():
- # only False if stdin is redirected like "-t" in perl.
- return sys.stdin.isatty()
-
-# Or take advantage of Python's Higher Order Functions:
-is_interactive = sys.stdin.isatty
-##------------------
-import posix
-def is_interactive_posix():
- tty = open("/dev/tty")
- tpgrp = posix.tcgetpgrp(tty.fileno())
- pgrp = posix.getpgrp()
- tty.close()
- return (tpgrp == pgrp)
-
-# test with:
-# python 15.2.py
-# echo "dummy" | python 15.2.py | cat
-print "is python shell:", is_interactive_python()
-print "is a tty:", is_interactive()
-print "has no tty:", is_interactive_posix()
-
-if is_interactive():
- while True:
- try:
- ln = raw_input("Prompt:")
- except:
- break
- print "you typed:", ln
-
-
-# @@PLEAC@@_15.3
-
-# Python has no Term::Cap module.
-# One could use the curses, but this was not ported to windows,
-# use console.
-
-# just run clear
-import os
-os.system("clear")
-# cache output
-clear = os.popen("clear").read()
-print clear
-# or to avoid print's newline
-sys.stdout.write(clear)
-
-# @@PLEAC@@_15.4
-# Determining Terminal or Window Size
-
-# eiter use ioctl
-import struct, fcntl, termios, sys
-
-s = struct.pack("HHHH", 0, 0, 0, 0)
-hchar, wchar = struct.unpack("HHHH", fcntl.ioctl(sys.stdout.fileno(),
- termios.TIOCGWINSZ, s))[:2]
-# or curses
-import curses
-(hchar,wchar) = curses.getmaxyx()
-
-# graph contents of values
-import struct, fcntl, termios, sys
-width = struct.unpack("HHHH", fcntl.ioctl(sys.stdout.fileno(),
- termios.TIOCGWINSZ,
- struct.pack("HHHH", 0, 0, 0, 0)))[1]
-if width<10:
- print "You must have at least 10 characters"
- raise SystemExit
-
-max_value = 0
-for v in values:
- max_value = max(max_value,v)
-
-ratio = (width-10)/max_value # chars per unit
-for v in values:
- print "%8.1f %s" % (v, "*"*(v*ratio))
-
-# @@PLEAC@@_15.5
-
-# there seems to be no standard ansi module
-# and BLINK does not blink here.
-RED = '\033[31m'
-RESET = '\033[0;0m'
-BLINK = '\033[05m'
-NOBLINK = '\033[25m'
-
-print RED+"DANGER, Will Robinson!"+RESET
-print "This is just normal text"
-print "Will ``"+BLINK+"Do you hurt yet?"+NOBLINK+"'' and back"
-
-# @@PLEAC@@_15.6
-
-# Show ASCII values for keypresses
-
-# _Getch is from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/134892
-class _Getch:
- """Gets a single character from standard input. Doesn't echo to screen."""
- def __init__(self):
- try:
- self.impl = _GetchWindows()
- except ImportError:
- self.impl = _GetchUnix()
-
- def __call__(self):
- return self.impl()
-
-
-class _GetchUnix:
- def __init__(self):
- import tty, sys
-
- def __call__(self):
- import sys, tty, termios
- fd = sys.stdin.fileno()
- old_settings = termios.tcgetattr(fd)
- try:
- tty.setraw(sys.stdin.fileno())
- ch = sys.stdin.read(1)
- finally:
- termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
- return ch
-
-
-class _GetchWindows:
- def __init__(self):
- import msvcrt
-
- def __call__(self):
- import msvcrt
- return msvcrt.getch()
-
-
-getch = _Getch()
-
-print "Press keys to see their ASCII values. Use Ctrl-C to quit.\n"
-try:
- while True:
- char = ord(getch())
- if char == 3:
- break
- print " Decimal: %3d Octal: %3o Hex: x%02x" % (char, char, char)
-except KeyboardError:
- pass
-#----------------------------------------
-
-# @@PLEAC@@_15.7
-print "\aWake up!\n";
-#----------------------------------------
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_15.8
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_15.9
-# On Windows
-import msvcrt
-if msvcrt.kbhit():
- c = msvcrt.getch
-
-# See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/134892
-# @@INCOMPLETE@@
-
-
-# @@PLEAC@@_15.10
-#----------------------------------------
-import getpass
-import pwd
-import crypt
-password = getpass.getpass('Enter your password: ')
-username = getpass.getuser()
-encrypted = pwd.getpwnam(username).pw_passwd
-if not encrypted or encrypted == 'x':
- # If using shadow passwords, this will be empty or 'x'
- print "Cannot verify password"
-elif crypt.crypt(password, encrypted) != encrypted:
- print "You are not", username
-else:
- print "Welcome,", username
-#----------------------------------------
-
-# @@PLEAC@@_15.11
-
-# simply importing readline gives line edit capabilities to raw_
-import readline
-readline.add_history("fake line")
-line = raw_input()
-
-# download the following standalone program
-#!/usr/bin/python
-# vbsh - very bad shell
-
-import os
-import readline
-
-while True:
- try:
- cmd = raw_input('$ ')
- except EOFError:
- break
- status = os.system(cmd)
- exit_value = status >> 8
- signal_num = status & 127
- dumped_core = status & 128 and "(core dumped)" or ""
- print "Program terminated with status %d from signal %d%s\n" % (
- exit_value, signal_num, dumped_core)
-
-
-
-readline.add_history("some line!")
-readline.remove_history_item(position)
-line = readline.get_history_item(index)
-
-# an interactive python shell would be
-import code, readline
-code.InteractiveConsole().interact("code.InteractiveConsole")
-
-# @@PLEAC@@_15.12
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_15.13
-#----------------------------------------
-# This entry uses pexpect, a pure Python Expect-like module.
-# http://pexpect.sourceforge.net/
-
-# for more information, check pexpect's documentation and example.
-
-import pexpect
-
-#----------------------------------------
-# spawn program
-try:
- command = pexpect.spawn("program to run")
-except pexpect.ExceptionPexpect:
- # couldn't spawn program
- pass
-
-#----------------------------------------
-# you can pass any filelike object to setlog
-# passing None will stop logging
-
-# stop logging
-command.setlog(None)
-
-# log to stdout
-import sys
-command.setlog(sys.stdout)
-
-# log to specific file
-fp = file("pexpect.log", "w")
-command.setlog(fp)
-
-#----------------------------------------
-# expecting simple string
-command.expect("ftp>")
-
-# expecting regular expression
-# actually, string is always treated as regular expression
-
-# so it's the same thing
-command.expect("Name.*:")
-
-# you can do it this way, too
-import re
-regex = re.compile("Name.*:")
-command.expect(regex)
-
-#----------------------------------------
-# expecting with timeout
-try:
- command.expect("Password:", 10)
-except pexpect.TIMEOUT:
- # timed out
- pass
-
-# setting default timeout
-command.timeout = 10
-
-# since we set default timeout, following does same as above
-try:
- command.expect("Password:")
-except pexpect.TIMEOUT:
- # timed out
- pass
-
-#----------------------------------------
-# what? do you *really* want to wait forever?
-
-#----------------------------------------
-# sending line: normal way
-command.sendline("get spam_and_ham")
-
-# you can also treat it as file
-print>>command, "get spam_and_ham"
-
-#----------------------------------------
-# finalization
-
-# close connection with child process
-# (that is, freeing file descriptor)
-command.close()
-
-# kill child process
-import signal
-command.kill(signal.SIGKILL)
-
-#----------------------------------------
-# expecting multiple choices
-which = command.expect(["invalid", "success", "error", "boom"])
-
-# return value is index of matched choice
-# 0: invalid
-# 1: success
-# 2: error
-# 3: boom
-
-#----------------------------------------
-# avoiding exception handling
-choices = ["invalid", "success", "error", "boom"]
-choices.append(pexpect.TIMEOUT)
-choices.append(pexpect.EOF)
-
-which = command.expect(choices)
-
-# if TIMEOUT or EOF occurs, appropriate index is returned
-# (instead of raising exception)
-# 4: TIMEOUT
-# 5: EOF
-
-# @@PLEAC@@_15.14
-from Tkinter import *
-
-def print_callback():
- print "print_callback"
-
-main = Tk()
-
-menubar = Menu(main)
-main.config(menu=menubar)
-
-file_menu = Menu(menubar)
-menubar.add_cascade(label="File", underline=1, menu=file_menu)
-file_menu.add_command(label="Print", command=print_callback)
-
-main.mainloop()
-
-# using a class
-from Tkinter import *
-
-class Application(Tk):
- def print_callback(self):
- print "print_callback"
- def debug_callback(self):
- print "debug:", self.debug.get()
- print "debug level:", self.debug_level.get()
-
- def createWidgets(self):
- menubar = Menu(self)
- self.config(menu=menubar)
- file_menu = Menu(menubar)
- menubar.add_cascade(label="File",
- underline=1, menu=file_menu)
- file_menu.add_command(label="Print",
- command=self.print_callback)
- file_menu.add_command(label="Quit Immediately",
- command=sys.exit)
- #
- options_menu = Menu(menubar)
- menubar.add_cascade(label="Options",
- underline=0, menu=options_menu)
- options_menu.add_checkbutton(
- label="Create Debugging File",
- variable=self.debug,
- command=self.debug_callback,
- onvalue=1, offvalue=0)
- options_menu.add_separator()
- options_menu.add_radiobutton(
- label = "Level 1",
- variable = self.debug_level,
- value = 1
- )
- options_menu.add_radiobutton(
- label = "Level 2",
- variable = self.debug_level,
- value = 2
- )
- options_menu.add_radiobutton(
- label = "Level 3",
- variable = self.debug_level,
- value = 3
- )
-
- def __init__(self, master=None):
- Tk.__init__(self, master)
- # bound variables must be IntVar, StrVar, ...
- self.debug = IntVar()
- self.debug.set(0)
- self.debug_level = IntVar()
- self.debug_level.set(1)
- self.createWidgets()
-
-app = Application()
-app.mainloop()
-
-# @@PLEAC@@_15.15
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_15.16
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_15.17
-# Start Python scripts without the annoying DOS window on win32
-# Use extension ".pyw" on files - eg: "foo.pyw" instead of "foo.py"
-# Or run programs using "pythonw.exe" rather than "python.exe"
-
-# @@PLEAC@@_15.18
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_15.19
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-
-# @@PLEAC@@_16.1
-import popen2
-
-# other popen methods than popen4 can lead to deadlocks
-# if there is much data on stdout and stderr
-
-(err_out, stdin) = popen2.popen4("program args")
-lines = err_out.read() # collect output into one multiline string
-
-(err_out, stdin) = popen2.popen4("program args")
-lines = err_out.readlines() # collect output into a list, one line per element
-
-#-----------------------------
-
-(err_out, stdin) = popen2.popen4("program args")
-output = []
-while True:
- line = err_out.readline()
- if not line:
- break
- output.appen(line)
-output = ''.join(output)
-
-# @@PLEAC@@_16.2
-import os
-myfile = "foo.txt"
-status = os.system("vi %s" % myfile)
-
-#-----------------------------
-import os
-os.system("cmd1 args | cmd2 | cmd3 >outfile")
-os.system("cmd args <infile >outfile 2>errfile")
-
-status = os.system("%s %s %s" % (program, arg1, arg2))
-if status != 0:
- print "%s exited funny: %s" % (program, status)
- raise SystemExit
-
-
-# @@PLEAC@@_16.3
-# -----------------------------
-import os
-import sys
-import glob
-
-args = glob.glob("*.data")
-try:
- os.execvp("archive", args)
-except OSError, e:
- print "Couldn't replace myself with archive: %s" % err
- raise SystemExit
-
-# The error message does not contain the line number like the "die" in
-# perl. But if you want to show more information for debugging, you can
-# delete the try...except and you get a nice traceback which shows all
-# line numbers and filenames.
-
-# -----------------------------
-os.execvp("archive", ["accounting.data"])
-
-# @@PLEAC@@_16.4
-# -------------------------
-# Read from a child process
-
-import sys
-import popen2
-pipe = popen2.Popen4("program arguments")
-pid = pipe.pid
-for line in pipe.fromchild.readlines():
- sys.stdout.write(line)
-
-# Popen4 provides stdout and stderr.
-# This avoids deadlocks if you get data
-# from both streams.
-#
-# If you don't need the pid, you
-# can use popen2.popen4(...)
-
-# -----------------------------
-# Write to a child process
-
-import popen2
-
-pipe = popen2.Popen4("gzip > foo.gz")
-pid = pipe.pid
-pipe.tochild.write("Hello zipped world!\n")
-pipe.tochild.close() # programm will get EOF on STDIN
-
-# @@PLEAC@@_16.5
-class OutputFilter(object):
- def __init__(self, target, *args, **kwds):
- self.target = target
- self.setup(*args, **kwds)
- self.textbuffer = ""
-
- def setup(self, *args, **kwds):
- pass
-
- def write(self, data):
- if data.endswith("\n"):
- data = self.process(self.textbuffer + data)
- self.textbuffer = ""
- if data is not None:
- self.target.write(data)
- else:
- self.textbuffer += data
-
- def process(self, data):
- return data
-
-class HeadFilter(OutputFilter):
- def setup(self, maxcount):
- self.count = 0
- self.maxcount = maxcount
-
- def process(self, data):
- if self.count < self.maxcount:
- self.count += 1
- return data
-
-class NumberFilter(OutputFilter):
- def setup(self):
- self.count=0
-
- def process(self, data):
- self.count += 1
- return "%s: %s"%(self.count, data)
-
-class QuoteFilter(OutputFilter):
- def process(self, data):
- return "> " + data
-
-import sys
-f = HeadFilter(sys.stdout, 100)
-for i in range(130):
- print>>f, i
-
-print
-
-txt = """Welcome to Linux, version 2.0.33 on a i686
-
-"The software required `Windows 95 or better',
-so I installed Linux." """
-f1 = NumberFilter(sys.stdout)
-f2 = QuoteFilter(f1)
-for line in txt.split("\n"):
- print>>f2, line
-print
-f1 = QuoteFilter(sys.stdout)
-f2 = NumberFilter(f1)
-for line in txt.split("\n"):
- print>>f2, line
-
-
-# @@PLEAC@@_16.6
-# This script accepts several filenames
-# as argument. If the file is zipped, unzip
-# it first. Then read each line if the file
-import os
-import sys
-import popen2
-
-for file in sys.argv[1:]:
- if file.endswith(".gz") or file.endswith(".Z"):
- (stdout, stdin) = popen2.popen2("gzip -dc '%s'" % file)
- fd = stdout
- else:
- fd = open(file)
- for line in fd:
- # ....
- sys.stdout.write(line)
- fd.close()
-#-----------------------------
-
-#-----------------------------
-# Ask for filename and open it
-import sys
-print "File, please?"
-line = sys.stdin.readline()
-file = line.strip() # chomp
-open(file)
-
-# @@PLEAC@@_16.7
-# Execute foo_command and read the output
-
-import popen2
-(stdout_err, stdin) = popen2.popen4("foo_command")
-for line in stdout_err.readlines():
- # ....
-
-# @@PLEAC@@_16.8
-# Open command in a pipe
-# which reads from stdin and writes to stdout
-
-import popen2
-pipe = popen2.Popen4("wc -l") # Unix command
-pipe.tochild.write("line 1\nline 2\nline 3\n")
-pipe.tochild.close()
-output = pipe.fromchild.read()
-
-# @@PLEAC@@_16.9
-
-# popen3: get stdout and stderr of new process
-# Attetion: This can lead to deadlock,
-# since the buffer of stderr or stdout might get filled.
-# You need to use select if you want to avoid this.
-
-import popen2
-(child_stdout, child_stdin, child_stderr) = popen2.popen3(...)
-
-# @@PLEAC@@_16.10
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_16.11
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_16.12
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_16.13
-#
-# Print available signals and their value
-# See "man signal" "man kill" on unix.
-
-import signal
-for name in dir(signal):
- if name.startswith("SIG"):
- value = getattr(signal, name)
- print "%s=%s" % (name, value)
-
-# @@PLEAC@@_16.14
-# You can send signals to processes
-# with os.kill(pid, signal)
-
-
-# @@PLEAC@@_16.15
-import signal
-
-def get_sig_quit(signum, frame):
- ....
-
-signal.signal(signal.SIGQUIT, get_sig_quit) # Install handler
-
-signal.signal(signal.SIGINT, signal.SIG_IGN) # Ignore this signal
-signal.signal(signal.SIGSTOP, signal.SIG_DFL) # Restore to default handling
-
-# @@PLEAC@@_16.16
-# Example of handler: User must Enter Name ctrl-c does not help
-
-import sys
-import signal
-
-def ding(signum, frame):
- print "\aEnter your name!"
- return
-
-signal.signal(signal.SIGINT, ding)
-print "Please enter your name:"
-
-name = ""
-while not name:
- try:
- name = sys.stdin.readline().strip()
- except:
- pass
-
-print "Hello: %s" % name
-
-# @@PLEAC@@_16.17
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_16.18
-import signal
-
-# ignore signal INT
-signal.signal(signal.SIGINT, signal.SIG_IGN)
-
-# Install signal handler
-def tsktsk(signum, frame):
- print "..."
-
-signal.signal(signal.SIGINT, tsktsk)
-
-# @@PLEAC@@_16.19
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_16.20
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_16.21
-import signal
-
-def handler(signum, frame):
- raise "timeout"
-
-signal.signal(signal.SIGALRM, handler)
-
-try:
- signal.alarm(5) # signal.alarm(3600)
-
- # long-time operation
- while True:
- print "foo"
-
- signal.alarm(0)
-except:
- signal.alarm(0)
- print "timed out"
-else:
- print "no time out"
-
-# @@PLEAC@@_16.22
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_17.0
-# Socket Programming (tcp/ip and udp/ip)
-
-import socket
-
-# Convert human readable form to 32 bit value
-packed_ip = socket.inet_aton("208.146.240.1")
-packed_ip = socket.inet_aton("www.oreilly.com")
-
-# Convert 32 bit value to ip adress
-ip_adress = socket.inet_ntoa(packed_ip)
-
-# Create socket object
-socketobj = socket(family, type) # Example socket.AF_INT, socket.SOCK_STREAM
-
-# Get socketname
-socketobj.getsockname() # Example, get port adress of client
-
-# @@PLEAC@@_17.1
-
-# Example: Connect to a server (tcp)
-# Connect to a smtp server at localhost and send an email.
-# For real applications you should use smtplib.
-
-import socket
-s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-s.connect(("localhost", 25)) # SMTP
-print s.recv(1024)
-s.send("mail from: <pleac@localhost>\n")
-print s.recv(1024)
-s.send("rcpt to: <guettli@localhost>\n")
-print s.recv(1024)
-s.send("data\n")
-print s.recv(1024)
-s.send("From: Python Lover\nSubject: Python is better then perl\n\nYES!\n.\n")
-print s.recv(1024)
-s.close()
-
-# @@PLEAC@@_17.2
-
-# Create a Server, calling handler for every client
-# You can test it with "telnet localhost 1029"
-
-from SocketServer import TCPServer
-from SocketServer import BaseRequestHandler
-
-class MyHandler(BaseRequestHandler):
- def handle(self):
- print "I got an request"
-
-server = TCPServer(("127.0.0.1", 1029), MyHandler)
-server.serve_forever()
-
-# @@PLEAC@@_17.3
-# This is the continuation of 17.2
-
-import time
-from SocketServer import TCPServer
-from SocketServer import BaseRequestHandler
-
-class MyHandler(BaseRequestHandler):
- def handle(self):
- # self.request is the socket object
- print "%s I got an request from ip=%s port=%s" % (
- time.strftime("%Y-%m-%d %H:%M:%S"),
- self.client_address[0],
- self.client_address[1]
- )
- self.request.send("What is your name?\n")
- bufsize=1024
- response=self.request.recv(bufsize).strip() # or recv(bufsize, flags)
- data_to_send="Welcome %s!\n" % response
- self.request.send(data_to_send) # or send(data, flags)
- print "%s connection finnished" % self.client_address[0]
-
-server = TCPServer(("127.0.0.1", 1028), MyHandler)
-server.serve_forever()
-
-# -----------------
-# Using select
-
-import select
-import socket
-
-in_list = []
-in_list.append(mysocket)
-in_list.append(myfile)
-# ...
-
-out_list = []
-out_list.append(...)
-
-except_list = []
-except_list.append(...)
-
-(in_, out_, exc_) = select.select(in_list, out_list, except_list, timeout)
-
-for fd in in_:
- print "Can read", fd
-for fd in out_:
- print "Can write", fd
-for fd in exc_:
- print "Exception on", fd
-
-# Missing: setting TCP_NODELAY
-
-# @@PLEAC@@_17.4
-
-import socket
-# Set up a UDP socket
-s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-# send
-MSG = 'Hello'
-HOSTNAME = '127.0.0.1'
-PORTNO = 10000
-s.connect((HOSTNAME, PORTNO))
-if len(MSG) != s.send(MSG):
- # where to get error message "$!".
- print "cannot send to %s(%d):" % (HOSTNAME,PORTNO)
- raise SystemExit(1)
-MAXLEN = 1024
-(data,addr) = s.recvfrom(MAXLEN)
-s.close()
-print '%s(%d) said "%s"' % (addr[0],addr[1], data)
-
-# download the following standalone program
-#!/usr/bin/python
-# clockdrift - compare another system's clock with this one
-
-import socket
-import struct
-import sys
-import time
-
-if len(sys.argv)>1:
- him = sys.argv[1]
-else:
- him = '127.1'
-
-SECS_of_70_YEARS = 2208988800
-
-s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-s.connect((him,socket.getservbyname('time','udp')))
-s.send('')
-(ptime, src) = s.recvfrom(4)
-host = socket.gethostbyaddr(src[0])
-delta = struct.unpack("!L", ptime)[0] - SECS_of_70_YEARS - time.time()
-print "Clock on %s is %d seconds ahead of this one." % (host[0], delta)
-
-
-
-# @@PLEAC@@_17.5
-
-import socket
-import sys
-
-s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-try:
- s.bind(('', server_port))
-except socket.error, err:
- print "Couldn't be a udp server on port %d : %s" % (
- server_port, err)
- raise SystemExit
-
-while True:
- datagram = s.recv(MAX_TO_READ)
- if not datagram:
- break
- # do something
-s.close()
-
-# or
-import SocketServer
-
-class handler(SocketServer.DatagramRequestHandler):
- def handle(self):
- # do something (with self.request[0])
-
-s = SocketServer.UDPServer(('',10000), handler)
-s.serve_forever()
-
-# download the following standalone program
-#!/usr/bin/python
-# udpqotd - UDP message server
-
-import SocketServer
-
-PORTNO = 5151
-
-class handler(SocketServer.DatagramRequestHandler):
- def handle(self):
- newmsg = self.rfile.readline().rstrip()
- print "Client %s said ``%s''" % (self.client_address[0], newmsg)
- self.wfile.write(self.server.oldmsg)
- self.server.oldmsg = newmsg
-
-s = SocketServer.UDPServer(('',PORTNO), handler)
-print "Awaiting UDP messages on port %d" % PORTNO
-s.oldmsg = "This is the starting message."
-s.serve_forever()
-
-
-# download the following standalone program
-#!/usr/bin/python
-# udpmsg - send a message to the udpquotd server
-
-import socket
-import sys
-
-MAXLEN = 1024
-PORTNO = 5151
-TIMEOUT = 5
-
-server_host = sys.argv[1]
-msg = " ".join(sys.argv[2:])
-
-sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-sock.settimeout(TIMEOUT)
-sock.connect((server_host, PORTNO))
-sock.send(msg)
-try:
- msg = sock.recv(MAXLEN)
- ipaddr, port = sock.getpeername()
- hishost = socket.gethostbyaddr(ipaddr)
- print "Server %s responded ``%s''" % ( hishost[0], msg)
-except:
- print "recv from %s failed (timeout or no server running)." % (
- server_host )
-sock.close()
-
-
-# @@PLEAC@@_17.6
-
-import socket
-import os, os.path
-
-if os.path.exists("/tmp/mysock"):
- os.remove("/tmp/mysock")
-
-server = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
-server.bind("/tmp/mysock")
-
-client = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
-client.connect("/tmp/mysock")
-
-# @@PLEAC@@_17.7
-
-ipaddr, port = s.getpeername()
-hostname, aliaslist, ipaddrlist = socket.gethostbyaddr(ipaddr)
-ipaddr = socket.gethostbyname('www.python.org')
-# '194.109.137.226'
-hostname, aliaslist, ipaddrlist = socket.gethostbyname_ex('www.python.org')
-# ('fang.python.org', ['www.python.org'], ['194.109.137.226'])
-socket.gethostbyname_ex('www.google.org')
-# ('www.l.google.com', ['www.google.org', 'www.google.com'],
-# ['64.233.161.147','64.233.161.104', '64.233.161.99'])
-
-# @@PLEAC@@_17.8
-
-import os
-
-kernel, hostname, release, version, hardware = os.uname()
-
-import socket
-
-address = socket.gethostbyname(hostname)
-hostname = socket.gethostbyaddr(address)
-hostname, aliaslist, ipaddrlist = socket.gethostbyname_ex(hostname)
-# e.g. ('lx3.local', ['lx3', 'b70'], ['192.168.0.13', '192.168.0.70'])
-
-# @@PLEAC@@_17.9
-
-socket.shutdown(0) # Further receives are disallowed
-socket.shutdown(1) # Further sends are disallowed.
-socket.shutdown(2) # Further sends and receives are disallowed.
-
-#
-
-server.send("my request\n") # send some data
-server.shutdown(1) # send eof; no more writing
-answer = server.recv(1000) # but you can still read
-
-# @@PLEAC@@_17.10
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_17.11
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_17.12
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_17.13
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_17.14
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_17.15
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_17.16
-#------------------------------
-# Restart programm on signal SIGHUP
-# Script must be executable: chmod a+x foo.py
-
-#!/usr/bin/env python
-import os
-import sys
-import time
-import signal
-
-def phoenix(signum, frame):
- print "Restarting myself: %s %s" % (self, args)
- os.execv(self, args)
-
-self = os.path.abspath(sys.argv[0])
-args = sys.argv[:]
-signal.signal(signal.SIGHUP, phoenix)
-
-while True:
- print "work"
- time.sleep(1)
-
-#--------------------
-# Read config file on SIGHUP
-import signal
-
-config_file = "/usr/local/etc/myprog/server_conf.py"
-
-def read_config():
- execfile(config_file)
-
-signal.signal(signal.SIGHUP, read_config)
-
-# @@PLEAC@@_17.17
-
-# chroot
-
-import os
-
-try:
- os.chroot("/var/daemon")
-except Exception:
- print "Could not chroot"
- raise SystemExit(1)
-
-#-----------------------------
-# fork (Unix): Create a new process
-# if pid == 0 --> parent process
-# else child process
-
-import os
-
-pid = os.fork()
-if pid:
- print "I am the new child %s" % pid
- raise SystemExit
-else:
- print "I am still the parent"
-
-
-# ----------------------------
-# setsid (Unix): Create a new session
-import os
-id=os.setsid()
-
-# ----------------------------
-# Work until INT TERM or HUP signal is received
-import time
-import signal
-
-time_to_die = 0
-
-def sighandler(signum, frame):
- print "time to die"
- global time_to_die
- time_to_die = 1
-
-signal.signal(signal.SIGINT, sighandler)
-signal.signal(signal.SIGTERM, sighandler)
-signal.signal(signal.SIGHUP, sighandler)
-
-while not time_to_die:
- print "work"
- time.sleep(1)
-
-# @@PLEAC@@_17.18
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_18.1
-
-import socket
-try:
- host_info = socket.gethostbyname_ex(name)
- # (hostname, aliaslist, ipaddrlist)
-except socket.gaierror, err:
- print "Can't resolve hostname %s: %s" % (name, err[1])
-
-# if you only need the first one
-import socket
-try:
- address = socket.gethostbyname(name)
-except socket.gaierror, err:
- print "Can't resolve hostname %s: %s" % (name, err[1])
-
-# if you have an ip address
-try:
- host_info = socket.gethostbyaddr(address)
- # (hostname, aliaslist, ipaddrlist)
-except socket.gaierror, err:
- print "Can't resolve address %s: %s" % (address, err[1])
-
-# checking back
-import socket
-try:
- host_info = socket.gethostbyaddr(address)
-except socket.gaierror, err:
- print "Can't look up %s: %s" % (address, err[1])
- raise SystemExit(1)
-try:
- host_info = socket.gethostbyname_ex(name)
-except:
- print "Can't look up %s: %s" % (name, err[1])
- raise SystemExit(1)
-
-found = address in host_info[2]
-
-# use dnspython for more complex jobs.
-# download the following standalone program
-#!/usr/bin/python
-# mxhost - find mx exchangers for a host
-
-import sys
-
-import dns
-import dns.resolver
-
-answers = dns.resolver.query(sys.argv[1], 'MX')
-for rdata in answers:
- print rdata.preference, rdata.exchange
-
-
-
-# download the following standalone program
-#!/usr/bin/python
-# hostaddrs - canonize name and show addresses
-
-import sys
-import socket
-name = sys.argv[1]
-hent = socket.gethostbyname_ex(name)
-print "%s aliases: %s => %s" % (
- hent[0],
- len(hent[1])==0 and "None" or ",".join(hent[1]),
- ",".join(hent[2]) )
-
-
-# @@PLEAC@@_18.2
-import ftplib
-ftp = ftplib.FTP("ftp.host.com")
-ftp.login(username, password)
-ftp.cwd(directory)
-
-# get file
-outfile = open(filename, "wb")
-ftp.retrbinary("RETR %s" % filename, outfile.write)
-outfile.close()
-
-# upload file
-upfile = open(upfilename, "rb")
-ftp.storbinary("STOR %s" % upfilename, upfile)
-upfile.close()
-
-ftp.quit()
-
-
-# @@PLEAC@@_18.3
-import smtplib
-from email.MIMEText import MIMEText
-
-msg = MIMEText(body)
-msg['From'] = from_address
-msg['To'] = to_address
-msg['Subject'] = subject
-
-mailer = smtplib.SMTP()
-mailer.connect()
-mailer.sendmail(from_address, [to_address], msg.as_string())
-
-# @@PLEAC@@_18.4
-import nntplib
-
-# You can except nntplib.NNTPError to process errors
-# instead of displaying traceback.
-
-server = nntplib.NNTP("news.example.com")
-response, count, first, last, name = server.group("misc.test")
-headers = server.head(first)
-bodytext = server.body(first)
-article = server.article(first)
-
-f = file("article.txt")
-server.post(f)
-
-response, grouplist = server.list()
-for group in grouplist:
- name, last, first, flag = group
- if flag == 'y':
- pass # I can post to group
-
-# @@PLEAC@@_18.5
-import poplib
-
-pop = poplib.POP3("mail.example.com")
-pop.user(username)
-pop.pass_(password)
-count, size = pop.stat()
-for i in range(1, count+1):
- reponse, message, octets = pop.retr(i)
- # message is a list of lines
- pop.dele(i)
-
-# You must quit, otherwise mailbox remains locked.
-pop.quit()
-
-# @@PLEAC@@_18.6
-
-import telnetlib
-
-tn = telnetlib.Telnet(hostname)
-
-tn.read_until("login: ")
-tn.write(user + "\n")
-tn.read_until("Password: ")
-tn.write(password + "\n")
-# read the logon message up to the prompt
-d = tn.expect([prompt,], 10)
-tn.write("ls\n")
-files = d[2].split()
-print len(files), "files"
-tn.write("exit\n")
-print tn.read_all() # blocks till eof
-
-# @@PLEAC@@_18.7
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_18.8
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_18.9
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_19.0
-# Introduction
-#
-# There is no standard cgi/web framework in python,
-# this is reason for ranting now and then.
-#
-# See `PyWebOff <http://pyre.third-bit.com/pyweb/index.html>`__
-# which compares CherryPy, Quixote, Twisted, WebWare and Zope
-# Karrigell and print stantements.
-#
-# Then there is Nevow and Standalone ZPT.
-
-# @@PLEAC@@_19.1
-# Partial implementation of PLEAC Python section 19.1
-# Written by Seo Sanghyeon
-
-# Standard CGI module is where PERL shines. Python
-# module, cgi, is nothing but a form parser. So it is
-# not really fair to compare these two. But I hesitate
-# to introduce any non-standard module. After all,
-# which one should I choose?
-
-# I would stick to simple print statements. I believe
-# the following is close to how these tasks are usually
-# done in Python.
-
-#-----------------------------
-#!/usr/bin/env python
-# hiweb - using FieldStorage class to get at form data
-
-import cgi
-form = cgi.FieldStorage()
-
-# get a value from the form
-value = form.getvalue("PARAM_NAME")
-
-# print a standard header
-print "Content-Type: text/html"
-print
-
-# print a document
-print "<P>You typed: <TT>%s</TT></P>" % (
- cgi.escape(value),
- )
-
-#-----------------------------
-import cgi
-form = cgi.FieldStorage()
-
-who = form.getvalue("Name")
-phone = form.getvalue("Number")
-picks = form.getvalue("Choices")
-
-# if you want to assure `picks' to be a list
-picks = form.getlist("Choices")
-
-#-----------------------------
-# Not Implemented
-
-# To implement -EXPIRES => '+3d', I need to study about
-import cgi
-import datetime
-
-time_format = "%a, %d %b %Y %H:%M:%S %Z"
-print "Expires: %s" % (
- (datetime.datetime.now()
- + datetime.timedelta(+3)).strftime(time_format)
- )
-print "Date: %s" % (datetime.datetime.now().strftime(time_format))
-print "Content-Type: text/plain; charset=ISO-8859-1"
-
-#-----------------------------
-# NOTES
-
-# CGI::param() is a multi-purpose function. Here I want to
-# note which Python functions correspond to it.
-
-# PERL version 5.6.1, CGI.pm version 2.80.
-# Python version 2.2.3. cgi.py CVS revision 1.68.
-
-# Assume that `form' is the FieldStorage instance.
-
-# param() with zero argument returns parameter names as
-# a list. It is `form.keys()' in Python, following Python's
-# usual mapping interface.
-
-# param() with one argument returns the value of the named
-# parameter. It is `form.getvalue()', but there are some
-# twists:
-
-# 1) A single value is passed.
-# No problem.
-
-# 2) Multiple values are passed.
-# PERL: in LIST context, you get a list. in SCALAR context,
-# you get the first value from the list.
-# Python: `form.getvalue()' returns a list if multiple
-# values are passed, a raw value if a single value
-# is passed. With `form.getlist()', you always
-# get a list. (When a single value is passed, you
-# get a list with one element.) With `form.getfirst()',
-# you always get a value. (When multiple values are
-# passed, you get the first one.)
-
-# 3) Parameter name is given, but no value is passed.
-# PERL: returns an empty string, not undef. POD says this
-# feature is new in 2.63, and was introduced to avoid
-# "undefined value" warnings when running with the
-# -w switch.
-# Python: tricky. If you want black values to be retained,
-# you should pass a nonzero `keep_blank_values' keyword
-# argument. Default is not to retain blanks. In case
-# values are not retained, see below.
-
-# 4) Even parameter name is never mentioned.
-# PERL: returns undef.
-# Python: returns None, or whatever you passed as the second
-# argument, or `default` keyword argument. This is
-# consistent with `get()' method of the Python mapping
-# interface.
-
-# param() with more than one argument modifies the already
-# set form data. This functionality is not available in Python
-# cgi module.
-
-
-# @@PLEAC@@_19.2
-# enable() from 'cgitb' module, by default, redirects traceback
-# to the browser. It is defined as 'enable(display=True, logdir=None,
-# context=5)'.
-
-# equivalent to importing CGI::Carp::fatalsToBrowser.
-import cgitb
-cgitb.enable()
-
-# to suppress browser output, you should explicitly say so.
-import cgitb
-cgitb.enable(display=False)
-
-# equivalent to call CGI::Carp::carpout with temporary files.
-import cgitb
-cgitb.enable(logdir="/var/local/cgi-logs/")
-
-# Python exception, traceback facilities are much richer than PERL's
-# die and its friends. You can use your custom exception formatter
-# by replacing sys.excepthook. (equivalent to CGI::Carp::set_message.)
-# Default formatter is available as traceback.print_exc() in pure
-# Python. In fact, what cgitb.enable() does is replacing excepthook
-# to cgitb.handler(), which knows how to format exceptions to HTML.
-
-# If this is not enough, (usually this is enough!) Python 2.3 comes
-# with a new standard module called 'logging', which is complex, but
-# very flexible and entirely customizable.
-
-# @@PLEAC@@_19.3
-#
-# download the following standalone program
-#!/usr/bin/python
-# webwhoami - show web users id
-import getpass
-print "Content-Type: text/plain\n"
-print "Running as %s\n" % getpass.getuser()
-
-
-
-# STDOUT/ERR flushing
-#
-# In contrast to what the perl cookbook says, modpython.org tells
-# STDERR is buffered too.
-
-# @@PLEAC@@_19.4
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_19.5
-
-# use mod_python in the Apache web server.
-
-# Load the module in httpd.conf or apache.conf
-
-LoadModule python_module libexec/mod_python.so
-
-<Directory /some/directory/htdocs/test>
- AddHandler mod_python .py
- PythonHandler mptest
- PythonDebug On
-</Directory>
-
-# test.py file in /some/directory/htdocs/test
-from mod_python import apache
-
-def handler(req):
- req.write("Hello World!")
- return apache.OK
-
-# @@PLEAC@@_19.6
-
-import os
-os.system("command %s %s" % (input, " ".join(files))) # UNSAFE
-
-# python doc lib cgi-security it says
-#
-# To be on the safe side, if you must pass a string gotten from a form to a shell
-# command, you should make sure the string contains only alphanumeric characters, dashes,
-# underscores, and periods.
-import re
-cmd = "command %s %s" % (input, " ".join(files))
-if re.search(r"[^a-zA-Z0-9._\-]", cmd):
- print "rejected"
- sys.exit(1)
-os.system(cmd)
-trans = string.maketrans(string.ascii_letters+string.digits+"-_.",
-
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_19.7
-#-----------------------------
-# This uses nevow's (http://nevow.com) stan; there's no standard
-# way to generate HTML, though there are many implementations of
-# this basic idea.
-from nevow import tags as T
-print T.ol[T.li['red'], T.li['blue'], T.li['green']]
-# <ol><li>red</li><li>blue</li><li>green</li></ol>
-
-names = 'Larry Moe Curly'.split()
-print T.ul[ [T.li(type="disc")[name] for name in names] ]
-# <ul><li type="disc">Larry</li><li type="disc">Moe</li>
-# <li type="disc">Curly</li></ul>
-#-----------------------------
-print T.li["alpha"]
-# <li>alpha</li>
-
-print T.li['alpha'], T.li['omega']
-# <li>alpha</li> <li>omega</li>
-#-----------------------------
-states = {
- "Wisconsin": [ "Superior", "Lake Geneva", "Madison" ],
- "Colorado": [ "Denver", "Fort Collins", "Boulder" ],
- "Texas": [ "Plano", "Austin", "Fort Stockton" ],
- "California": [ "Sebastopol", "Santa Rosa", "Berkeley" ],
-}
-
-print "<TABLE> <CAPTION>Cities I Have Known</CAPTION>";
-print T.tr[T.th('State'), T.th('Cities')]
-for k in sorted(states.keys()):
- print T.tr[ [T.th(k)] + [T.td(city) for city in sorted(states[k])] ]
-print "</TABLE>";
-#-----------------------------
-# <TABLE> <CAPTION>Cities I Have Known</CAPTION>
-#
-# <TR><TH>State</TH> <TH>Cities</TH></TR>
-#
-# <TR><TH>California</TH> <TD>Berkeley</TD> <TD>Santa Rosa</TD>
-#
-# <TD>Sebastopol</TD> </TR>
-#
-# <TR><TH>Colorado</TH> <TD>Boulder</TD> <TD>Denver</TD>
-#
-# <TD>Fort Collins</TD> </TR>
-#
-# <TR><TH>Texas</TH> <TD>Austin</TD> <TD>Fort Stockton</TD>
-#
-# <TD>Plano</TD></TR>
-#
-# <TR><TH>Wisconsin</TH> <TD>Lake Geneva</TD> <TD>Madison</TD>
-#
-# <TD>Superior</TD></TR>
-#
-# </TABLE>
-#-----------------------------
-print T.table[
- [T.caption['Cities I have Known'],
- T.tr[T.th['State'], T.th['Cities']] ] +
- [T.tr[ [T.th(k)] + [T.td(city) for city in sorted(states[k])]]
- for k in sorted(states.keys())]]
-#-----------------------------
-# salcheck - check for salaries
-import MySQLdb
-import cgi
-
-form = cgi.FieldStorage()
-
-if 'limit' in form:
- limit = int(form['limit'].value)
-else:
- limit = ''
-
-# There's not a good way to start an HTML/XML construct with stan
-# without completing it.
-print '<html><head><title>Salary Query</title></head><body>'
-print T.h1['Search']
-print '<form>'
-print T.p['Enter minimum salary',
- T.input(type="text", name="limit", value=limit)]
-print T.input(type="submit")
-print '</form>'
-
-if limit:
- dbconn = MySQLdb.connect(db='somedb', host='server.host.dom',
- port=3306, user='username',
- passwd='password')
- cursor = dbconn.cursor()
- cursor.execute("""
- SELECT name, salary FROM employees
- WHERE salary > %s""", (limit,))
-
- print T.h1["Results"]
- print "<TABLE BORDER=1>"
-
- for row in cursor.fetchall():
- print T.tr[ [T.td(cell) for cell in row] ]
-
- print "</TABLE>\n";
- cursor.close()
- dbconn.close()
-
-print '</body></html>'
-#-----------------------------
-
-# @@PLEAC@@_19.8
-#-----------------------------
-url = "http://python.org/pypi"
-print "Location: %s\n" % url
-raise SystemExit
-#-----------------------------
-# oreobounce - set a cookie and redirect the browser
-import Cookie
-import time
-
-c = Cookie.SimpleCookie()
-c['filling'] = 'vanilla cr?me'
-now = time.time()
-future = now + 3*(60*60*24*30) # 3 months
-expire_date = time.strftime('%a %d %b %Y %H:%M:%S GMT', future)
-c['filling']['expires'] = expire_date
-c['filling']['domain'] = '.python.org'
-
-whither = "http://somewhere.python.org/nonesuch.html"
-
-# Prints the cookie header
-print 'Status: 302 Moved Temporarily'
-print c
-print 'Location:', whither
-print
-
-#-----------------------------
-#Status: 302 Moved Temporarily
-#Set-Cookie: filling=vanilla%20cr%E4me; domain=.perl.com;
-# expires=Tue, 21-Jul-1998 11:58:55 GMT
-#Location: http://somewhere.perl.com/nonesuch.html
-#-----------------------------
-# os_snipe - redirect to a Jargon File entry about current OS
-import os, re
-dir = 'http://www.wins.uva.nl/%7Emes/jargon'
-matches = [
- (r'Mac', 'm/Macintrash.html'),
- (r'Win(dows )?NT', 'e/evilandrude.html'),
- (r'Win|MSIE|WebTV', 'm/MicroslothWindows.html'),
- (r'Linux', 'l/Linux.html'),
- (r'HP-UX', 'h/HP-SUX.html'),
- (r'SunOS', 's/ScumOS.html'),
- (None, 'a/AppendixB.html'),
- ]
-
-for regex, page in matches:
- if not regex: # default
- break
- if re.search(regex, os.environ['HTTP_USER_AGENT']):
- break
-print 'Location: %s/%s\n' % (dir, page)
-#-----------------------------
-# There's no special way to print headers
-print 'Status: 204 No response'
-print
-#-----------------------------
-#Status: 204 No response
-#-----------------------------
-
-# @@PLEAC@@_19.9
-# download the following standalone program
-#!/usr/bin/python
-# dummyhttpd - start a HTTP daemon and print what the client sends
-
-import SocketServer
-# or use BaseHTTPServer, SimpleHTTPServer, CGIHTTPServer
-
-def adr_str(adr):
- return "%s:%d" % adr
-
-class RequestHandler(SocketServer.BaseRequestHandler):
- def handle(self):
- print "client access from %s" % adr_str(self.client_address)
- print self.request.recv(10000)
- self.request.send("Content-Type: text/plain\n"
- "Server: dymmyhttpd/1.0.0\n"
- "\n...\n")
- self.request.close()
-
-
-adr = ('127.0.0.1', 8001)
-print "Please contact me at <http://%s>" % adr_str(adr)
-server = SocketServer.TCPServer(adr, RequestHandler)
-server.serve_forever()
-server.server_close()
-
-
-# @@PLEAC@@_19.10
-
-import Cookie
-cookies = Cookie.SimpleCookie()
-# SimpleCookie is more secure, but does not support all characters.
-cookies["preference-name"] = "whatever you'd like"
-print cookies
-
-# download the following standalone program
-#!/usr/bin/python
-# ic_cookies - sample CGI script that uses a cookie
-
-import cgi
-import os
-import Cookie
-import datetime
-
-cookname = "favorite-ice-cream" # SimpleCookie does not support blanks
-fieldname = "flavor"
-
-cookies = Cookie.SimpleCookie(os.environ.get("HTTP_COOKIE",""))
-if cookies.has_key(cookname):
- favorite = cookies[cookname].value
-else:
- favorite = "mint"
-
-form = cgi.FieldStorage()
-if not form.has_key(fieldname):
- print "Content-Type: text/html"
- print "\n"
- print "<html><body>"
- print "<h1>Hello Ice Cream</h1>"
- print "<form>"
- print 'Please select a flavor: <input type="text" name="%s" value="%s" />' % (
- fieldname, favorite )
- print "</form>"
- print "<hr />"
- print "</body></html>"
-else:
- favorite = form[fieldname].value
- cookies[cookname] = favorite
- expire = datetime.datetime.now() + datetime.timedelta(730)
- cookies[cookname]["expires"] = expire.strftime("%a, %d %b %Y %H:00:00 GMT")
- cookies[cookname]["path"] = "/"
- print "Content-Type: text/html"
- print cookies
- print "\n"
- print "<html><body>"
- print "<h1>Hello Ice Cream</h1>"
- print "<p>You chose as your favorite flavor \"%s\"</p>" % favorite
- print "</body></html>"
-
-
-# @@PLEAC@@_19.11
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_19.12
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_19.13
-#-----------------------------
-# first open and exclusively lock the file
-import os, cgi, fcntl, cPickle
-fh = open('/tmp/formlog', 'ab')
-fcntl.flock(fh.fileno(), fcntl.LOCK_EX)
-
-form = cgi.FieldStorage()
-# This doesn't produce a readable file; we copy the environment so
-# that we save a plain dictionary (os.environ is a dictionary-like
-# object).
-cPickle.dump((form, os.environ.copy()) fh)
-fh.close()
-#-----------------------------
-import cgi, smtplib, sys
-
-form = cgi.FieldStorage()
-email = """\
-From: %S
-To: hisname@hishost.com
-Subject: mailed form submission
-
-""" % sys.argv[0]
-
-for key in form:
- values = form[key]
- if not isinstance(values, list):
- value = [values.value]
- else:
- value = [v.value for v in values]
- for item in values:
- email += '\n%s: %s' % (key, value)
-
-server = smtplib.SMTP('localhost')
-server.sendmail(sys.argv[0], ['hisname@hishost.com'], email)
-server.quit()
-#-----------------------------
-# @@INCOMPLETE@@ I don't get the point of these:
-# param("_timestamp", scalar localtime);
-# param("_environs", %ENV);
-#-----------------------------
-import fcntl, cPickle
-fh = open('/tmp/formlog', 'rb')
-fcntl.flock(fh.fileno(), fcntl.LOCK_SH)
-
-count = 0
-while True:
- try:
- form, environ = cPickle.load(fh)
- except EOFError:
- break
- if environ.get('REMOTE_HOST').endswith('perl.com'):
- continue
- if 'items requested' in form:
- count += int(form['items requested'].value)
-print 'Total orders:', count
-#-----------------------------
-
-# @@PLEAC@@_19.14
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_20.1
-#-----------------------------
-import urllib
-content = urllib.urlopen(url).read()
-
-try:
- import urllib
- content = urllib.urlopen(url).read()
-except IOError:
- print "could not get %s" % url
-
-#-----------------------------
-# download the following standalone program
-#!/usr/bin/python
-# titlebytes - find the title and size of documents
-#
-# differences to perl
-#
-# * no URI::Heuristics
-# * perl LWP supports fetching files from local system
-# * fetching a title from ftp or file doesnt work in perl either.
-
-import sys, urllib2, HTMLParser
-if len(sys.argv)<=1:
- print "usage: %s url" % sys.argv[0]
- sys.exit(1)
-raw_url = sys.argv[1]
-
-# python has no equivalent to pearls URI::Heuristics, which
-# would do some guessing like :
-#
-# perl -> http://www.perl.com
-# www.oreilly.com -> http://www.oreilly.com
-# ftp.funet.fi -> ftp://ftp.funet.fi
-# /etc/passwd -> file:/etc/passwd
-
-# simple but pedantic html parser: tpj.com breaks it.
-class html(HTMLParser.HTMLParser):
- def __init__(self):
- HTMLParser.HTMLParser.__init__(self)
- self._data = {}
- self._open_tags = []
- def handle_starttag(self, tag, attrs):
- self._open_tags.append(tag)
- def handle_endtag(self, tag):
- if len(self._open_tags)>0:
- self._open_tags.pop()
- def handle_data(self, data):
- if len(self._open_tags)>0:
- self._data[self._open_tags[-1]] = data
- def __getattr__(self,attr):
- if not self._data.has_key(attr):
- return ""
- return self._data[attr]
-
-url = raw_url
-print "%s =>\n\t" % url,
-# TODO fake user agent "Schmozilla/v9.17 Platinum"
-# TODO referer "http://wizard.yellowbrick.oz"
-# as we only do http httplib would do also
-try:
- response = urllib2.urlopen(url)
-except:
- print " %s" % sys.exc_info()[1].reason[1]
- sys.exit(1)
-# title is not in response
-data = response.read()
-parser = html()
-parser.feed(data)
-parser.close() # force processing all data
-count = len(data.split("\n"))
-bytes = len(data)
-print "%s (%d lines, %d bytes)" % (parser.title,
- count,
- bytes)
-
-# omly bytes is in response.info()
-
-
-# @@PLEAC@@_20.2
-
-# GET method
-import httplib
-conn = httplib.HTTPConnection('www.perl.com')
-conn.request('GET','/cgi-bin/cpan_mod?module=DB_File&readme=1')
-r1 = conn.getresponse()
-content = r1.read()
-
-# POST method
-import urllib
-params = urllib.urlencode({'module': 'DB_File', 'readme': 1})
-content = urllib.urlopen('http://www.perl.com', params).read()
-
-# fields must be properly escaped
-# script.cgi?field1?arg=%22this%20isn%27t%20%3CEASY%3E%22
-
-# proxies can be taken from environment, or specified
-# as the optional thrid parameter to urlopen.
-
-# @@PLEAC@@_20.3
-# download the following standalone program
-#!/usr/bin/python
-# xurl - extract unique, sorted list of links from URL
-
-from HTMLParser import HTMLParser
-import urllib
-from sets import Set as set # not needed in 2.4
-class myParser(HTMLParser):
- def __init__(self, url):
- self.baseUrl = url[:url.rfind('/')]
- HTMLParser.__init__(self)
- def reset(self):
- self.urls = set()
- HTMLParser.reset(self)
- def handle_starttag(self, tag, attrs):
- if tag == 'a':
- if attrs[0][0] == 'href':
- if attrs[0][1].find(':') == -1:
- # we need to add the base URL.
- self.urls.add(self.baseUrl + '/' + attrs[0][1])
- else:
- self.urls.add(attrs[0][1])
-url = 'http://www.perl.com/CPAN'
-p = myParser(url)
-s = urllib.urlopen(url)
-data = s.read()
-p.feed(data)
-urllist = p.urls._data.keys()
-urllist.sort()
-print '\n'.join(urllist)
-
-
-
-# @@PLEAC@@_20.4
-# Converting ASCII to HTML
-
-# download the following standalone program
-#!/usr/bin/python
-# text2html - trivial html encoding of normal text
-
-import sys
-import re
-
-# precompile regular expressions
-re_quoted = re.compile(r"(?m)^(>.*?)$")
-re_url = re.compile(r"<URL:(.*)>")
-re_http = re.compile(r"(http:\S+)")
-re_strong = re.compile(r"\*(\S+)\*")
-re_em = re.compile(r"\b_(\S+)_\b")
-
-# split paragraphs
-for para in open(sys.argv[1]).read().split("\n\n"):
- # TODO encode entities: dont encode "<>" but do "&"
- if para.startswith(" "):
- print "<pre>\n%s\n</pre>" % para
- else:
- para = re_quoted.sub(r"\1<br />", para) # quoted text
- para = re_url.sub(r'<a href="\1">\1</a>', para) # embedded URL
- para = re_http.sub(r'<a href="\1">\1</a>', para) # guessed URL
- para = re_strong.sub(r"<strong>\1</strong>",para) # this is *bold* here
- para = re_em.sub(r"<em>\1</em>",para) # this is _italic_ here
- print "<p>\n%s\n</p>" % para # add paragraph tags
-
-
-
-#-----------------------------
-import sys, re
-import htmlentitydefs
-
-def encode_entities(s):
- for k,v in htmlentitydefs.codepoint2name.items():
- if k<256: # no unicodes
- s = s.replace(chr(k),"&%s;"%v)
- return s
-
-print "<table>"
-text = sys.stdin.read()
-text = encode_entities(text)
-text = re.sub(r"(\n[ \t]+)"," . ",text) # continuation lines
-text = re.sub(r"(?m)^(\S+?:)\s*(.*?)$",
- r'<tr><th align="left">\1</th><td>\2</td></tr>',
- text);
-print text
-print "</table>"
-
-# @@PLEAC@@_20.5
-# Converting HTML to ASCII
-
-#-----------------------------
-import os
-ascii = os.popen("lynx -dump " + filename).read()
-
-#-----------------------------
-import formatter
-import htmllib
-
-w = formatter.DumbWriter()
-f = formatter.AbstractFormatter(w)
-p = htmllib.HTMLParser(f)
-p.feed(html)
-p.close()
-
-# Above is a bare minimum to use writer/formatter/parser
-# framework of Python.
-
-# Search Python Cookbook for more details, like writing
-# your own writers or formatters.
-
-# Recipe #52297 has TtyFormatter, formatting underline
-# and bold in Terminal. Recipe #135005 has a writer
-# accumulating text instead of printing.
-
-# @@PLEAC@@_20.6
-
-import re
-
-plain_text = re.sub(r"<[^>]*>","",html_text) #WRONG
-
-# using HTMLParser
-import sys, HTMLParser
-
-class html(HTMLParser.HTMLParser):
- def __init__(self):
- HTMLParser.HTMLParser.__init__(self)
- self._plaintext = ""
- self._ignore = False
- def handle_starttag(self, tag, attrs):
- if tag == "script":
- self._ignore = True
- def handle_endtag(self, tag):
- if tag == "script":
- self._ignore = False
- def handle_data(self, data):
- if len(data)>0 and not self._ignore:
- self._plaintext += data
- def get_plaintext(self):
- return self._plaintext
- def error(self,msg):
- # ignore all errors
- pass
-
-html_text = open(sys.argv[1]).read()
-
-parser = html()
-parser.feed(html_text)
-parser.close() # force processing all data
-print parser.get_plaintext()
-
-title_s = re.search(r"(?i)<title>\s*(.*?)\s*</title>", text)
-title = title_s and title_s.groups()[0] or "NO TITLE"
-
-# download the following standalone program
-#!/usr/bin/python
-# htitlebytes - get html title from URL
-#
-
-import sys, urllib2, HTMLParser
-if len(sys.argv)<=1:
- print "usage: %s url ..." % sys.argv[0]
- sys.exit(1)
-
-# simple but pedantic html parser: tpj.com breaks it.
-class html(HTMLParser.HTMLParser):
- def __init__(self):
- HTMLParser.HTMLParser.__init__(self)
- self._data = {}
- self._open_tags = []
- def handle_starttag(self, tag, attrs):
- self._open_tags.append(tag)
- def handle_endtag(self, tag):
- if len(self._open_tags)>0:
- self._open_tags.pop()
- def handle_data(self, data):
- if len(self._open_tags)>0:
- self._data[self._open_tags[-1]] = data
- def __getattr__(self,attr):
- if not self._data.has_key(attr):
- return ""
- return self._data[attr]
- def error(self,msg):
- # ignore all errors
- pass
-
-for url in sys.argv[1:]:
- print "%s: " % url,
- # TODO fake user agent "Schmozilla/v9.17 Platinum"
- # TODO referer "http://wizard.yellowbrick.oz"
- # as we only do http httplib would do also
- try:
- response = urllib2.urlopen(url)
- except:
- print " %s" % sys.exc_info()[1]
- sys.exit(1)
- # title is not in response
- parser = html()
- parser.feed(response.read())
- parser.close() # force processing all data
- print parser.title
-
-
-
-# @@PLEAC@@_20.7
-# download the following standalone program
-#!/usr/bin/python
-# churl - check urls
-
-import sys
-
-# head request
-import urllib
-def valid(url):
- try:
- conn = urllib.urlopen(url)
- return 1
- except:
- return 0
-
-# parser class as in xurl
-from HTMLParser import HTMLParser
-from sets import Set as set # not needed in 2.4
-class myParser(HTMLParser):
- def __init__(self, url):
- self.baseUrl = url[:url.rfind('/')]
- HTMLParser.__init__(self)
- def reset(self):
- self.urls = set()
- HTMLParser.reset(self)
- def handle_starttag(self, tag, attrs):
- if tag == 'a':
- if attrs[0][0] == 'href':
- if attrs[0][1].find(':') == -1:
- # we need to add the base URL.
- self.urls.add(self.baseUrl + '/' + attrs[0][1])
- else:
- self.urls.add(attrs[0][1])
-
-if len(sys.argv)<=1:
- print "usage: %s <start_url>" % (sys.argv[0])
- sys.exit(1)
-
-base_url = sys.argv[1]
-print base_url+":"
-p = myParser(base_url)
-s = urllib.urlopen(base_url)
-data = s.read()
-p.feed(data)
-for link in p.urls._data.keys():
- state = "UNKNOWN URL"
- if link.startswith("http:"):
- state = "BAD"
- if valid(link):
- state = "OK"
- print " %s: %s" % (link, state)
-
-
-
-# @@PLEAC@@_20.8
-# download the following standalone program
-#!/usr/bin/python
-# surl - sort URLs by their last modification date
-
-import urllib
-import time
-import sys
-
-Date = {}
-while 1:
- # we only read from stdin not from argv.
- ln = sys.stdin.readline()
- if not ln:
- break
- ln = ln.strip()
- try:
- u = urllib.urlopen(ln)
- date = time.mktime(u.info().getdate("date"))
- if not Date.has_key(date):
- Date[date] = []
- Date[date].append(ln)
- except:
- sys.stderr.write("%s: %s!\n" % (ln, sys.exc_info()[1]))
-
-dates = Date.keys()
-dates.sort() # python 2.4 would have sorted
-for d in dates:
- print "%s %s" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(d)),
- ", ".join(Date[d]))
-
-
-# @@PLEAC@@_20.9
-import re
-
-def template(filename, fillings):
- text = open(filename).read()
- def repl(matchobj):
- if fillings.has_key(matchobj.group(1)):
- return str(fillings[matchobj.group(1)])
- return ""
- # replace quoted words with value from fillings dictionary
- text = re.sub("%%(.+?)%%", repl, text)
- return text
-
-fields = { "username":"peter", "count":"23", "total": "1234"}
-print template("/home/httpd/templates/simple.template", fields)
-
-# download the following standalone program
-#!/usr/bin/python
-# userrep1 - report duration of user logins using SQL database
-
-import MySQLdb
-import cgi
-import re
-import sys
-
-def template(filename, fillings):
- text = open(filename).read()
- def repl(matchobj):
- if fillings.has_key(matchobj.group(1)):
- return str(fillings[matchobj.group(1)])
- return ""
- # replace quoted words with value from fillings dictionary
- text = re.sub("%%(.+?)%%", repl, text)
- return text
-
-fields = cgi.FieldStorage()
-if not fields.has_key("user"):
- print "Content-Type: text/plain\n"
- print "No username"
- sys.exit(1)
-
-def get_userdata(username):
- db = MySQLdb.connect(passwd="",db="connections", user="bert")
- db.query("select count(duration) as count,"
- +" sum(duration) as total from logins"
- +" where username='%s'" % username)
- res = db.store_result().fetch_row(maxrows=1,how=1)
- res[0]["username"] = username
- db.close()
- return res[0]
-
-print "Content-Type: text/html\n"
-
-print template("report.tpl", get_userdata(fields["user"].value))
-
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_20.10
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_20.11
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_20.12
-
-# sample data, use ``LOGFILE = open(sys.argv[1])`` in real life
-LOGFILE = [
- '127.0.0.1 - - [04/Sep/2005:20:50:31 +0200] "GET /bus HTTP/1.1" 301 303\n',
- '127.0.0.1 - - [04/Sep/2005:20:50:31 +0200] "GET /bus HTTP/1.1" 301 303 "-" "Opera/8.02 (X11; Linux i686; U; en)"\n',
- '192.168.0.1 - - [04/Sep/2005:20:50:36 +0200] "GET /bus/libjs/layersmenu-library.js HTTP/1.1" 200 6228\n',
- '192.168.0.1 - - [04/Sep/2005:20:50:36 +0200] "GET /bus/libjs/layersmenu-library.js HTTP/1.1" 200 6228 "http://localhost/bus/" "Opera/8.02 (X11; Linux i686; U; en)"\n',
- ]
-
-import re
-
-# similar too perl version.
-web_server_log_re = re.compile(r'^(\S+) (\S+) (\S+) \[([^:]+):(\d+:\d+:\d+) ([^\]]+)\] "(\S+) (.*?) (\S+)" (\S+) (\S+)$')
-
-# with group naming.
-split_re = re.compile(r'''(?x) # allow nicer formatting (but requires escaping blanks)
- ^(?P<client>\S+)\s
- (?P<identuser>\S+)\s
- (?P<authuser>\S+)\s
- \[
- (?P<date>[^:]+):
- (?P<time>[\d:]+)\s
- (?P<tz>[^\]]+)
- \]\s
- "
- (?P<method>\S+)\s
- (?P<url>.*?)\s
- (?P<protocol>\S+)
- "\s
- (?P<status>\S+)\s
- (?P<bytes>\S+)
- (?:
- \s
- "
- (?P<referrer>[^"]+)
- "\s
- "
- (?P<agent>[^"]+)
- "
- )?''')
-for line in LOGFILE:
- f = split_re.match(line)
- if f:
- print "agent = %s" % f.groupdict()['agent']
-
-# @@PLEAC@@_20.13
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-
-# @@PLEAC@@_20.14
-# @@INCOMPLETE@@
-# @@INCOMPLETE@@
-