Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

add Python3.1.2 files

  • Loading branch information...
commit b7671f7077d9bb51fd046da75139872b1f4bcec7 1 parent b154ab7
@cocoatomo authored
Showing with 31,996 additions and 0 deletions.
  1. +61 −0 Demo/README
  2. +11 −0 Demo/cgi/README
  3. +8 −0 Demo/cgi/cgi0.sh
  4. +14 −0 Demo/cgi/cgi1.py
  5. +22 −0 Demo/cgi/cgi2.py
  6. +10 −0 Demo/cgi/cgi3.py
  7. +123 −0 Demo/cgi/wiki.py
  8. +314 −0 Demo/classes/Complex.py
  9. +227 −0 Demo/classes/Dates.py
  10. +66 −0 Demo/classes/Dbm.py
  11. +12 −0 Demo/classes/README
  12. +93 −0 Demo/classes/Range.py
  13. +95 −0 Demo/classes/Rev.py
  14. +54 −0 Demo/classes/Vec.py
  15. +322 −0 Demo/classes/bitvec.py
  16. +60 −0 Demo/comparisons/README
  17. +4 −0 Demo/comparisons/patterns
  18. +47 −0 Demo/comparisons/regextest.py
  19. +45 −0 Demo/comparisons/sortingtest.py
  20. +74 −0 Demo/comparisons/systemtest.py
  21. +25 −0 Demo/curses/README
  22. +216 −0 Demo/curses/life.py
  23. +273 −0 Demo/curses/ncurses.py
  24. +94 −0 Demo/curses/rain.py
  25. +80 −0 Demo/curses/repeat.py
  26. +147 −0 Demo/curses/tclock.py
  27. +906 −0 Demo/curses/xmas.py
  28. +3 −0  Demo/distutils/test2to3/README
  29. +10 −0 Demo/distutils/test2to3/maintest.py
  30. +26 −0 Demo/distutils/test2to3/setup.py
  31. +19 −0 Demo/distutils/test2to3/test/runtests.py
  32. +8 −0 Demo/distutils/test2to3/test/test_foo.py
  33. +1 −0  Demo/distutils/test2to3/test2to3/__init__.py
  34. +5 −0 Demo/distutils/test2to3/test2to3/hello.py
  35. +57 −0 Demo/embed/Makefile
  36. +19 −0 Demo/embed/README
  37. +80 −0 Demo/embed/demo.c
  38. +23 −0 Demo/embed/importexc.c
  39. +33 −0 Demo/embed/loop.c
  40. +123 −0 Demo/imputil/knee.py
  41. +10 −0 Demo/md5test/README
  42. +1 −0  Demo/md5test/foo
  43. +123 −0 Demo/md5test/md5driver.py
  44. +141 −0 Demo/newmetaclasses/Eiffel.py
  45. +177 −0 Demo/newmetaclasses/Enum.py
  46. +6 −0 Demo/parser/FILES
  47. +31 −0 Demo/parser/README
  48. +2 −0  Demo/parser/docstring.py
  49. +190 −0 Demo/parser/example.py
  50. +1 −0  Demo/parser/simple.py
  51. +27 −0 Demo/parser/source.py
  52. +48 −0 Demo/parser/test_parser.py
  53. +100 −0 Demo/parser/texipre.dat
  54. +509 −0 Demo/parser/unparse.py
  55. +322 −0 Demo/pdist/FSProxy.py
  56. +198 −0 Demo/pdist/RCSProxy.py
  57. +121 −0 Demo/pdist/README
  58. +156 −0 Demo/pdist/client.py
  59. +142 −0 Demo/pdist/cmdfw.py
  60. +213 −0 Demo/pdist/cmptree.py
  61. +359 −0 Demo/pdist/cvslib.py
  62. +279 −0 Demo/pdist/cvslock.py
  63. +24 −0 Demo/pdist/mac.py
  64. +109 −0 Demo/pdist/makechangelog.py
  65. +33 −0 Demo/pdist/rcsbump
  66. +71 −0 Demo/pdist/rcsclient.py
  67. +334 −0 Demo/pdist/rcslib.py
  68. +8 −0 Demo/pdist/rcvs
  69. +476 −0 Demo/pdist/rcvs.py
  70. +8 −0 Demo/pdist/rrcs
  71. +158 −0 Demo/pdist/rrcs.py
  72. +33 −0 Demo/pdist/security.py
  73. +143 −0 Demo/pdist/server.py
  74. +27 −0 Demo/pdist/sumtree.py
  75. +57 −0 Demo/pysvr/Makefile
  76. +9 −0 Demo/pysvr/README
  77. +370 −0 Demo/pysvr/pysvr.c
  78. +124 −0 Demo/pysvr/pysvr.py
  79. +10 −0 Demo/rpc/MANIFEST
  80. +31 −0 Demo/rpc/README
  81. +22 −0 Demo/rpc/T.py
  82. +202 −0 Demo/rpc/mountclient.py
  83. +201 −0 Demo/rpc/nfsclient.py
  84. +98 −0 Demo/rpc/rnusersclient.py
  85. +890 −0 Demo/rpc/rpc.py
  86. +24 −0 Demo/rpc/test
  87. +200 −0 Demo/rpc/xdr.py
  88. +22 −0 Demo/scripts/README
  89. +20 −0 Demo/scripts/beer.py
  90. +198 −0 Demo/scripts/eqfix.py
  91. +49 −0 Demo/scripts/fact.py
  92. +40 −0 Demo/scripts/find-uname.py
  93. +35 −0 Demo/scripts/from.py
  94. +102 −0 Demo/scripts/lpwatch.py
  95. +21 −0 Demo/scripts/makedir.py
  96. +121 −0 Demo/scripts/markov.py
  97. +124 −0 Demo/scripts/mboxconvert.py
  98. +128 −0 Demo/scripts/morse.py
  99. +59 −0 Demo/scripts/newslist.doc
  100. +361 −0 Demo/scripts/newslist.py
  101. +33 −0 Demo/scripts/pi.py
  102. +125 −0 Demo/scripts/pp.py
  103. +27 −0 Demo/scripts/primes.py
  104. +85 −0 Demo/scripts/queens.py
  105. +42 −0 Demo/scripts/script.py
  106. +107 −0 Demo/scripts/toaiff.py
  107. +106 −0 Demo/scripts/unbirthday.py
  108. +92 −0 Demo/scripts/update.py
  109. +2 −0  Demo/scripts/wh.py
  110. +14 −0 Demo/sockets/README
  111. +15 −0 Demo/sockets/broadcast.py
  112. +31 −0 Demo/sockets/echosvr.py
  113. +58 −0 Demo/sockets/finger.py
  114. +152 −0 Demo/sockets/ftp.py
  115. +352 −0 Demo/sockets/gopher.py
  116. +80 −0 Demo/sockets/mcast.py
  117. +14 −0 Demo/sockets/radio.py
  118. +35 −0 Demo/sockets/rpython.py
  119. +52 −0 Demo/sockets/rpythond.py
  120. +109 −0 Demo/sockets/telnet.py
  121. +93 −0 Demo/sockets/throughput.py
  122. +64 −0 Demo/sockets/udpecho.py
  123. +14 −0 Demo/sockets/unicast.py
  124. +12 −0 Demo/sockets/unixclient.py
  125. +24 −0 Demo/sockets/unixserver.py
  126. +159 −0 Demo/threads/Coroutine.py
  127. +92 −0 Demo/threads/Generator.py
  128. +11 −0 Demo/threads/README
  129. +64 −0 Demo/threads/fcmp.py
  130. +154 −0 Demo/threads/find.py
  131. +105 −0 Demo/threads/squasher.py
  132. +599 −0 Demo/threads/sync.py
  133. +114 −0 Demo/threads/telnet.py
  134. +89 −0 Demo/tix/INSTALL.txt
  135. +19 −0 Demo/tix/README.txt
  136. +50 −0 Demo/tix/bitmaps/about.xpm
  137. +6 −0 Demo/tix/bitmaps/bold.xbm
  138. +6 −0 Demo/tix/bitmaps/capital.xbm
  139. +6 −0 Demo/tix/bitmaps/centerj.xbm
  140. +14 −0 Demo/tix/bitmaps/combobox.xbm
  141. +49 −0 Demo/tix/bitmaps/combobox.xpm
  142. +47 −0 Demo/tix/bitmaps/combobox.xpm.1
  143. +14 −0 Demo/tix/bitmaps/drivea.xbm
  144. +43 −0 Demo/tix/bitmaps/drivea.xpm
  145. +48 −0 Demo/tix/bitmaps/exit.xpm
  146. +14 −0 Demo/tix/bitmaps/filebox.xbm
  147. +49 −0 Demo/tix/bitmaps/filebox.xpm
  148. +6 −0 Demo/tix/bitmaps/italic.xbm
  149. +6 −0 Demo/tix/bitmaps/justify.xbm
  150. +6 −0 Demo/tix/bitmaps/leftj.xbm
  151. +14 −0 Demo/tix/bitmaps/netw.xbm
  152. +45 −0 Demo/tix/bitmaps/netw.xpm
  153. +48 −0 Demo/tix/bitmaps/optmenu.xpm
  154. +6 −0 Demo/tix/bitmaps/rightj.xbm
  155. +52 −0 Demo/tix/bitmaps/select.xpm
  156. BIN  Demo/tix/bitmaps/tix.gif
  157. +6 −0 Demo/tix/bitmaps/underline.xbm
  158. +28 −0 Demo/tix/grid.py
  159. +68 −0 Demo/tix/samples/Balloon.py
  160. +44 −0 Demo/tix/samples/BtnBox.py
  161. +196 −0 Demo/tix/samples/CmpImg.py
  162. +102 −0 Demo/tix/samples/ComboBox.py
  163. +122 −0 Demo/tix/samples/Control.py
  164. +131 −0 Demo/tix/samples/DirList.py
  165. +117 −0 Demo/tix/samples/DirTree.py
  166. +119 −0 Demo/tix/samples/NoteBook.py
  167. +68 −0 Demo/tix/samples/OptMenu.py
  168. +98 −0 Demo/tix/samples/PanedWin.py
  169. +57 −0 Demo/tix/samples/PopMenu.py
  170. +131 −0 Demo/tix/samples/SHList1.py
  171. +168 −0 Demo/tix/samples/SHList2.py
  172. +80 −0 Demo/tix/samples/Tree.py
  173. +1,002 −0 Demo/tix/tixwidgets.py
  174. +11 −0 Demo/tkinter/README
  175. +451 −0 Demo/tkinter/guido/AttrDialog.py
  176. +220 −0 Demo/tkinter/guido/ManPage.py
  177. +143 −0 Demo/tkinter/guido/MimeViewer.py
  178. +147 −0 Demo/tkinter/guido/ShellWindow.py
  179. +50 −0 Demo/tkinter/guido/brownian.py
  180. +55 −0 Demo/tkinter/guido/brownian2.py
  181. +244 −0 Demo/tkinter/guido/canvasevents.py
  182. +109 −0 Demo/tkinter/guido/dialog.py
  183. +91 −0 Demo/tkinter/guido/electrons.py
  184. +154 −0 Demo/tkinter/guido/hanoi.py
  185. +17 −0 Demo/tkinter/guido/hello.py
  186. +23 −0 Demo/tkinter/guido/imagedraw.py
  187. +12 −0 Demo/tkinter/guido/imageview.py
  188. +98 −0 Demo/tkinter/guido/kill.py
  189. +37 −0 Demo/tkinter/guido/listtree.py
  190. +283 −0 Demo/tkinter/guido/mbox.py
  191. +47 −0 Demo/tkinter/guido/newmenubardemo.py
  192. +27 −0 Demo/tkinter/guido/optionmenu.py
  193. +60 −0 Demo/tkinter/guido/paint.py
  194. +159 −0 Demo/tkinter/guido/rmt.py
  195. +637 −0 Demo/tkinter/guido/solitaire.py
  196. +633 −0 Demo/tkinter/guido/sortvisu.py
  197. +845 −0 Demo/tkinter/guido/ss1.py
  198. +128 −0 Demo/tkinter/guido/svkill.py
  199. +55 −0 Demo/tkinter/guido/switch.py
  200. +267 −0 Demo/tkinter/guido/tkman.py
  201. +30 −0 Demo/tkinter/guido/wish.py
  202. +27 −0 Demo/tkinter/matt/00-HELLO-WORLD.py
  203. +30 −0 Demo/tkinter/matt/README
  204. +35 −0 Demo/tkinter/matt/animation-simple.py
  205. +44 −0 Demo/tkinter/matt/animation-w-velocity-ctrl.py
  206. +44 −0 Demo/tkinter/matt/bind-w-mult-calls-p-type.py
  207. +28 −0 Demo/tkinter/matt/canvas-demo-simple.py
  208. +61 −0 Demo/tkinter/matt/canvas-gridding.py
  209. +62 −0 Demo/tkinter/matt/canvas-moving-or-creating.py
  210. +55 −0 Demo/tkinter/matt/canvas-moving-w-mouse.py
  211. +78 −0 Demo/tkinter/matt/canvas-mult-item-sel.py
  212. +49 −0 Demo/tkinter/matt/canvas-reading-tag-info.py
  213. +36 −0 Demo/tkinter/matt/canvas-w-widget-draw-el.py
  214. +60 −0 Demo/tkinter/matt/canvas-with-scrollbars.py
  215. +64 −0 Demo/tkinter/matt/dialog-box.py
  216. +24 −0 Demo/tkinter/matt/entry-simple.py
  217. +46 −0 Demo/tkinter/matt/entry-with-shared-variable.py
  218. +42 −0 Demo/tkinter/matt/killing-window-w-wm.py
  219. +244 −0 Demo/tkinter/matt/menu-all-types-of-entries.py
  220. +112 −0 Demo/tkinter/matt/menu-simple.py
  221. +28 −0 Demo/tkinter/matt/not-what-you-might-think-1.py
  222. +30 −0 Demo/tkinter/matt/not-what-you-might-think-2.py
  223. +41 −0 Demo/tkinter/matt/packer-and-placer-together.py
  224. +32 −0 Demo/tkinter/matt/packer-simple.py
  225. +39 −0 Demo/tkinter/matt/placer-simple.py
  226. +54 −0 Demo/tkinter/matt/pong-demo-1.py
  227. +61 −0 Demo/tkinter/matt/printing-coords-of-items.py
  228. +62 −0 Demo/tkinter/matt/radiobutton-simple.py
  229. +58 −0 Demo/tkinter/matt/rubber-band-box-demo-1.py
  230. +51 −0 Demo/tkinter/matt/rubber-line-demo-1.py
  231. +36 −0 Demo/tkinter/matt/slider-demo-1.py
  232. +28 −0 Demo/tkinter/matt/subclass-existing-widgets.py
  233. +110 −0 Demo/tkinter/matt/two-radio-groups.py
  234. +35 −0 Demo/tkinter/matt/window-creation-more.py
  235. +31 −0 Demo/tkinter/matt/window-creation-simple.py
  236. +45 −0 Demo/tkinter/matt/window-creation-w-location.py
  237. +46 −0 Demo/tkinter/ttk/combo_themes.py
  238. +93 −0 Demo/tkinter/ttk/dirbrowser.py
  239. BIN  Demo/tkinter/ttk/img/close.gif
  240. BIN  Demo/tkinter/ttk/img/close_active.gif
  241. BIN  Demo/tkinter/ttk/img/close_pressed.gif
  242. +37 −0 Demo/tkinter/ttk/listbox_scrollcmd.py
  243. +78 −0 Demo/tkinter/ttk/mac_searchentry.py
  244. +78 −0 Demo/tkinter/ttk/notebook_closebtn.py
  245. +268 −0 Demo/tkinter/ttk/plastik_theme.py
  246. +111 −0 Demo/tkinter/ttk/roundframe.py
  247. +61 −0 Demo/tkinter/ttk/theme_selector.py
  248. +107 −0 Demo/tkinter/ttk/treeview_multicolumn.py
  249. +231 −0 Demo/tkinter/ttk/ttkcalendar.py
  250. +83 −0 Demo/tkinter/ttk/widget_state.py
  251. +76 −0 Demo/turtle/about_turtle.txt
  252. +13 −0 Demo/turtle/about_turtledemo.txt
  253. +75 −0 Demo/turtle/demohelp.txt
  254. +58 −0 Demo/turtle/tdemo_I_dontlike_tiltdemo.py
  255. +162 −0 Demo/turtle/tdemo_bytedesign.py
  256. +59 −0 Demo/turtle/tdemo_chaos.py
  257. +132 −0 Demo/turtle/tdemo_clock.py
  258. +60 −0 Demo/turtle/tdemo_colormixer.py
  259. +109 −0 Demo/turtle/tdemo_forest.py
  260. +138 −0 Demo/turtle/tdemo_fractalcurves.py
  261. +119 −0 Demo/turtle/tdemo_lindenmayer_indian.py
  262. +76 −0 Demo/turtle/tdemo_minimal_hanoi.py
  263. +227 −0 Demo/turtle/tdemo_nim.py
  264. +50 −0 Demo/turtle/tdemo_paint.py
  265. +65 −0 Demo/turtle/tdemo_peace.py
  266. +181 −0 Demo/turtle/tdemo_penrose.py
  267. +113 −0 Demo/turtle/tdemo_planet_and_moon.py
  268. +90 −0 Demo/turtle/tdemo_round_dance.py
  269. +63 −0 Demo/turtle/tdemo_tree.py
  270. +65 −0 Demo/turtle/tdemo_wikipedia.py
  271. +49 −0 Demo/turtle/tdemo_yinyang.py
  272. +10 −0 Demo/turtle/turtle.cfg
  273. +291 −0 Demo/turtle/turtleDemo.py
  274. +52 −0 Demo/turtle/turtledemo_two_canvases.py
  275. +42 −0 Demo/xml/elem_count.py
  276. +46 −0 Demo/xml/roundtrip.py
  277. +97 −0 Demo/xml/rss2html.py
  278. +133 −0 Demo/zlib/minigzip.py
  279. +48 −0 Demo/zlib/zlibdemo.py
  280. +222 −0 Doc/ACKS.txt
  281. +173 −0 Doc/Makefile
  282. +150 −0 Doc/README.txt
  283. +34 −0 Doc/about.rst
  284. +58 −0 Doc/bugs.rst
  285. +25 −0 Doc/c-api/abstract.rst
  286. +71 −0 Doc/c-api/allocation.rst
  287. +577 −0 Doc/c-api/arg.rst
  288. +46 −0 Doc/c-api/bool.rst
  289. +320 −0 Doc/c-api/buffer.rst
  290. +85 −0 Doc/c-api/bytearray.rst
  291. +194 −0 Doc/c-api/bytes.rst
  292. +150 −0 Doc/c-api/capsule.rst
  293. +62 −0 Doc/c-api/cell.rst
  294. +59 −0 Doc/c-api/cobject.rst
  295. +126 −0 Doc/c-api/complex.rst
  296. +108 −0 Doc/c-api/concrete.rst
  297. +170 −0 Doc/c-api/conversion.rst
  298. +183 −0 Doc/c-api/datetime.rst
  299. +40 −0 Doc/c-api/descriptor.rst
  300. +218 −0 Doc/c-api/dict.rst
Sorry, we could not display the entire diff because too many files (12,030) changed.
View
61 Demo/README
@@ -0,0 +1,61 @@
+This directory contains various demonstrations of what you can do with
+Python. They were all written by me except where explicitly stated
+otherwise -- in general, demos contributed by others ends up in the
+../Contrib directory, unless I think they're of utmost general
+importance (like Matt Conway's Tk demos).
+
+A fair number of utilities that are useful when while developing
+Python code can be found in the ../Tools directory -- some of these
+can also be considered good examples of how to write Python code.
+
+Finally, in order to save disk space and net bandwidth, not all
+subdirectories listed here are distributed. They are listed just
+in case I change my mind about them.
+
+
+cgi CGI examples (see also ../Tools/faqwiz/.)
+
+classes Some examples of how to use classes.
+
+comparisons A set of responses to a really old language-comparison
+ challenge.
+
+curses A set of curses demos.
+
+embed An example of embedding Python in another application
+ (see also pysvr).
+
+imputil Demonstration subclasses of imputil.Importer.
+
+md5test Test program for the optional md5 module.
+
+metaclasses The code from the 1.5 metaclasses paper on the web.
+
+parser Example using the parser module.
+
+pdist Old, unfinished code messing with CVS, RCS and remote
+ files.
+
+pysvr An example of embedding Python in a threaded
+ application.
+
+rpc A set of classes for building clients and servers for
+ Sun RPC.
+
+scripts Some useful Python scripts that I put in my bin
+ directory. No optional built-in modules needed.
+
+sockets Examples for the new built-in module 'socket'.
+
+threads Demos that use the 'thread' module. (Currently these
+ only run on SGIs, but this may change in the future.)
+
+tix Demos using the Tix widget set addition to Tkinter.
+
+tkinter Demos using the Tk interface (including Matt Conway's
+ excellent set of demos).
+
+xml Some XML demos.
+
+zlib Some demos for the zlib module (see also the standard
+ library module gzip.py).
View
11 Demo/cgi/README
@@ -0,0 +1,11 @@
+CGI Examples
+------------
+
+Here are some example CGI programs. For a larger example, see
+../../Tools/faqwiz/.
+
+cgi0.sh -- A shell script to test your server is configured for CGI
+cgi1.py -- A Python script to test your server is configured for CGI
+cgi2.py -- A Python script showing how to parse a form
+cgi3.py -- A Python script for driving an arbitrary CGI application
+wiki.py -- Sample CGI application: a minimal Wiki implementation
View
8 Demo/cgi/cgi0.sh
@@ -0,0 +1,8 @@
+#! /bin/sh
+
+# If you can't get this to work, your web server isn't set up right
+
+echo Content-type: text/plain
+echo
+echo Hello world
+echo This is cgi0.sh
View
14 Demo/cgi/cgi1.py
@@ -0,0 +1,14 @@
+#!/usr/local/bin/python
+
+"""CGI test 1 - check server setup."""
+
+# Until you get this to work, your web server isn't set up right or
+# your Python isn't set up right.
+
+# If cgi0.sh works but cgi1.py doesn't, check the #! line and the file
+# permissions. The docs for the cgi.py module have debugging tips.
+
+print("Content-type: text/html")
+print()
+print("<h1>Hello world</h1>")
+print("<p>This is cgi1.py")
View
22 Demo/cgi/cgi2.py
@@ -0,0 +1,22 @@
+#!/usr/local/bin/python
+
+"""CGI test 2 - basic use of cgi module."""
+
+import cgitb; cgitb.enable()
+
+import cgi
+
+def main():
+ form = cgi.FieldStorage()
+ print("Content-type: text/html")
+ print()
+ if not form:
+ print("<h1>No Form Keys</h1>")
+ else:
+ print("<h1>Form Keys</h1>")
+ for key in form.keys():
+ value = form[key].value
+ print("<p>", cgi.escape(key), ":", cgi.escape(value))
+
+if __name__ == "__main__":
+ main()
View
10 Demo/cgi/cgi3.py
@@ -0,0 +1,10 @@
+#!/usr/local/bin/python
+
+"""CGI test 3 (persistent data)."""
+
+import cgitb; cgitb.enable()
+
+from wiki import main
+
+if __name__ == "__main__":
+ main()
View
123 Demo/cgi/wiki.py
@@ -0,0 +1,123 @@
+"""Wiki main program. Imported and run by cgi3.py."""
+
+import os, re, cgi, sys, tempfile
+escape = cgi.escape
+
+def main():
+ form = cgi.FieldStorage()
+ print("Content-type: text/html")
+ print()
+ cmd = form.getvalue("cmd", "view")
+ page = form.getvalue("page", "FrontPage")
+ wiki = WikiPage(page)
+ method = getattr(wiki, 'cmd_' + cmd, None) or wiki.cmd_view
+ method(form)
+
+class WikiPage:
+
+ homedir = tempfile.gettempdir()
+ scripturl = os.path.basename(sys.argv[0])
+
+ def __init__(self, name):
+ if not self.iswikiword(name):
+ raise ValueError("page name is not a wiki word")
+ self.name = name
+ self.load()
+
+ def cmd_view(self, form):
+ print("<h1>", escape(self.splitwikiword(self.name)), "</h1>")
+ print("<p>")
+ for line in self.data.splitlines():
+ line = line.rstrip()
+ if not line:
+ print("<p>")
+ else:
+ print(self.formatline(line))
+ print("<hr>")
+ print("<p>", self.mklink("edit", self.name, "Edit this page") + ";")
+ print(self.mklink("view", "FrontPage", "go to front page") + ".")
+
+ def formatline(self, line):
+ words = []
+ for word in re.split('(\W+)', line):
+ if self.iswikiword(word):
+ if os.path.isfile(self.mkfile(word)):
+ word = self.mklink("view", word, word)
+ else:
+ word = self.mklink("new", word, word + "*")
+ else:
+ word = escape(word)
+ words.append(word)
+ return "".join(words)
+
+ def cmd_edit(self, form, label="Change"):
+ print("<h1>", label, self.name, "</h1>")
+ print('<form method="POST" action="%s">' % self.scripturl)
+ s = '<textarea cols="70" rows="20" name="text">%s</textarea>'
+ print(s % self.data)
+ print('<input type="hidden" name="cmd" value="create">')
+ print('<input type="hidden" name="page" value="%s">' % self.name)
+ print('<br>')
+ print('<input type="submit" value="%s Page">' % label)
+ print("</form>")
+
+ def cmd_create(self, form):
+ self.data = form.getvalue("text", "").strip()
+ error = self.store()
+ if error:
+ print("<h1>I'm sorry. That didn't work</h1>")
+ print("<p>An error occurred while attempting to write the file:")
+ print("<p>", escape(error))
+ else:
+ # Use a redirect directive, to avoid "reload page" problems
+ print("<head>")
+ s = '<meta http-equiv="refresh" content="1; URL=%s">'
+ print(s % (self.scripturl + "?cmd=view&page=" + self.name))
+ print("<head>")
+ print("<h1>OK</h1>")
+ print("<p>If nothing happens, please click here:", end=' ')
+ print(self.mklink("view", self.name, self.name))
+
+ def cmd_new(self, form):
+ self.cmd_edit(form, label="Create")
+
+ def iswikiword(self, word):
+ return re.match("[A-Z][a-z]+([A-Z][a-z]*)+", word)
+
+ def splitwikiword(self, word):
+ chars = []
+ for c in word:
+ if chars and c.isupper():
+ chars.append(' ')
+ chars.append(c)
+ return "".join(chars)
+
+ def mkfile(self, name=None):
+ if name is None:
+ name = self.name
+ return os.path.join(self.homedir, name + ".txt")
+
+ def mklink(self, cmd, page, text):
+ link = self.scripturl + "?cmd=" + cmd + "&page=" + page
+ return '<a href="%s">%s</a>' % (link, text)
+
+ def load(self):
+ try:
+ f = open(self.mkfile())
+ data = f.read().strip()
+ f.close()
+ except IOError:
+ data = ""
+ self.data = data
+
+ def store(self):
+ data = self.data
+ try:
+ f = open(self.mkfile(), "w")
+ f.write(data)
+ if data and not data.endswith('\n'):
+ f.write('\n')
+ f.close()
+ return ""
+ except IOError as err:
+ return "IOError: %s" % str(err)
View
314 Demo/classes/Complex.py
@@ -0,0 +1,314 @@
+# Complex numbers
+# ---------------
+
+# [Now that Python has a complex data type built-in, this is not very
+# useful, but it's still a nice example class]
+
+# This module represents complex numbers as instances of the class Complex.
+# A Complex instance z has two data attribues, z.re (the real part) and z.im
+# (the imaginary part). In fact, z.re and z.im can have any value -- all
+# arithmetic operators work regardless of the type of z.re and z.im (as long
+# as they support numerical operations).
+#
+# The following functions exist (Complex is actually a class):
+# Complex([re [,im]) -> creates a complex number from a real and an imaginary part
+# IsComplex(z) -> true iff z is a complex number (== has .re and .im attributes)
+# ToComplex(z) -> a complex number equal to z; z itself if IsComplex(z) is true
+# if z is a tuple(re, im) it will also be converted
+# PolarToComplex([r [,phi [,fullcircle]]]) ->
+# the complex number z for which r == z.radius() and phi == z.angle(fullcircle)
+# (r and phi default to 0)
+# exp(z) -> returns the complex exponential of z. Equivalent to pow(math.e,z).
+#
+# Complex numbers have the following methods:
+# z.abs() -> absolute value of z
+# z.radius() == z.abs()
+# z.angle([fullcircle]) -> angle from positive X axis; fullcircle gives units
+# z.phi([fullcircle]) == z.angle(fullcircle)
+#
+# These standard functions and unary operators accept complex arguments:
+# abs(z)
+# -z
+# +z
+# not z
+# repr(z) == `z`
+# str(z)
+# hash(z) -> a combination of hash(z.re) and hash(z.im) such that if z.im is zero
+# the result equals hash(z.re)
+# Note that hex(z) and oct(z) are not defined.
+#
+# These conversions accept complex arguments only if their imaginary part is zero:
+# int(z)
+# float(z)
+#
+# The following operators accept two complex numbers, or one complex number
+# and one real number (int, long or float):
+# z1 + z2
+# z1 - z2
+# z1 * z2
+# z1 / z2
+# pow(z1, z2)
+# cmp(z1, z2)
+# Note that z1 % z2 and divmod(z1, z2) are not defined,
+# nor are shift and mask operations.
+#
+# The standard module math does not support complex numbers.
+# The cmath modules should be used instead.
+#
+# Idea:
+# add a class Polar(r, phi) and mixed-mode arithmetic which
+# chooses the most appropriate type for the result:
+# Complex for +,-,cmp
+# Polar for *,/,pow
+
+import math
+import sys
+
+twopi = math.pi*2.0
+halfpi = math.pi/2.0
+
+def IsComplex(obj):
+ return hasattr(obj, 're') and hasattr(obj, 'im')
+
+def ToComplex(obj):
+ if IsComplex(obj):
+ return obj
+ elif isinstance(obj, tuple):
+ return Complex(*obj)
+ else:
+ return Complex(obj)
+
+def PolarToComplex(r = 0, phi = 0, fullcircle = twopi):
+ phi = phi * (twopi / fullcircle)
+ return Complex(math.cos(phi)*r, math.sin(phi)*r)
+
+def Re(obj):
+ if IsComplex(obj):
+ return obj.re
+ return obj
+
+def Im(obj):
+ if IsComplex(obj):
+ return obj.im
+ return 0
+
+class Complex:
+
+ def __init__(self, re=0, im=0):
+ _re = 0
+ _im = 0
+ if IsComplex(re):
+ _re = re.re
+ _im = re.im
+ else:
+ _re = re
+ if IsComplex(im):
+ _re = _re - im.im
+ _im = _im + im.re
+ else:
+ _im = _im + im
+ # this class is immutable, so setting self.re directly is
+ # not possible.
+ self.__dict__['re'] = _re
+ self.__dict__['im'] = _im
+
+ def __setattr__(self, name, value):
+ raise TypeError('Complex numbers are immutable')
+
+ def __hash__(self):
+ if not self.im:
+ return hash(self.re)
+ return hash((self.re, self.im))
+
+ def __repr__(self):
+ if not self.im:
+ return 'Complex(%r)' % (self.re,)
+ else:
+ return 'Complex(%r, %r)' % (self.re, self.im)
+
+ def __str__(self):
+ if not self.im:
+ return repr(self.re)
+ else:
+ return 'Complex(%r, %r)' % (self.re, self.im)
+
+ def __neg__(self):
+ return Complex(-self.re, -self.im)
+
+ def __pos__(self):
+ return self
+
+ def __abs__(self):
+ return math.hypot(self.re, self.im)
+
+ def __int__(self):
+ if self.im:
+ raise ValueError("can't convert Complex with nonzero im to int")
+ return int(self.re)
+
+ def __float__(self):
+ if self.im:
+ raise ValueError("can't convert Complex with nonzero im to float")
+ return float(self.re)
+
+ def __cmp__(self, other):
+ other = ToComplex(other)
+ return cmp((self.re, self.im), (other.re, other.im))
+
+ def __rcmp__(self, other):
+ other = ToComplex(other)
+ return cmp(other, self)
+
+ def __bool__(self):
+ return not (self.re == self.im == 0)
+
+ abs = radius = __abs__
+
+ def angle(self, fullcircle = twopi):
+ return (fullcircle/twopi) * ((halfpi - math.atan2(self.re, self.im)) % twopi)
+
+ phi = angle
+
+ def __add__(self, other):
+ other = ToComplex(other)
+ return Complex(self.re + other.re, self.im + other.im)
+
+ __radd__ = __add__
+
+ def __sub__(self, other):
+ other = ToComplex(other)
+ return Complex(self.re - other.re, self.im - other.im)
+
+ def __rsub__(self, other):
+ other = ToComplex(other)
+ return other - self
+
+ def __mul__(self, other):
+ other = ToComplex(other)
+ return Complex(self.re*other.re - self.im*other.im,
+ self.re*other.im + self.im*other.re)
+
+ __rmul__ = __mul__
+
+ def __div__(self, other):
+ other = ToComplex(other)
+ d = float(other.re*other.re + other.im*other.im)
+ if not d: raise ZeroDivisionError('Complex division')
+ return Complex((self.re*other.re + self.im*other.im) / d,
+ (self.im*other.re - self.re*other.im) / d)
+
+ def __rdiv__(self, other):
+ other = ToComplex(other)
+ return other / self
+
+ def __pow__(self, n, z=None):
+ if z is not None:
+ raise TypeError('Complex does not support ternary pow()')
+ if IsComplex(n):
+ if n.im:
+ if self.im: raise TypeError('Complex to the Complex power')
+ else: return exp(math.log(self.re)*n)
+ n = n.re
+ r = pow(self.abs(), n)
+ phi = n*self.angle()
+ return Complex(math.cos(phi)*r, math.sin(phi)*r)
+
+ def __rpow__(self, base):
+ base = ToComplex(base)
+ return pow(base, self)
+
+def exp(z):
+ r = math.exp(z.re)
+ return Complex(math.cos(z.im)*r,math.sin(z.im)*r)
+
+
+def checkop(expr, a, b, value, fuzz = 1e-6):
+ print(' ', a, 'and', b, end=' ')
+ try:
+ result = eval(expr)
+ except:
+ result = sys.exc_info()[0]
+ print('->', result)
+ if isinstance(result, str) or isinstance(value, str):
+ ok = (result == value)
+ else:
+ ok = abs(result - value) <= fuzz
+ if not ok:
+ print('!!\t!!\t!! should be', value, 'diff', abs(result - value))
+
+def test():
+ print('test constructors')
+ constructor_test = (
+ # "expect" is an array [re,im] "got" the Complex.
+ ( (0,0), Complex() ),
+ ( (0,0), Complex() ),
+ ( (1,0), Complex(1) ),
+ ( (0,1), Complex(0,1) ),
+ ( (1,2), Complex(Complex(1,2)) ),
+ ( (1,3), Complex(Complex(1,2),1) ),
+ ( (0,0), Complex(0,Complex(0,0)) ),
+ ( (3,4), Complex(3,Complex(4)) ),
+ ( (-1,3), Complex(1,Complex(3,2)) ),
+ ( (-7,6), Complex(Complex(1,2),Complex(4,8)) ) )
+ cnt = [0,0]
+ for t in constructor_test:
+ cnt[0] += 1
+ if ((t[0][0]!=t[1].re)or(t[0][1]!=t[1].im)):
+ print(" expected", t[0], "got", t[1])
+ cnt[1] += 1
+ print(" ", cnt[1], "of", cnt[0], "tests failed")
+ # test operators
+ testsuite = {
+ 'a+b': [
+ (1, 10, 11),
+ (1, Complex(0,10), Complex(1,10)),
+ (Complex(0,10), 1, Complex(1,10)),
+ (Complex(0,10), Complex(1), Complex(1,10)),
+ (Complex(1), Complex(0,10), Complex(1,10)),
+ ],
+ 'a-b': [
+ (1, 10, -9),
+ (1, Complex(0,10), Complex(1,-10)),
+ (Complex(0,10), 1, Complex(-1,10)),
+ (Complex(0,10), Complex(1), Complex(-1,10)),
+ (Complex(1), Complex(0,10), Complex(1,-10)),
+ ],
+ 'a*b': [
+ (1, 10, 10),
+ (1, Complex(0,10), Complex(0, 10)),
+ (Complex(0,10), 1, Complex(0,10)),
+ (Complex(0,10), Complex(1), Complex(0,10)),
+ (Complex(1), Complex(0,10), Complex(0,10)),
+ ],
+ 'a/b': [
+ (1., 10, 0.1),
+ (1, Complex(0,10), Complex(0, -0.1)),
+ (Complex(0, 10), 1, Complex(0, 10)),
+ (Complex(0, 10), Complex(1), Complex(0, 10)),
+ (Complex(1), Complex(0,10), Complex(0, -0.1)),
+ ],
+ 'pow(a,b)': [
+ (1, 10, 1),
+ (1, Complex(0,10), 1),
+ (Complex(0,10), 1, Complex(0,10)),
+ (Complex(0,10), Complex(1), Complex(0,10)),
+ (Complex(1), Complex(0,10), 1),
+ (2, Complex(4,0), 16),
+ ],
+ 'cmp(a,b)': [
+ (1, 10, -1),
+ (1, Complex(0,10), 1),
+ (Complex(0,10), 1, -1),
+ (Complex(0,10), Complex(1), -1),
+ (Complex(1), Complex(0,10), 1),
+ ],
+ }
+ for expr in sorted(testsuite):
+ print(expr + ':')
+ t = (expr,)
+ for item in testsuite[expr]:
+ checkop(*(t+item))
+
+
+if __name__ == '__main__':
+ test()
View
227 Demo/classes/Dates.py
@@ -0,0 +1,227 @@
+# Class Date supplies date objects that support date arithmetic.
+#
+# Date(month,day,year) returns a Date object. An instance prints as,
+# e.g., 'Mon 16 Aug 1993'.
+#
+# Addition, subtraction, comparison operators, min, max, and sorting
+# all work as expected for date objects: int+date or date+int returns
+# the date `int' days from `date'; date+date raises an exception;
+# date-int returns the date `int' days before `date'; date2-date1 returns
+# an integer, the number of days from date1 to date2; int-date raises an
+# exception; date1 < date2 is true iff date1 occurs before date2 (&
+# similarly for other comparisons); min(date1,date2) is the earlier of
+# the two dates and max(date1,date2) the later; and date objects can be
+# used as dictionary keys.
+#
+# Date objects support one visible method, date.weekday(). This returns
+# the day of the week the date falls on, as a string.
+#
+# Date objects also have 4 read-only data attributes:
+# .month in 1..12
+# .day in 1..31
+# .year int or long int
+# .ord the ordinal of the date relative to an arbitrary staring point
+#
+# The Dates module also supplies function today(), which returns the
+# current date as a date object.
+#
+# Those entranced by calendar trivia will be disappointed, as no attempt
+# has been made to accommodate the Julian (etc) system. On the other
+# hand, at least this package knows that 2000 is a leap year but 2100
+# isn't, and works fine for years with a hundred decimal digits <wink>.
+
+# Tim Peters tim@ksr.com
+# not speaking for Kendall Square Research Corp
+
+# Adapted to Python 1.1 (where some hacks to overcome coercion are unnecessary)
+# by Guido van Rossum
+
+# Note that as of Python 2.3, a datetime module is included in the stardard
+# library.
+
+# vi:set tabsize=8:
+
+_MONTH_NAMES = [ 'January', 'February', 'March', 'April', 'May',
+ 'June', 'July', 'August', 'September', 'October',
+ 'November', 'December' ]
+
+_DAY_NAMES = [ 'Friday', 'Saturday', 'Sunday', 'Monday',
+ 'Tuesday', 'Wednesday', 'Thursday' ]
+
+_DAYS_IN_MONTH = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]
+
+_DAYS_BEFORE_MONTH = []
+dbm = 0
+for dim in _DAYS_IN_MONTH:
+ _DAYS_BEFORE_MONTH.append(dbm)
+ dbm = dbm + dim
+del dbm, dim
+
+_INT_TYPES = type(1), type(1)
+
+def _is_leap(year): # 1 if leap year, else 0
+ if year % 4 != 0: return 0
+ if year % 400 == 0: return 1
+ return year % 100 != 0
+
+def _days_in_year(year): # number of days in year
+ return 365 + _is_leap(year)
+
+def _days_before_year(year): # number of days before year
+ return year*365 + (year+3)//4 - (year+99)//100 + (year+399)//400
+
+def _days_in_month(month, year): # number of days in month of year
+ if month == 2 and _is_leap(year): return 29
+ return _DAYS_IN_MONTH[month-1]
+
+def _days_before_month(month, year): # number of days in year before month
+ return _DAYS_BEFORE_MONTH[month-1] + (month > 2 and _is_leap(year))
+
+def _date2num(date): # compute ordinal of date.month,day,year
+ return _days_before_year(date.year) + \
+ _days_before_month(date.month, date.year) + \
+ date.day
+
+_DI400Y = _days_before_year(400) # number of days in 400 years
+
+def _num2date(n): # return date with ordinal n
+ if type(n) not in _INT_TYPES:
+ raise TypeError('argument must be integer: %r' % type(n))
+
+ ans = Date(1,1,1) # arguments irrelevant; just getting a Date obj
+ del ans.ord, ans.month, ans.day, ans.year # un-initialize it
+ ans.ord = n
+
+ n400 = (n-1)//_DI400Y # # of 400-year blocks preceding
+ year, n = 400 * n400, n - _DI400Y * n400
+ more = n // 365
+ dby = _days_before_year(more)
+ if dby >= n:
+ more = more - 1
+ dby = dby - _days_in_year(more)
+ year, n = year + more, int(n - dby)
+
+ try: year = int(year) # chop to int, if it fits
+ except (ValueError, OverflowError): pass
+
+ month = min(n//29 + 1, 12)
+ dbm = _days_before_month(month, year)
+ if dbm >= n:
+ month = month - 1
+ dbm = dbm - _days_in_month(month, year)
+
+ ans.month, ans.day, ans.year = month, n-dbm, year
+ return ans
+
+def _num2day(n): # return weekday name of day with ordinal n
+ return _DAY_NAMES[ int(n % 7) ]
+
+
+class Date:
+ def __init__(self, month, day, year):
+ if not 1 <= month <= 12:
+ raise ValueError('month must be in 1..12: %r' % (month,))
+ dim = _days_in_month(month, year)
+ if not 1 <= day <= dim:
+ raise ValueError('day must be in 1..%r: %r' % (dim, day))
+ self.month, self.day, self.year = month, day, year
+ self.ord = _date2num(self)
+
+ # don't allow setting existing attributes
+ def __setattr__(self, name, value):
+ if name in self.__dict__:
+ raise AttributeError('read-only attribute ' + name)
+ self.__dict__[name] = value
+
+ def __cmp__(self, other):
+ return cmp(self.ord, other.ord)
+
+ # define a hash function so dates can be used as dictionary keys
+ def __hash__(self):
+ return hash(self.ord)
+
+ # print as, e.g., Mon 16 Aug 1993
+ def __repr__(self):
+ return '%.3s %2d %.3s %r' % (
+ self.weekday(),
+ self.day,
+ _MONTH_NAMES[self.month-1],
+ self.year)
+
+ # Python 1.1 coerces neither int+date nor date+int
+ def __add__(self, n):
+ if type(n) not in _INT_TYPES:
+ raise TypeError('can\'t add %r to date' % type(n))
+ return _num2date(self.ord + n)
+ __radd__ = __add__ # handle int+date
+
+ # Python 1.1 coerces neither date-int nor date-date
+ def __sub__(self, other):
+ if type(other) in _INT_TYPES: # date-int
+ return _num2date(self.ord - other)
+ else:
+ return self.ord - other.ord # date-date
+
+ # complain about int-date
+ def __rsub__(self, other):
+ raise TypeError('Can\'t subtract date from integer')
+
+ def weekday(self):
+ return _num2day(self.ord)
+
+def today():
+ import time
+ local = time.localtime(time.time())
+ return Date(local[1], local[2], local[0])
+
+class DateTestError(Exception):
+ pass
+
+def test(firstyear, lastyear):
+ a = Date(9,30,1913)
+ b = Date(9,30,1914)
+ if repr(a) != 'Tue 30 Sep 1913':
+ raise DateTestError('__repr__ failure')
+ if (not a < b) or a == b or a > b or b != b:
+ raise DateTestError('__cmp__ failure')
+ if a+365 != b or 365+a != b:
+ raise DateTestError('__add__ failure')
+ if b-a != 365 or b-365 != a:
+ raise DateTestError('__sub__ failure')
+ try:
+ x = 1 - a
+ raise DateTestError('int-date should have failed')
+ except TypeError:
+ pass
+ try:
+ x = a + b
+ raise DateTestError('date+date should have failed')
+ except TypeError:
+ pass
+ if a.weekday() != 'Tuesday':
+ raise DateTestError('weekday() failure')
+ if max(a,b) is not b or min(a,b) is not a:
+ raise DateTestError('min/max failure')
+ d = {a-1:b, b:a+1}
+ if d[b-366] != b or d[a+(b-a)] != Date(10,1,1913):
+ raise DateTestError('dictionary failure')
+
+ # verify date<->number conversions for first and last days for
+ # all years in firstyear .. lastyear
+
+ lord = _days_before_year(firstyear)
+ y = firstyear
+ while y <= lastyear:
+ ford = lord + 1
+ lord = ford + _days_in_year(y) - 1
+ fd, ld = Date(1,1,y), Date(12,31,y)
+ if (fd.ord,ld.ord) != (ford,lord):
+ raise DateTestError('date->num failed', y)
+ fd, ld = _num2date(ford), _num2date(lord)
+ if (1,1,y,12,31,y) != \
+ (fd.month,fd.day,fd.year,ld.month,ld.day,ld.year):
+ raise DateTestError('num->date failed', y)
+ y = y + 1
+
+if __name__ == '__main__':
+ test(1850, 2150)
View
66 Demo/classes/Dbm.py
@@ -0,0 +1,66 @@
+# A wrapper around the (optional) built-in class dbm, supporting keys
+# and values of almost any type instead of just string.
+# (Actually, this works only for keys and values that can be read back
+# correctly after being converted to a string.)
+
+
+class Dbm:
+
+ def __init__(self, filename, mode, perm):
+ import dbm.ndbm
+ self.db = dbm.ndbm.open(filename, mode, perm)
+
+ def __repr__(self):
+ s = ''
+ for key in self.keys():
+ t = repr(key) + ': ' + repr(self[key])
+ if s: t = ', ' + t
+ s = s + t
+ return '{' + s + '}'
+
+ def __len__(self):
+ return len(self.db)
+
+ def __getitem__(self, key):
+ return eval(self.db[repr(key)])
+
+ def __setitem__(self, key, value):
+ self.db[repr(key)] = repr(value)
+
+ def __delitem__(self, key):
+ del self.db[repr(key)]
+
+ def keys(self):
+ res = []
+ for key in self.db.keys():
+ res.append(eval(key))
+ return res
+
+ def has_key(self, key):
+ return repr(key) in self.db
+
+
+def test():
+ d = Dbm('@dbm', 'rw', 0o600)
+ print(d)
+ while 1:
+ try:
+ key = eval(input('key: '))
+ if key in d:
+ value = d[key]
+ print('currently:', value)
+ value = eval(input('value: '))
+ if value is None:
+ del d[key]
+ else:
+ d[key] = value
+ except KeyboardInterrupt:
+ print('')
+ print(d)
+ except EOFError:
+ print('[eof]')
+ break
+ print(d)
+
+
+test()
View
12 Demo/classes/README
@@ -0,0 +1,12 @@
+Examples of classes that implement special operators (see reference manual):
+
+Complex.py Complex numbers
+Dates.py Date manipulation package by Tim Peters
+Dbm.py Wrapper around built-in dbm, supporting arbitrary values
+Range.py Example of a generator: re-implement built-in range()
+Rev.py Yield the reverse of a sequence
+Vec.py A simple vector class
+bitvec.py A bit-vector class by Jan-Hein B\"uhrman
+
+(For straightforward examples of basic class features, such as use of
+methods and inheritance, see the library code.)
View
93 Demo/classes/Range.py
@@ -0,0 +1,93 @@
+"""Example of a generator: re-implement the built-in range function
+without actually constructing the list of values.
+
+OldStyleRange is coded in the way required to work in a 'for' loop before
+iterators were introduced into the language; using __getitem__ and __len__ .
+
+"""
+def handleargs(arglist):
+ """Take list of arguments and extract/create proper start, stop, and step
+ values and return in a tuple"""
+ try:
+ if len(arglist) == 1:
+ return 0, int(arglist[0]), 1
+ elif len(arglist) == 2:
+ return int(arglist[0]), int(arglist[1]), 1
+ elif len(arglist) == 3:
+ if arglist[2] == 0:
+ raise ValueError("step argument must not be zero")
+ return tuple(int(x) for x in arglist)
+ else:
+ raise TypeError("range() accepts 1-3 arguments, given", len(arglist))
+ except TypeError:
+ raise TypeError("range() arguments must be numbers or strings "
+ "representing numbers")
+
+def genrange(*a):
+ """Function to implement 'range' as a generator"""
+ start, stop, step = handleargs(a)
+ value = start
+ while value < stop:
+ yield value
+ value += step
+
+class oldrange:
+ """Class implementing a range object.
+ To the user the instances feel like immutable sequences
+ (and you can't concatenate or slice them)
+
+ Done using the old way (pre-iterators; __len__ and __getitem__) to have an
+ object be used by a 'for' loop.
+
+ """
+
+ def __init__(self, *a):
+ """ Initialize start, stop, and step values along with calculating the
+ nubmer of values (what __len__ will return) in the range"""
+ self.start, self.stop, self.step = handleargs(a)
+ self.len = max(0, (self.stop - self.start) // self.step)
+
+ def __repr__(self):
+ """implement repr(x) which is also used by print"""
+ return 'range(%r, %r, %r)' % (self.start, self.stop, self.step)
+
+ def __len__(self):
+ """implement len(x)"""
+ return self.len
+
+ def __getitem__(self, i):
+ """implement x[i]"""
+ if 0 <= i <= self.len:
+ return self.start + self.step * i
+ else:
+ raise IndexError('range[i] index out of range')
+
+
+def test():
+ import time, builtins
+ #Just a quick sanity check
+ correct_result = builtins.range(5, 100, 3)
+ oldrange_result = list(oldrange(5, 100, 3))
+ genrange_result = list(genrange(5, 100, 3))
+ if genrange_result != correct_result or oldrange_result != correct_result:
+ raise Exception("error in implementation:\ncorrect = %s"
+ "\nold-style = %s\ngenerator = %s" %
+ (correct_result, oldrange_result, genrange_result))
+ print("Timings for range(1000):")
+ t1 = time.time()
+ for i in oldrange(1000):
+ pass
+ t2 = time.time()
+ for i in genrange(1000):
+ pass
+ t3 = time.time()
+ for i in builtins.range(1000):
+ pass
+ t4 = time.time()
+ print(t2-t1, 'sec (old-style class)')
+ print(t3-t2, 'sec (generator)')
+ print(t4-t3, 'sec (built-in)')
+
+
+if __name__ == '__main__':
+ test()
View
95 Demo/classes/Rev.py
@@ -0,0 +1,95 @@
+'''
+A class which presents the reverse of a sequence without duplicating it.
+From: "Steven D. Majewski" <sdm7g@elvis.med.virginia.edu>
+
+It works on mutable or inmutable sequences.
+
+>>> chars = list(Rev('Hello World!'))
+>>> print ''.join(chars)
+!dlroW olleH
+
+The .forw is so you can use anonymous sequences in __init__, and still
+keep a reference the forward sequence. )
+If you give it a non-anonymous mutable sequence, the reverse sequence
+will track the updated values. ( but not reassignment! - another
+good reason to use anonymous values in creating the sequence to avoid
+confusion. Maybe it should be change to copy input sequence to break
+the connection completely ? )
+
+>>> nnn = range(3)
+>>> rnn = Rev(nnn)
+>>> for n in rnn: print n
+...
+2
+1
+0
+>>> for n in range(4, 6): nnn.append(n) # update nnn
+...
+>>> for n in rnn: print n # prints reversed updated values
+...
+5
+4
+2
+1
+0
+>>> nnn = nnn[1:-1]
+>>> nnn
+[1, 2, 4]
+>>> for n in rnn: print n # prints reversed values of old nnn
+...
+5
+4
+2
+1
+0
+
+#
+>>> WH = Rev('Hello World!')
+>>> print WH.forw, WH.back
+Hello World! !dlroW olleH
+>>> nnn = Rev(range(1, 10))
+>>> print nnn.forw
+[1, 2, 3, 4, 5, 6, 7, 8, 9]
+>>> print nnn.back
+[9, 8, 7, 6, 5, 4, 3, 2, 1]
+
+>>> rrr = Rev(nnn)
+>>> rrr
+<1, 2, 3, 4, 5, 6, 7, 8, 9>
+
+'''
+
+class Rev:
+ def __init__(self, seq):
+ self.forw = seq
+ self.back = self
+
+ def __len__(self):
+ return len(self.forw)
+
+ def __getitem__(self, j):
+ return self.forw[-(j + 1)]
+
+ def __repr__(self):
+ seq = self.forw
+ if isinstance(seq, list):
+ wrap = '[]'
+ sep = ', '
+ elif isinstance(seq, tuple):
+ wrap = '()'
+ sep = ', '
+ elif isinstance(seq, str):
+ wrap = ''
+ sep = ''
+ else:
+ wrap = '<>'
+ sep = ', '
+ outstrs = [str(item) for item in self.back]
+ return wrap[:1] + sep.join(outstrs) + wrap[-1:]
+
+def _test():
+ import doctest, Rev
+ return doctest.testmod(Rev)
+
+if __name__ == "__main__":
+ _test()
View
54 Demo/classes/Vec.py
@@ -0,0 +1,54 @@
+# A simple vector class
+
+
+def vec(*v):
+ return Vec(*v)
+
+
+class Vec:
+
+ def __init__(self, *v):
+ self.v = list(v)
+
+ def fromlist(self, v):
+ if not isinstance(v, list):
+ raise TypeError
+ self.v = v[:]
+ return self
+
+ def __repr__(self):
+ return 'vec(' + repr(self.v)[1:-1] + ')'
+
+ def __len__(self):
+ return len(self.v)
+
+ def __getitem__(self, i):
+ return self.v[i]
+
+ def __add__(self, other):
+ # Element-wise addition
+ v = list(map(lambda x, y: x+y, self, other))
+ return Vec().fromlist(v)
+
+ def __sub__(self, other):
+ # Element-wise subtraction
+ v = list(map(lambda x, y: x-y, self, other))
+ return Vec().fromlist(v)
+
+ def __mul__(self, scalar):
+ # Multiply by scalar
+ v = [x*scalar for x in self.v]
+ return Vec().fromlist(v)
+
+
+
+def test():
+ a = vec(1, 2, 3)
+ b = vec(3, 2, 1)
+ print(a)
+ print(b)
+ print(a+b)
+ print(a-b)
+ print(a*3.0)
+
+test()
View
322 Demo/classes/bitvec.py
@@ -0,0 +1,322 @@
+#
+# this is a rather strict implementation of a bit vector class
+# it is accessed the same way as an array of python-ints, except
+# the value must be 0 or 1
+#
+
+import sys; rprt = sys.stderr.write #for debugging
+
+class error(Exception):
+ pass
+
+
+def _check_value(value):
+ if type(value) != type(0) or not 0 <= value < 2:
+ raise error('bitvec() items must have int value 0 or 1')
+
+
+import math
+
+def _compute_len(param):
+ mant, l = math.frexp(float(param))
+ bitmask = 1 << l
+ if bitmask <= param:
+ raise ValueError('(param, l) = %r' % ((param, l),))
+ while l:
+ bitmask = bitmask >> 1
+ if param & bitmask:
+ break
+ l = l - 1
+ return l
+
+
+def _check_key(len, key):
+ if type(key) != type(0):
+ raise TypeError('sequence subscript not int')
+ if key < 0:
+ key = key + len
+ if not 0 <= key < len:
+ raise IndexError('list index out of range')
+ return key
+
+def _check_slice(len, i, j):
+ #the type is ok, Python already checked that
+ i, j = max(i, 0), min(len, j)
+ if i > j:
+ i = j
+ return i, j
+
+
+class BitVec:
+
+ def __init__(self, *params):
+ self._data = 0
+ self._len = 0
+ if not len(params):
+ pass
+ elif len(params) == 1:
+ param, = params
+ if type(param) == type([]):
+ value = 0
+ bit_mask = 1
+ for item in param:
+ # strict check
+ #_check_value(item)
+ if item:
+ value = value | bit_mask
+ bit_mask = bit_mask << 1
+ self._data = value
+ self._len = len(param)
+ elif type(param) == type(0):
+ if param < 0:
+ raise error('bitvec() can\'t handle negative longs')
+ self._data = param
+ self._len = _compute_len(param)
+ else:
+ raise error('bitvec() requires array or long parameter')
+ elif len(params) == 2:
+ param, length = params
+ if type(param) == type(0):
+ if param < 0:
+ raise error('can\'t handle negative longs')
+ self._data = param
+ if type(length) != type(0):
+ raise error('bitvec()\'s 2nd parameter must be int')
+ computed_length = _compute_len(param)
+ if computed_length > length:
+ print('warning: bitvec() value is longer than the length indicates, truncating value')
+ self._data = self._data & \
+ ((1 << length) - 1)
+ self._len = length
+ else:
+ raise error('bitvec() requires array or long parameter')
+ else:
+ raise error('bitvec() requires 0 -- 2 parameter(s)')
+
+
+ def append(self, item):
+ #_check_value(item)
+ #self[self._len:self._len] = [item]
+ self[self._len:self._len] = \
+ BitVec(int(not not item), 1)
+
+
+ def count(self, value):
+ #_check_value(value)
+ if value:
+ data = self._data
+ else:
+ data = (~self)._data
+ count = 0
+ while data:
+ data, count = data >> 1, count + (data & 1 != 0)
+ return count
+
+
+ def index(self, value):
+ #_check_value(value):
+ if value:
+ data = self._data
+ else:
+ data = (~self)._data
+ index = 0
+ if not data:
+ raise ValueError('list.index(x): x not in list')
+ while not (data & 1):
+ data, index = data >> 1, index + 1
+ return index
+
+
+ def insert(self, index, item):
+ #_check_value(item)
+ #self[index:index] = [item]
+ self[index:index] = BitVec(int(not not item), 1)
+
+
+ def remove(self, value):
+ del self[self.index(value)]
+
+
+ def reverse(self):
+ #ouch, this one is expensive!
+ #for i in self._len>>1: self[i], self[l-i] = self[l-i], self[i]
+ data, result = self._data, 0
+ for i in range(self._len):
+ if not data:
+ result = result << (self._len - i)
+ break
+ result, data = (result << 1) | (data & 1), data >> 1
+ self._data = result
+
+
+ def sort(self):
+ c = self.count(1)
+ self._data = ((1 << c) - 1) << (self._len - c)
+
+
+ def copy(self):
+ return BitVec(self._data, self._len)
+
+
+ def seq(self):
+ result = []
+ for i in self:
+ result.append(i)
+ return result
+
+
+ def __repr__(self):
+ ##rprt('<bitvec class instance object>.' + '__repr__()\n')
+ return 'bitvec(%r, %r)' % (self._data, self._len)
+
+ def __cmp__(self, other, *rest):
+ #rprt('%r.__cmp__%r\n' % (self, (other,) + rest))
+ if type(other) != type(self):
+ other = bitvec(other, *rest)
+ #expensive solution... recursive binary, with slicing
+ length = self._len
+ if length == 0 or other._len == 0:
+ return cmp(length, other._len)
+ if length != other._len:
+ min_length = min(length, other._len)
+ return cmp(self[:min_length], other[:min_length]) or \
+ cmp(self[min_length:], other[min_length:])
+ #the lengths are the same now...
+ if self._data == other._data:
+ return 0
+ if length == 1:
+ return cmp(self[0], other[0])
+ else:
+ length = length >> 1
+ return cmp(self[:length], other[:length]) or \
+ cmp(self[length:], other[length:])
+
+
+ def __len__(self):
+ #rprt('%r.__len__()\n' % (self,))
+ return self._len
+
+ def __getitem__(self, key):
+ #rprt('%r.__getitem__(%r)\n' % (self, key))
+ key = _check_key(self._len, key)
+ return self._data & (1 << key) != 0
+
+ def __setitem__(self, key, value):
+ #rprt('%r.__setitem__(%r, %r)\n' % (self, key, value))
+ key = _check_key(self._len, key)
+ #_check_value(value)
+ if value:
+ self._data = self._data | (1 << key)
+ else:
+ self._data = self._data & ~(1 << key)
+
+ def __delitem__(self, key):
+ #rprt('%r.__delitem__(%r)\n' % (self, key))
+ key = _check_key(self._len, key)
+ #el cheapo solution...
+ self._data = self[:key]._data | self[key+1:]._data >> key
+ self._len = self._len - 1
+
+ def __getslice__(self, i, j):
+ #rprt('%r.__getslice__(%r, %r)\n' % (self, i, j))
+ i, j = _check_slice(self._len, i, j)
+ if i >= j:
+ return BitVec(0, 0)
+ if i:
+ ndata = self._data >> i
+ else:
+ ndata = self._data
+ nlength = j - i
+ if j != self._len:
+ #we'll have to invent faster variants here
+ #e.g. mod_2exp
+ ndata = ndata & ((1 << nlength) - 1)
+ return BitVec(ndata, nlength)
+
+ def __setslice__(self, i, j, sequence, *rest):
+ #rprt('%s.__setslice__%r\n' % (self, (i, j, sequence) + rest))
+ i, j = _check_slice(self._len, i, j)
+ if type(sequence) != type(self):
+ sequence = bitvec(sequence, *rest)
+ #sequence is now of our own type
+ ls_part = self[:i]
+ ms_part = self[j:]
+ self._data = ls_part._data | \
+ ((sequence._data | \
+ (ms_part._data << sequence._len)) << ls_part._len)
+ self._len = self._len - j + i + sequence._len
+
+ def __delslice__(self, i, j):
+ #rprt('%r.__delslice__(%r, %r)\n' % (self, i, j))
+ i, j = _check_slice(self._len, i, j)
+ if i == 0 and j == self._len:
+ self._data, self._len = 0, 0
+ elif i < j:
+ self._data = self[:i]._data | (self[j:]._data >> i)
+ self._len = self._len - j + i
+
+ def __add__(self, other):
+ #rprt('%r.__add__(%r)\n' % (self, other))
+ retval = self.copy()
+ retval[self._len:self._len] = other
+ return retval
+
+ def __mul__(self, multiplier):
+ #rprt('%r.__mul__(%r)\n' % (self, multiplier))
+ if type(multiplier) != type(0):
+ raise TypeError('sequence subscript not int')
+ if multiplier <= 0:
+ return BitVec(0, 0)
+ elif multiplier == 1:
+ return self.copy()
+ #handle special cases all 0 or all 1...
+ if self._data == 0:
+ return BitVec(0, self._len * multiplier)
+ elif (~self)._data == 0:
+ return ~BitVec(0, self._len * multiplier)
+ #otherwise el cheapo again...
+ retval = BitVec(0, 0)
+ while multiplier:
+ retval, multiplier = retval + self, multiplier - 1
+ return retval
+
+ def __and__(self, otherseq, *rest):
+ #rprt('%r.__and__%r\n' % (self, (otherseq,) + rest))
+ if type(otherseq) != type(self):
+ otherseq = bitvec(otherseq, *rest)
+ #sequence is now of our own type
+ return BitVec(self._data & otherseq._data, \
+ min(self._len, otherseq._len))
+
+
+ def __xor__(self, otherseq, *rest):
+ #rprt('%r.__xor__%r\n' % (self, (otherseq,) + rest))
+ if type(otherseq) != type(self):
+ otherseq = bitvec(otherseq, *rest)
+ #sequence is now of our own type
+ return BitVec(self._data ^ otherseq._data, \
+ max(self._len, otherseq._len))
+
+
+ def __or__(self, otherseq, *rest):
+ #rprt('%r.__or__%r\n' % (self, (otherseq,) + rest))
+ if type(otherseq) != type(self):
+ otherseq = bitvec(otherseq, *rest)
+ #sequence is now of our own type
+ return BitVec(self._data | otherseq._data, \
+ max(self._len, otherseq._len))
+
+
+ def __invert__(self):
+ #rprt('%r.__invert__()\n' % (self,))
+ return BitVec(~self._data & ((1 << self._len) - 1), \
+ self._len)
+
+ def __int__(self):
+ return int(self._data)
+
+ def __float__(self):
+ return float(self._data)
+
+
+bitvec = BitVec
View
60 Demo/comparisons/README
@@ -0,0 +1,60 @@
+Subject: Re: What language would you use?
+From: Tom Christiansen <tchrist@mox.perl.com>
+Date: 6 Nov 1994 15:14:51 GMT
+Newsgroups: comp.lang.python,comp.lang.tcl,comp.lang.scheme,comp.lang.misc,comp.lang.perl
+Message-Id: <39irtb$3t4@csnews.cs.Colorado.EDU>
+References: <39b7ha$j9v@zeno.nscf.org> <39hhjp$lgn@csnews.cs.Colorado.EDU> <39hvsu$dus@mathserv.mps.ohio-state.edu>
+
+[...]
+If you're really into benchmarks, I'd love it if someone were to code up
+the following problems in tcl, python, and scheme (and whatever else you'd
+like). Separate versions (one optimized for speed, one for beauty :-) are
+ok. Post your code so we can time it on our own systems.
+
+0) Factorial Test (numerics and function calls)
+
+ (we did this already)
+
+1) Regular Expressions Test
+
+ Read a file of (extended per egrep) regular expressions (one per line),
+ and apply those to all files whose names are listed on the command line.
+ Basically, an 'egrep -f' simulator. Test it with 20 "vt100" patterns
+ against a five /etc/termcap files. Tests using more elaborate patters
+ would also be interesting. Your code should not break if given hundreds
+ of regular expressions or binary files to scan.
+
+2) Sorting Test
+
+ Sort an input file that consists of lines like this
+
+ var1=23 other=14 ditto=23 fred=2
+
+ such that each output line is sorted WRT to the number. Order
+ of output lines does not change. Resolve collisions using the
+ variable name. e.g.
+
+ fred=2 other=14 ditto=23 var1=23
+
+ Lines may be up to several kilobytes in length and contain
+ zillions of variables.
+
+3) System Test
+
+ Given a list of directories, report any bogus symbolic links contained
+ anywhere in those subtrees. A bogus symbolic link is one that cannot
+ be resolved because it points to a nonexistent or otherwise
+ unresolvable file. Do *not* use an external find executable.
+ Directories may be very very deep. Print a warning immediately if the
+ system you're running on doesn't support symbolic links.
+
+
+I'll post perl solutions if people post the others.
+
+
+--tom
+--
+Tom Christiansen Perl Consultant, Gamer, Hiker tchrist@mox.perl.com
+
+ "But Billy! A *small* allowance prepares you for a lifetime of small
+ salaries and for your Social Security payments." --Family Circus
View
4 Demo/comparisons/patterns
@@ -0,0 +1,4 @@
+^def
+^class
+^import
+^from
View
47 Demo/comparisons/regextest.py
@@ -0,0 +1,47 @@
+#! /usr/bin/env python
+
+# 1) Regular Expressions Test
+#
+# Read a file of (extended per egrep) regular expressions (one per line),
+# and apply those to all files whose names are listed on the command line.
+# Basically, an 'egrep -f' simulator. Test it with 20 "vt100" patterns
+# against a five /etc/termcap files. Tests using more elaborate patters
+# would also be interesting. Your code should not break if given hundreds
+# of regular expressions or binary files to scan.
+
+# This implementation:
+# - combines all patterns into a single one using ( ... | ... | ... )
+# - reads patterns from stdin, scans files given as command line arguments
+# - produces output in the format <file>:<lineno>:<line>
+# - is only about 2.5 times as slow as egrep (though I couldn't run
+# Tom's test -- this system, a vanilla SGI, only has /etc/terminfo)
+
+import string
+import sys
+import re
+
+def main():
+ pats = list(map(chomp, sys.stdin.readlines()))
+ bigpat = '(' + '|'.join(pats) + ')'
+ prog = re.compile(bigpat)
+
+ for file in sys.argv[1:]:
+ try:
+ fp = open(file, 'r')
+ except IOError as msg:
+ print("%s: %s" % (file, msg))
+ continue
+ lineno = 0
+ while 1:
+ line = fp.readline()
+ if not line:
+ break
+ lineno = lineno + 1
+ if prog.search(line):
+ print("%s:%s:%s" % (file, lineno, line), end=' ')
+
+def chomp(s):
+ return s.rstrip('\n')
+
+if __name__ == '__main__':
+ main()
View
45 Demo/comparisons/sortingtest.py
@@ -0,0 +1,45 @@
+#! /usr/bin/env python
+
+# 2) Sorting Test
+#
+# Sort an input file that consists of lines like this
+#
+# var1=23 other=14 ditto=23 fred=2
+#
+# such that each output line is sorted WRT to the number. Order
+# of output lines does not change. Resolve collisions using the
+# variable name. e.g.
+#
+# fred=2 other=14 ditto=23 var1=23
+#
+# Lines may be up to several kilobytes in length and contain
+# zillions of variables.
+
+# This implementation:
+# - Reads stdin, writes stdout
+# - Uses any amount of whitespace to separate fields
+# - Allows signed numbers
+# - Treats illegally formatted fields as field=0
+# - Outputs the sorted fields with exactly one space between them
+# - Handles blank input lines correctly
+
+import re
+import sys
+
+def main():
+ prog = re.compile('^(.*)=([-+]?[0-9]+)')
+ def makekey(item, prog=prog):
+ match = prog.match(item)
+ if match:
+ var, num = match.groups()
+ return int(num), var
+ else:
+ # Bad input -- pretend it's a var with value 0
+ return 0, item
+ for line in sys.stdin:
+ items = sorted(makekey(item) for item in line.split())
+ for num, var in items:
+ print("%s=%s" % (var, num), end=' ')
+ print()
+
+main()
View
74 Demo/comparisons/systemtest.py
@@ -0,0 +1,74 @@
+#! /usr/bin/env python
+
+# 3) System Test
+#
+# Given a list of directories, report any bogus symbolic links contained
+# anywhere in those subtrees. A bogus symbolic link is one that cannot
+# be resolved because it points to a nonexistent or otherwise
+# unresolvable file. Do *not* use an external find executable.
+# Directories may be very very deep. Print a warning immediately if the
+# system you're running on doesn't support symbolic links.
+
+# This implementation:
+# - takes one optional argument, using the current directory as default
+# - uses chdir to increase performance
+# - sorts the names per directory
+# - prints output lines of the form "path1 -> path2" as it goes
+# - prints error messages about directories it can't list or chdir into
+
+import os
+import sys
+from stat import *
+
+def main():
+ try:
+ # Note: can't test for presence of lstat -- it's always there
+ dummy = os.readlink
+ except AttributeError:
+ print("This system doesn't have symbolic links")
+ sys.exit(0)
+ if sys.argv[1:]:
+ prefix = sys.argv[1]
+ else:
+ prefix = ''
+ if prefix:
+ os.chdir(prefix)
+ if prefix[-1:] != '/': prefix = prefix + '/'
+ reportboguslinks(prefix)
+ else:
+ reportboguslinks('')
+
+def reportboguslinks(prefix):
+ try:
+ names = os.listdir('.')
+ except os.error as msg:
+ print("%s%s: can't list: %s" % (prefix, '.', msg))
+ return
+ names.sort()
+ for name in names:
+ if name == os.curdir or name == os.pardir:
+ continue
+ try:
+ mode = os.lstat(name)[ST_MODE]
+ except os.error:
+ print("%s%s: can't stat: %s" % (prefix, name, msg))
+ continue
+ if S_ISLNK(mode):
+ try:
+ os.stat(name)
+ except os.error:
+ print("%s%s -> %s" % \
+ (prefix, name, os.readlink(name)))
+ elif S_ISDIR(mode):
+ try:
+ os.chdir(name)
+ except os.error as msg:
+ print("%s%s: can't chdir: %s" % \
+ (prefix, name, msg))
+ continue
+ try:
+ reportboguslinks(prefix + name + '/')
+ finally:
+ os.chdir('..')
+
+main()
View
25 Demo/curses/README
@@ -0,0 +1,25 @@
+This is a collection of demos and tests for the curses module.
+
+ncurses demos
+=============
+
+These demos are converted from the C versions in the ncurses
+distribution, and were contributed by Thomas Gellekum <tg@FreeBSD.org>
+I didn't strive for a `pythonic' style, but bluntly copied the
+originals. I won't attempt to `beautify' the program anytime soon, but
+I wouldn't mind someone else making an effort in that direction, of
+course.
+
+ncurses.py -- currently only a panels demo
+rain.py -- raindrops keep falling on my desktop
+tclock.py -- ASCII clock, by Howard Jones
+xmas.py -- I'm dreaming of an ASCII christmas
+
+Please submit bugfixes and new contributions to the Python bug tracker.
+
+
+Other demos
+===========
+
+life.py -- Simple game of Life
+repeat.py -- Repeatedly execute a shell command (like watch(1))
View
216 Demo/curses/life.py
@@ -0,0 +1,216 @@
+#!/usr/bin/env python
+# life.py -- A curses-based version of Conway's Game of Life.
+# Contributed by AMK
+#
+# An empty board will be displayed, and the following commands are available:
+# E : Erase the board
+# R : Fill the board randomly
+# S : Step for a single generation
+# C : Update continuously until a key is struck
+# Q : Quit
+# Cursor keys : Move the cursor around the board
+# Space or Enter : Toggle the contents of the cursor's position
+#
+# TODO :
+# Support the mouse
+# Use colour if available
+# Make board updates faster
+#
+
+import random, string, traceback
+import curses
+
+class LifeBoard:
+ """Encapsulates a Life board
+
+ Attributes:
+ X,Y : horizontal and vertical size of the board
+ state : dictionary mapping (x,y) to 0 or 1
+
+ Methods:
+ display(update_board) -- If update_board is true, compute the
+ next generation. Then display the state
+ of the board and refresh the screen.
+ erase() -- clear the entire board
+ makeRandom() -- fill the board randomly
+ set(y,x) -- set the given cell to Live; doesn't refresh the screen
+ toggle(y,x) -- change the given cell from live to dead, or vice
+ versa, and refresh the screen display
+
+ """
+ def __init__(self, scr, char=ord('*')):
+ """Create a new LifeBoard instance.
+
+ scr -- curses screen object to use for display
+ char -- character used to render live cells (default: '*')
+ """
+ self.state = {}
+ self.scr = scr
+ Y, X = self.scr.getmaxyx()
+ self.X, self.Y = X-2, Y-2-1
+ self.char = char
+ self.scr.clear()
+
+ # Draw a border around the board
+ border_line = '+'+(self.X*'-')+'+'
+ self.scr.addstr(0, 0, border_line)
+ self.scr.addstr(self.Y+1,0, border_line)
+ for y in range(0, self.Y):
+ self.scr.addstr(1+y, 0, '|')
+ self.scr.addstr(1+y, self.X+1, '|')
+ self.scr.refresh()
+
+ def set(self, y, x):
+ """Set a cell to the live state"""
+ if x<0 or self.X<=x or y<0 or self.Y<=y:
+ raise ValueError("Coordinates out of range %i,%i"% (y,x))
+ self.state[x,y] = 1
+
+ def toggle(self, y, x):
+ """Toggle a cell's state between live and dead"""
+ if x<0 or self.X<=x or y<0 or self.Y<=y:
+ raise ValueError("Coordinates out of range %i,%i"% (y,x))
+ if (x,y) in self.state:
+ del self.state[x,y]
+ self.scr.addch(y+1, x+1, ' ')
+ else:
+ self.state[x,y] = 1
+ self.scr.addch(y+1, x+1, self.char)
+ self.scr.refresh()
+
+ def erase(self):
+ """Clear the entire board and update the board display"""
+ self.state = {}
+ self.display(update_board=False)
+
+ def display(self, update_board=True):
+ """Display the whole board, optionally computing one generation"""
+ M,N = self.X, self.Y
+ if not