History

add hg and python

cinap_lenrek committed 15 years ago

Commit 4bb9e221 parent 987265c3706 files · +1228772 −-233Browse files

Showing the changes to sys/src/cmd/python (894 of 3706 files). Show all

Unified · Split

894 files
  1. sys/src/cmd/python/Demo/README +61 −0
  2. sys/src/cmd/python/Demo/cgi/README +11 −0
  3. sys/src/cmd/python/Demo/cgi/cgi0.sh +8 −0
  4. sys/src/cmd/python/Demo/cgi/cgi1.py +14 −0
  5. sys/src/cmd/python/Demo/cgi/cgi2.py +22 −0
  6. sys/src/cmd/python/Demo/cgi/cgi3.py +10 −0
  7. sys/src/cmd/python/Demo/cgi/wiki.py +123 −0
  8. sys/src/cmd/python/Demo/classes/Complex.py +320 −0
  9. sys/src/cmd/python/Demo/classes/Dates.py +222 −0
  10. sys/src/cmd/python/Demo/classes/Dbm.py +66 −0
  11. sys/src/cmd/python/Demo/classes/README +13 −0
  12. sys/src/cmd/python/Demo/classes/Range.py +93 −0
  13. sys/src/cmd/python/Demo/classes/Rat.py +310 −0
  14. sys/src/cmd/python/Demo/classes/Rev.py +95 −0
  15. sys/src/cmd/python/Demo/classes/Vec.py +54 −0
  16. sys/src/cmd/python/Demo/classes/bitvec.py +332 −0
  17. sys/src/cmd/python/Demo/comparisons/README +60 −0
  18. sys/src/cmd/python/Demo/comparisons/patterns +4 −0
  19. sys/src/cmd/python/Demo/comparisons/regextest.py +47 −0
  20. sys/src/cmd/python/Demo/comparisons/sortingtest.py +51 −0
  21. sys/src/cmd/python/Demo/comparisons/systemtest.py +74 −0
  22. sys/src/cmd/python/Demo/curses/README +25 −0
  23. sys/src/cmd/python/Demo/curses/life.py +216 −0
  24. sys/src/cmd/python/Demo/curses/ncurses.py +273 −0
  25. sys/src/cmd/python/Demo/curses/rain.py +94 −0
  26. sys/src/cmd/python/Demo/curses/repeat.py +58 −0
  27. sys/src/cmd/python/Demo/curses/tclock.py +147 −0
  28. sys/src/cmd/python/Demo/curses/xmas.py +906 −0
  29. sys/src/cmd/python/Demo/embed/Makefile +57 −0
  30. sys/src/cmd/python/Demo/embed/README +19 −0
  31. sys/src/cmd/python/Demo/embed/demo.c +65 −0
  32. sys/src/cmd/python/Demo/embed/importexc.c +17 −0
  33. sys/src/cmd/python/Demo/embed/loop.c +33 −0
  34. sys/src/cmd/python/Demo/imputil/importers.py +248 −0
  35. sys/src/cmd/python/Demo/imputil/knee.py +126 −0
  36. sys/src/cmd/python/Demo/md5test/README +10 −0
  37. sys/src/cmd/python/Demo/md5test/foo +1 −0
  38. sys/src/cmd/python/Demo/md5test/md5driver.py +123 −0
  39. sys/src/cmd/python/Demo/metaclasses/Eiffel.py +113 −0
  40. sys/src/cmd/python/Demo/metaclasses/Enum.py +169 −0
  41. sys/src/cmd/python/Demo/metaclasses/Meta.py +118 −0
  42. sys/src/cmd/python/Demo/metaclasses/Simple.py +45 −0
  43. sys/src/cmd/python/Demo/metaclasses/Synch.py +256 −0
  44. sys/src/cmd/python/Demo/metaclasses/Trace.py +144 −0
  45. sys/src/cmd/python/Demo/metaclasses/index.html +605 −0
  46. sys/src/cmd/python/Demo/metaclasses/meta-vladimir.txt +256 −0
  47. sys/src/cmd/python/Demo/newmetaclasses/Eiffel.py +141 −0
  48. sys/src/cmd/python/Demo/newmetaclasses/Enum.py +177 −0
  49. sys/src/cmd/python/Demo/parser/FILES +6 −0
  50. sys/src/cmd/python/Demo/parser/README +31 −0
  51. sys/src/cmd/python/Demo/parser/docstring.py +2 −0
  52. sys/src/cmd/python/Demo/parser/example.py +190 −0
  53. sys/src/cmd/python/Demo/parser/simple.py +1 −0
  54. sys/src/cmd/python/Demo/parser/source.py +27 −0
  55. sys/src/cmd/python/Demo/parser/test_parser.py +48 −0
  56. sys/src/cmd/python/Demo/parser/texipre.dat +100 −0
  57. sys/src/cmd/python/Demo/parser/unparse.py +519 −0
  58. sys/src/cmd/python/Demo/pdist/FSProxy.py +322 −0
  59. sys/src/cmd/python/Demo/pdist/RCSProxy.py +198 −0
  60. sys/src/cmd/python/Demo/pdist/README +121 −0
  61. sys/src/cmd/python/Demo/pdist/client.py +157 −0
  62. sys/src/cmd/python/Demo/pdist/cmdfw.py +144 −0
  63. sys/src/cmd/python/Demo/pdist/cmptree.py +208 −0
  64. sys/src/cmd/python/Demo/pdist/cvslib.py +364 −0
  65. sys/src/cmd/python/Demo/pdist/cvslock.py +280 −0
  66. sys/src/cmd/python/Demo/pdist/mac.py +19 −0
  67. sys/src/cmd/python/Demo/pdist/makechangelog.py +109 −0
  68. sys/src/cmd/python/Demo/pdist/rcsbump +33 −0
  69. sys/src/cmd/python/Demo/pdist/rcsclient.py +71 −0
  70. sys/src/cmd/python/Demo/pdist/rcslib.py +334 −0
  71. sys/src/cmd/python/Demo/pdist/rcvs +8 −0
  72. sys/src/cmd/python/Demo/pdist/rcvs.py +477 −0
  73. sys/src/cmd/python/Demo/pdist/rrcs +8 −0
  74. sys/src/cmd/python/Demo/pdist/rrcs.py +160 −0
  75. sys/src/cmd/python/Demo/pdist/security.py +33 −0
  76. sys/src/cmd/python/Demo/pdist/server.py +145 −0
  77. sys/src/cmd/python/Demo/pdist/sumtree.py +24 −0
  78. sys/src/cmd/python/Demo/pysvr/Makefile +57 −0
  79. sys/src/cmd/python/Demo/pysvr/README +9 −0
  80. sys/src/cmd/python/Demo/pysvr/pysvr.c +370 −0
  81. sys/src/cmd/python/Demo/pysvr/pysvr.py +124 −0
  82. sys/src/cmd/python/Demo/rpc/MANIFEST +10 −0
  83. sys/src/cmd/python/Demo/rpc/README +31 −0
  84. sys/src/cmd/python/Demo/rpc/T.py +22 −0
  85. sys/src/cmd/python/Demo/rpc/mountclient.py +202 −0
  86. sys/src/cmd/python/Demo/rpc/nfsclient.py +201 −0
  87. sys/src/cmd/python/Demo/rpc/rnusersclient.py +98 −0
  88. sys/src/cmd/python/Demo/rpc/rpc.py +893 −0
  89. sys/src/cmd/python/Demo/rpc/test +24 −0
  90. sys/src/cmd/python/Demo/rpc/xdr.py +200 −0
  91. sys/src/cmd/python/Demo/scripts/README +23 −0
  92. sys/src/cmd/python/Demo/scripts/beer.py +14 −0
  93. sys/src/cmd/python/Demo/scripts/eqfix.py +198 −0
  94. sys/src/cmd/python/Demo/scripts/fact.py +49 −0
  95. sys/src/cmd/python/Demo/scripts/find-uname.py +40 −0
  96. sys/src/cmd/python/Demo/scripts/from.py +35 −0
  97. sys/src/cmd/python/Demo/scripts/ftpstats.py +145 −0
  98. sys/src/cmd/python/Demo/scripts/lpwatch.py +110 −0
  99. sys/src/cmd/python/Demo/scripts/makedir.py +21 −0
  100. sys/src/cmd/python/Demo/scripts/markov.py +117 −0
  101. sys/src/cmd/python/Demo/scripts/mboxconvert.py +124 −0
  102. sys/src/cmd/python/Demo/scripts/mkrcs.py +61 −0
  103. sys/src/cmd/python/Demo/scripts/morse.py +149 −0
  104. sys/src/cmd/python/Demo/scripts/newslist.doc +59 −0
  105. sys/src/cmd/python/Demo/scripts/newslist.py +366 −0
  106. sys/src/cmd/python/Demo/scripts/pi.py +34 −0
  107. sys/src/cmd/python/Demo/scripts/pp.py +130 −0
  108. sys/src/cmd/python/Demo/scripts/primes.py +27 −0
  109. sys/src/cmd/python/Demo/scripts/queens.py +85 −0
  110. sys/src/cmd/python/Demo/scripts/script.py +33 −0
  111. sys/src/cmd/python/Demo/scripts/unbirthday.py +107 −0
  112. sys/src/cmd/python/Demo/scripts/update.py +92 −0
  113. sys/src/cmd/python/Demo/scripts/wh.py +2 −0
  114. sys/src/cmd/python/Demo/sockets/README +21 −0
  115. sys/src/cmd/python/Demo/sockets/broadcast.py +15 −0
  116. sys/src/cmd/python/Demo/sockets/echosvr.py +31 −0
  117. sys/src/cmd/python/Demo/sockets/finger.py +58 −0
  118. sys/src/cmd/python/Demo/sockets/ftp.py +146 −0
  119. sys/src/cmd/python/Demo/sockets/gopher.py +347 −0
  120. sys/src/cmd/python/Demo/sockets/mcast.py +93 −0
  121. sys/src/cmd/python/Demo/sockets/radio.py +14 −0
  122. sys/src/cmd/python/Demo/sockets/rpython.py +35 −0
  123. sys/src/cmd/python/Demo/sockets/rpythond.py +52 −0
  124. sys/src/cmd/python/Demo/sockets/telnet.py +109 −0
  125. sys/src/cmd/python/Demo/sockets/throughput.py +93 −0
  126. sys/src/cmd/python/Demo/sockets/udpecho.py +63 −0
  127. sys/src/cmd/python/Demo/sockets/unicast.py +14 −0
  128. sys/src/cmd/python/Demo/sockets/unixclient.py +12 −0
  129. sys/src/cmd/python/Demo/sockets/unixserver.py +24 −0
  130. sys/src/cmd/python/Demo/threads/Coroutine.py +159 −0
  131. sys/src/cmd/python/Demo/threads/Generator.py +84 −0
  132. sys/src/cmd/python/Demo/threads/README +13 −0
  133. sys/src/cmd/python/Demo/threads/fcmp.py +64 −0
  134. sys/src/cmd/python/Demo/threads/find.py +155 −0
  135. sys/src/cmd/python/Demo/threads/squasher.py +105 −0
  136. sys/src/cmd/python/Demo/threads/sync.py +603 −0
  137. sys/src/cmd/python/Demo/threads/telnet.py +114 −0
  138. sys/src/cmd/python/Demo/tix/INSTALL.txt +89 −0
  139. sys/src/cmd/python/Demo/tix/README.txt +19 −0
  140. sys/src/cmd/python/Demo/tix/bitmaps/about.xpm +50 −0
  141. sys/src/cmd/python/Demo/tix/bitmaps/bold.xbm +6 −0
  142. sys/src/cmd/python/Demo/tix/bitmaps/capital.xbm +6 −0
  143. sys/src/cmd/python/Demo/tix/bitmaps/centerj.xbm +6 −0
  144. sys/src/cmd/python/Demo/tix/bitmaps/combobox.xbm +14 −0
  145. sys/src/cmd/python/Demo/tix/bitmaps/combobox.xpm +49 −0
  146. sys/src/cmd/python/Demo/tix/bitmaps/drivea.xbm +14 −0
  147. sys/src/cmd/python/Demo/tix/bitmaps/drivea.xpm +43 −0
  148. sys/src/cmd/python/Demo/tix/bitmaps/exit.xpm +48 −0
  149. sys/src/cmd/python/Demo/tix/bitmaps/filebox.xbm +14 −0
  150. sys/src/cmd/python/Demo/tix/bitmaps/filebox.xpm +49 −0
  151. sys/src/cmd/python/Demo/tix/bitmaps/italic.xbm +6 −0
  152. sys/src/cmd/python/Demo/tix/bitmaps/justify.xbm +6 −0
  153. sys/src/cmd/python/Demo/tix/bitmaps/leftj.xbm +6 −0
  154. sys/src/cmd/python/Demo/tix/bitmaps/netw.xbm +14 −0
  155. sys/src/cmd/python/Demo/tix/bitmaps/netw.xpm +45 −0
  156. sys/src/cmd/python/Demo/tix/bitmaps/optmenu.xpm +48 −0
  157. sys/src/cmd/python/Demo/tix/bitmaps/rightj.xbm +6 −0
  158. sys/src/cmd/python/Demo/tix/bitmaps/select.xpm +52 −0
  159. sys/src/cmd/python/Demo/tix/bitmaps/tix.gif +0 −0
  160. sys/src/cmd/python/Demo/tix/bitmaps/underline.xbm +6 −0
  161. sys/src/cmd/python/Demo/tix/grid.py +28 −0
  162. sys/src/cmd/python/Demo/tix/samples/Balloon.py +68 −0
  163. sys/src/cmd/python/Demo/tix/samples/BtnBox.py +44 −0
  164. sys/src/cmd/python/Demo/tix/samples/CmpImg.py +196 −0
  165. sys/src/cmd/python/Demo/tix/samples/ComboBox.py +102 −0
  166. sys/src/cmd/python/Demo/tix/samples/Control.py +122 −0
  167. sys/src/cmd/python/Demo/tix/samples/DirList.py +131 −0
  168. sys/src/cmd/python/Demo/tix/samples/DirTree.py +117 −0
  169. sys/src/cmd/python/Demo/tix/samples/NoteBook.py +119 −0
  170. sys/src/cmd/python/Demo/tix/samples/OptMenu.py +68 −0
  171. sys/src/cmd/python/Demo/tix/samples/PanedWin.py +98 −0
  172. sys/src/cmd/python/Demo/tix/samples/PopMenu.py +57 −0
  173. sys/src/cmd/python/Demo/tix/samples/SHList1.py +131 −0
  174. sys/src/cmd/python/Demo/tix/samples/SHList2.py +168 −0
  175. sys/src/cmd/python/Demo/tix/samples/Tree.py +80 −0
  176. sys/src/cmd/python/Demo/tix/tixwidgets.py +1003 −0
  177. sys/src/cmd/python/Demo/tkinter/README +10 −0
  178. sys/src/cmd/python/Demo/tkinter/guido/AttrDialog.py +452 −0
  179. sys/src/cmd/python/Demo/tkinter/guido/ManPage.py +220 −0
  180. sys/src/cmd/python/Demo/tkinter/guido/MimeViewer.py +143 −0
  181. sys/src/cmd/python/Demo/tkinter/guido/ShellWindow.py +151 −0
  182. sys/src/cmd/python/Demo/tkinter/guido/brownian.py +50 −0
  183. sys/src/cmd/python/Demo/tkinter/guido/canvasevents.py +244 −0
  184. sys/src/cmd/python/Demo/tkinter/guido/dialog.py +109 −0
  185. sys/src/cmd/python/Demo/tkinter/guido/electrons.py +91 −0
  186. sys/src/cmd/python/Demo/tkinter/guido/hanoi.py +154 −0
  187. sys/src/cmd/python/Demo/tkinter/guido/hello.py +17 −0
  188. sys/src/cmd/python/Demo/tkinter/guido/imagedraw.py +23 −0
  189. sys/src/cmd/python/Demo/tkinter/guido/imageview.py +12 −0
  190. sys/src/cmd/python/Demo/tkinter/guido/kill.py +98 −0
  191. sys/src/cmd/python/Demo/tkinter/guido/listtree.py +37 −0
  192. sys/src/cmd/python/Demo/tkinter/guido/mbox.py +285 −0
  193. sys/src/cmd/python/Demo/tkinter/guido/newmenubardemo.py +47 −0
  194. sys/src/cmd/python/Demo/tkinter/guido/optionmenu.py +27 −0
  195. sys/src/cmd/python/Demo/tkinter/guido/paint.py +60 −0
  196. sys/src/cmd/python/Demo/tkinter/guido/rmt.py +159 −0
  197. sys/src/cmd/python/Demo/tkinter/guido/solitaire.py +637 −0
  198. sys/src/cmd/python/Demo/tkinter/guido/sortvisu.py +634 −0
  199. sys/src/cmd/python/Demo/tkinter/guido/ss1.py +845 −0
  200. sys/src/cmd/python/Demo/tkinter/guido/svkill.py +128 −0
  201. sys/src/cmd/python/Demo/tkinter/guido/switch.py +55 −0
  202. sys/src/cmd/python/Demo/tkinter/guido/tkman.py +267 −0
  203. sys/src/cmd/python/Demo/tkinter/guido/wish.py +27 −0
  204. sys/src/cmd/python/Demo/tkinter/matt/00-HELLO-WORLD.py +27 −0
  205. sys/src/cmd/python/Demo/tkinter/matt/README +30 −0
  206. sys/src/cmd/python/Demo/tkinter/matt/animation-simple.py +35 −0
  207. sys/src/cmd/python/Demo/tkinter/matt/animation-w-velocity-ctrl.py +44 −0
  208. sys/src/cmd/python/Demo/tkinter/matt/bind-w-mult-calls-p-type.py +44 −0
  209. sys/src/cmd/python/Demo/tkinter/matt/canvas-demo-simple.py +28 −0
  210. sys/src/cmd/python/Demo/tkinter/matt/canvas-gridding.py +61 −0
  211. sys/src/cmd/python/Demo/tkinter/matt/canvas-moving-or-creating.py +62 −0
  212. sys/src/cmd/python/Demo/tkinter/matt/canvas-moving-w-mouse.py +55 −0
  213. sys/src/cmd/python/Demo/tkinter/matt/canvas-mult-item-sel.py +78 −0
  214. sys/src/cmd/python/Demo/tkinter/matt/canvas-reading-tag-info.py +49 −0
  215. sys/src/cmd/python/Demo/tkinter/matt/canvas-w-widget-draw-el.py +36 −0
  216. sys/src/cmd/python/Demo/tkinter/matt/canvas-with-scrollbars.py +60 −0
  217. sys/src/cmd/python/Demo/tkinter/matt/dialog-box.py +64 −0
  218. sys/src/cmd/python/Demo/tkinter/matt/entry-simple.py +24 −0
  219. sys/src/cmd/python/Demo/tkinter/matt/entry-with-shared-variable.py +46 −0
  220. sys/src/cmd/python/Demo/tkinter/matt/killing-window-w-wm.py +42 −0
  221. sys/src/cmd/python/Demo/tkinter/matt/menu-all-types-of-entries.py +244 −0
  222. sys/src/cmd/python/Demo/tkinter/matt/menu-simple.py +112 −0
  223. sys/src/cmd/python/Demo/tkinter/matt/not-what-you-might-think-1.py +28 −0
  224. sys/src/cmd/python/Demo/tkinter/matt/not-what-you-might-think-2.py +30 −0
  225. sys/src/cmd/python/Demo/tkinter/matt/packer-and-placer-together.py +41 −0
  226. sys/src/cmd/python/Demo/tkinter/matt/packer-simple.py +32 −0
  227. sys/src/cmd/python/Demo/tkinter/matt/placer-simple.py +39 −0
  228. sys/src/cmd/python/Demo/tkinter/matt/pong-demo-1.py +54 −0
  229. sys/src/cmd/python/Demo/tkinter/matt/printing-coords-of-items.py +61 −0
  230. sys/src/cmd/python/Demo/tkinter/matt/radiobutton-simple.py +62 −0
  231. sys/src/cmd/python/Demo/tkinter/matt/rubber-band-box-demo-1.py +58 −0
  232. sys/src/cmd/python/Demo/tkinter/matt/rubber-line-demo-1.py +51 −0
  233. sys/src/cmd/python/Demo/tkinter/matt/slider-demo-1.py +36 −0
  234. sys/src/cmd/python/Demo/tkinter/matt/subclass-existing-widgets.py +28 −0
  235. sys/src/cmd/python/Demo/tkinter/matt/two-radio-groups.py +110 −0
  236. sys/src/cmd/python/Demo/tkinter/matt/window-creation-more.py +35 −0
  237. sys/src/cmd/python/Demo/tkinter/matt/window-creation-simple.py +31 −0
  238. sys/src/cmd/python/Demo/tkinter/matt/window-creation-w-location.py +45 −0
  239. sys/src/cmd/python/Demo/xml/elem_count.py +36 −0
  240. sys/src/cmd/python/Demo/xml/roundtrip.py +45 −0
  241. sys/src/cmd/python/Demo/xml/rss2html.py +91 −0
  242. sys/src/cmd/python/Demo/zlib/minigzip.py +133 −0
  243. sys/src/cmd/python/Demo/zlib/zlibdemo.py +48 −0
  244. sys/src/cmd/python/Demo/zlib/zlibdemo.py.gz +0 −0
  245. sys/src/cmd/python/Doc/ACKS +202 −0
  246. sys/src/cmd/python/Doc/Makefile +736 −0
  247. sys/src/cmd/python/Doc/Makefile.deps +386 −0
  248. sys/src/cmd/python/Doc/README +246 −0
  249. sys/src/cmd/python/Doc/TODO +74 −0
  250. sys/src/cmd/python/Doc/api/abstract.tex +1057 −0
  251. sys/src/cmd/python/Doc/api/api.tex +60 −0
  252. sys/src/cmd/python/Doc/api/concrete.tex +3203 −0
  253. sys/src/cmd/python/Doc/api/exceptions.tex +442 −0
  254. sys/src/cmd/python/Doc/api/init.tex +884 −0
  255. sys/src/cmd/python/Doc/api/intro.tex +627 −0
  256. sys/src/cmd/python/Doc/api/memory.tex +204 −0
  257. sys/src/cmd/python/Doc/api/newtypes.tex +1780 −0
  258. sys/src/cmd/python/Doc/api/refcounting.tex +69 −0
  259. sys/src/cmd/python/Doc/api/refcounts.dat +1756 −0
  260. sys/src/cmd/python/Doc/api/utilities.tex +1023 −0
  261. sys/src/cmd/python/Doc/api/veryhigh.tex +287 −0
  262. sys/src/cmd/python/Doc/commontex/boilerplate.tex +9 −0
  263. sys/src/cmd/python/Doc/commontex/copyright.tex +14 −0
  264. sys/src/cmd/python/Doc/commontex/license.tex +673 −0
  265. sys/src/cmd/python/Doc/commontex/reportingbugs.tex +61 −0
  266. sys/src/cmd/python/Doc/commontex/typestruct.h +76 −0
  267. sys/src/cmd/python/Doc/dist/dist.tex +3795 −0
  268. sys/src/cmd/python/Doc/dist/sysconfig.tex +113 −0
  269. sys/src/cmd/python/Doc/doc/doc.tex +2129 −0
  270. sys/src/cmd/python/Doc/ext/building.tex +143 −0
  271. sys/src/cmd/python/Doc/ext/embedding.tex +316 −0
  272. sys/src/cmd/python/Doc/ext/ext.tex +67 −0
  273. sys/src/cmd/python/Doc/ext/extending.tex +1390 −0
  274. sys/src/cmd/python/Doc/ext/newtypes.tex +1765 −0
  275. sys/src/cmd/python/Doc/ext/noddy.c +54 −0
  276. sys/src/cmd/python/Doc/ext/noddy2.c +190 −0
  277. sys/src/cmd/python/Doc/ext/noddy3.c +243 −0
  278. sys/src/cmd/python/Doc/ext/noddy4.c +224 −0
  279. sys/src/cmd/python/Doc/ext/run-func.c +68 −0
  280. sys/src/cmd/python/Doc/ext/setup.py +8 −0
  281. sys/src/cmd/python/Doc/ext/shoddy.c +91 −0
  282. sys/src/cmd/python/Doc/ext/test.py +213 −0
  283. sys/src/cmd/python/Doc/ext/windows.tex +320 −0
  284. sys/src/cmd/python/Doc/howto/Makefile +84 −0
  285. sys/src/cmd/python/Doc/howto/TODO +13 −0
  286. sys/src/cmd/python/Doc/howto/advocacy.tex +411 −0
  287. sys/src/cmd/python/Doc/howto/curses.tex +485 −0
  288. sys/src/cmd/python/Doc/howto/doanddont.tex +344 −0
  289. sys/src/cmd/python/Doc/howto/regex.tex +1463 −0
  290. sys/src/cmd/python/Doc/howto/sockets.tex +465 −0
  291. sys/src/cmd/python/Doc/howto/unicode.rst +766 −0
  292. sys/src/cmd/python/Doc/howto/urllib2.rst +598 −0
  293. sys/src/cmd/python/Doc/html/about.dat +24 −0
  294. sys/src/cmd/python/Doc/html/about.html +84 −0
  295. sys/src/cmd/python/Doc/html/icons/blank.gif +0 −0
  296. sys/src/cmd/python/Doc/html/icons/blank.png +0 −0
  297. sys/src/cmd/python/Doc/html/icons/contents.gif +0 −0
  298. sys/src/cmd/python/Doc/html/icons/contents.png +0 −0
  299. sys/src/cmd/python/Doc/html/icons/index.gif +0 −0
  300. sys/src/cmd/python/Doc/html/icons/index.png +0 −0
  301. sys/src/cmd/python/Doc/html/icons/modules.gif +0 −0
  302. sys/src/cmd/python/Doc/html/icons/modules.png +0 −0
  303. sys/src/cmd/python/Doc/html/icons/next.gif +0 −0
  304. sys/src/cmd/python/Doc/html/icons/next.png +0 −0
  305. sys/src/cmd/python/Doc/html/icons/previous.gif +0 −0
  306. sys/src/cmd/python/Doc/html/icons/previous.png +0 −0
  307. sys/src/cmd/python/Doc/html/icons/pyfav.gif +0 −0
  308. sys/src/cmd/python/Doc/html/icons/pyfav.png +0 −0
  309. sys/src/cmd/python/Doc/html/icons/up.gif +0 −0
  310. sys/src/cmd/python/Doc/html/icons/up.png +0 −0
  311. sys/src/cmd/python/Doc/html/index.html.in +140 −0
  312. sys/src/cmd/python/Doc/html/stdabout.dat +54 −0
  313. sys/src/cmd/python/Doc/html/style.css +243 −0
  314. sys/src/cmd/python/Doc/info/Makefile +82 −0
  315. sys/src/cmd/python/Doc/info/README +21 −0
  316. sys/src/cmd/python/Doc/info/python.dir +11 −0
  317. sys/src/cmd/python/Doc/inst/inst.tex +1112 −0
  318. sys/src/cmd/python/Doc/lib/archiving.tex +8 −0
  319. sys/src/cmd/python/Doc/lib/asttable.tex +283 −0
  320. sys/src/cmd/python/Doc/lib/caseless.py +60 −0
  321. sys/src/cmd/python/Doc/lib/compiler.tex +354 −0
  322. sys/src/cmd/python/Doc/lib/custominterp.tex +13 −0
  323. sys/src/cmd/python/Doc/lib/datatypes.tex +10 −0
  324. sys/src/cmd/python/Doc/lib/development.tex +13 −0
  325. sys/src/cmd/python/Doc/lib/distutils.tex +38 −0
  326. sys/src/cmd/python/Doc/lib/email-dir.py +115 −0
  327. sys/src/cmd/python/Doc/lib/email-mime.py +32 −0
  328. sys/src/cmd/python/Doc/lib/email-simple.py +25 −0
  329. sys/src/cmd/python/Doc/lib/email-unpack.py +68 −0
  330. sys/src/cmd/python/Doc/lib/email.tex +402 −0
  331. sys/src/cmd/python/Doc/lib/emailcharsets.tex +244 −0
  332. sys/src/cmd/python/Doc/lib/emailencoders.tex +47 −0
  333. sys/src/cmd/python/Doc/lib/emailexc.tex +87 −0
  334. sys/src/cmd/python/Doc/lib/emailgenerator.tex +133 −0
  335. sys/src/cmd/python/Doc/lib/emailheaders.tex +178 −0
  336. sys/src/cmd/python/Doc/lib/emailiter.tex +65 −0
  337. sys/src/cmd/python/Doc/lib/emailmessage.tex +561 −0
  338. sys/src/cmd/python/Doc/lib/emailmimebase.tex +186 −0
  339. sys/src/cmd/python/Doc/lib/emailparser.tex +208 −0
  340. sys/src/cmd/python/Doc/lib/emailutil.tex +157 −0
  341. sys/src/cmd/python/Doc/lib/fileformats.tex +7 −0
  342. sys/src/cmd/python/Doc/lib/filesys.tex +18 −0
  343. sys/src/cmd/python/Doc/lib/frameworks.tex +10 −0
  344. sys/src/cmd/python/Doc/lib/i18n.tex +11 −0
  345. sys/src/cmd/python/Doc/lib/internet.tex +13 −0
  346. sys/src/cmd/python/Doc/lib/ipc.tex +14 −0
  347. sys/src/cmd/python/Doc/lib/language.tex +10 −0
  348. sys/src/cmd/python/Doc/lib/lib.tex +487 −0
  349. sys/src/cmd/python/Doc/lib/libaifc.tex +202 −0
  350. sys/src/cmd/python/Doc/lib/libal.tex +181 −0
  351. sys/src/cmd/python/Doc/lib/liballos.tex +9 −0
  352. sys/src/cmd/python/Doc/lib/libamoeba.tex +132 −0
  353. sys/src/cmd/python/Doc/lib/libanydbm.tex +85 −0
  354. sys/src/cmd/python/Doc/lib/libarray.tex +241 −0
  355. sys/src/cmd/python/Doc/lib/libascii.tex +175 −0
  356. sys/src/cmd/python/Doc/lib/libast.tex +57 −0
  357. sys/src/cmd/python/Doc/lib/libasynchat.tex +254 −0
  358. sys/src/cmd/python/Doc/lib/libasyncore.tex +260 −0
  359. sys/src/cmd/python/Doc/lib/libatexit.tex +94 −0
  360. sys/src/cmd/python/Doc/lib/libaudioop.tex +259 −0
  361. sys/src/cmd/python/Doc/lib/libbase64.tex +169 −0
  362. sys/src/cmd/python/Doc/lib/libbasehttp.tex +245 −0
  363. sys/src/cmd/python/Doc/lib/libbastion.tex +57 −0
  364. sys/src/cmd/python/Doc/lib/libbinascii.tex +147 −0
  365. sys/src/cmd/python/Doc/lib/libbinhex.tex +55 −0
  366. sys/src/cmd/python/Doc/lib/libbisect.tex +84 −0
  367. sys/src/cmd/python/Doc/lib/libbltin.tex +44 −0
  368. sys/src/cmd/python/Doc/lib/libbsddb.tex +208 −0
  369. sys/src/cmd/python/Doc/lib/libbz2.tex +174 −0
  370. sys/src/cmd/python/Doc/lib/libcalendar.tex +304 −0
  371. sys/src/cmd/python/Doc/lib/libcd.tex +304 −0
  372. sys/src/cmd/python/Doc/lib/libcfgparser.tex +313 −0
  373. sys/src/cmd/python/Doc/lib/libcgi.tex +602 −0
  374. sys/src/cmd/python/Doc/lib/libcgihttp.tex +70 −0
  375. sys/src/cmd/python/Doc/lib/libcgitb.tex +67 −0
  376. sys/src/cmd/python/Doc/lib/libchunk.tex +111 −0
  377. sys/src/cmd/python/Doc/lib/libcmath.tex +142 −0
  378. sys/src/cmd/python/Doc/lib/libcmd.tex +198 −0
  379. sys/src/cmd/python/Doc/lib/libcmp.tex +36 −0
  380. sys/src/cmd/python/Doc/lib/libcmpcache.tex +21 −0
  381. sys/src/cmd/python/Doc/lib/libcode.tex +173 −0
  382. sys/src/cmd/python/Doc/lib/libcodecs.tex +1348 −0
  383. sys/src/cmd/python/Doc/lib/libcodeop.tex +103 −0
  384. sys/src/cmd/python/Doc/lib/libcollections.tex +341 −0
  385. sys/src/cmd/python/Doc/lib/libcolorsys.tex +54 −0
  386. sys/src/cmd/python/Doc/lib/libcommands.tex +62 −0
  387. sys/src/cmd/python/Doc/lib/libcompileall.tex +63 −0
  388. sys/src/cmd/python/Doc/lib/libconsts.tex +31 −0
  389. sys/src/cmd/python/Doc/lib/libcontextlib.tex +130 −0
  390. sys/src/cmd/python/Doc/lib/libcookie.tex +260 −0
  391. sys/src/cmd/python/Doc/lib/libcookielib.tex +720 −0
  392. sys/src/cmd/python/Doc/lib/libcopy.tex +97 −0
  393. sys/src/cmd/python/Doc/lib/libcopyreg.tex +40 −0
  394. sys/src/cmd/python/Doc/lib/libcrypt.tex +54 −0
  395. sys/src/cmd/python/Doc/lib/libcrypto.tex +19 −0
  396. sys/src/cmd/python/Doc/lib/libcsv.tex +538 −0
  397. sys/src/cmd/python/Doc/lib/libctypes.tex +2443 −0
  398. sys/src/cmd/python/Doc/lib/libcurses.tex +1395 −0
  399. sys/src/cmd/python/Doc/lib/libcursespanel.tex +96 −0
  400. sys/src/cmd/python/Doc/lib/libdatetime.tex +1441 −0
  401. sys/src/cmd/python/Doc/lib/libdbhash.tex +88 −0
  402. sys/src/cmd/python/Doc/lib/libdbm.tex +61 −0
  403. sys/src/cmd/python/Doc/lib/libdecimal.tex +1313 −0
  404. sys/src/cmd/python/Doc/lib/libdifflib.tex +704 −0
  405. sys/src/cmd/python/Doc/lib/libdircache.tex +49 −0
  406. sys/src/cmd/python/Doc/lib/libdis.tex +706 −0
  407. sys/src/cmd/python/Doc/lib/libdl.tex +101 −0
  408. sys/src/cmd/python/Doc/lib/libdoctest.tex +1949 −0
  409. sys/src/cmd/python/Doc/lib/libdocxmlrpc.tex +105 −0
  410. sys/src/cmd/python/Doc/lib/libdumbdbm.tex +63 −0
  411. sys/src/cmd/python/Doc/lib/libdummythread.tex +22 −0
  412. sys/src/cmd/python/Doc/lib/libdummythreading.tex +22 −0
  413. sys/src/cmd/python/Doc/lib/liberrno.tex +149 −0
  414. sys/src/cmd/python/Doc/lib/libetree.tex +356 −0
  415. sys/src/cmd/python/Doc/lib/libexcs.tex +466 −0
  416. sys/src/cmd/python/Doc/lib/libfcntl.tex +174 −0
  417. sys/src/cmd/python/Doc/lib/libfilecmp.tex +142 −0
  418. sys/src/cmd/python/Doc/lib/libfileinput.tex +192 −0
  419. sys/src/cmd/python/Doc/lib/libfl.tex +507 −0
  420. sys/src/cmd/python/Doc/lib/libfm.tex +94 −0
  421. sys/src/cmd/python/Doc/lib/libfnmatch.tex +86 −0
  422. sys/src/cmd/python/Doc/lib/libformatter.tex +329 −0
  423. sys/src/cmd/python/Doc/lib/libfpectl.tex +127 −0
  424. sys/src/cmd/python/Doc/lib/libfpformat.tex +54 −0
  425. sys/src/cmd/python/Doc/lib/libftplib.tex +288 −0
  426. sys/src/cmd/python/Doc/lib/libfuncs.tex +1321 −0
  427. sys/src/cmd/python/Doc/lib/libfunctools.tex +132 −0
  428. sys/src/cmd/python/Doc/lib/libfuture.tex +69 −0
  429. sys/src/cmd/python/Doc/lib/libgc.tex +196 −0
  430. sys/src/cmd/python/Doc/lib/libgdbm.tex +100 −0
  431. sys/src/cmd/python/Doc/lib/libgetopt.tex +154 −0
  432. sys/src/cmd/python/Doc/lib/libgetpass.tex +36 −0
  433. sys/src/cmd/python/Doc/lib/libgettext.tex +773 −0
  434. sys/src/cmd/python/Doc/lib/libgl.tex +224 −0
  435. sys/src/cmd/python/Doc/lib/libglob.tex +51 −0
  436. sys/src/cmd/python/Doc/lib/libgopherlib.tex +36 −0
  437. sys/src/cmd/python/Doc/lib/libgrp.tex +49 −0
  438. sys/src/cmd/python/Doc/lib/libgzip.tex +70 −0
  439. sys/src/cmd/python/Doc/lib/libhashlib.tex +114 −0
  440. sys/src/cmd/python/Doc/lib/libheapq.tex +214 −0
  441. sys/src/cmd/python/Doc/lib/libhmac.tex +54 −0
  442. sys/src/cmd/python/Doc/lib/libhotshot.tex +137 −0
  443. sys/src/cmd/python/Doc/lib/libhtmllib.tex +181 −0
  444. sys/src/cmd/python/Doc/lib/libhtmlparser.tex +169 −0
  445. sys/src/cmd/python/Doc/lib/libhttplib.tex +434 −0
  446. sys/src/cmd/python/Doc/lib/libimageop.tex +100 −0
  447. sys/src/cmd/python/Doc/lib/libimaplib.tex +507 −0
  448. sys/src/cmd/python/Doc/lib/libimgfile.tex +66 −0
  449. sys/src/cmd/python/Doc/lib/libimghdr.tex +60 −0
  450. sys/src/cmd/python/Doc/lib/libimp.tex +291 −0
  451. sys/src/cmd/python/Doc/lib/libinspect.tex +393 −0
  452. sys/src/cmd/python/Doc/lib/libintro.tex +53 −0
  453. sys/src/cmd/python/Doc/lib/libitertools.tex +546 −0
  454. sys/src/cmd/python/Doc/lib/libjpeg.tex +80 −0
  455. sys/src/cmd/python/Doc/lib/libkeyword.tex +20 −0
  456. sys/src/cmd/python/Doc/lib/liblinecache.tex +50 −0
  457. sys/src/cmd/python/Doc/lib/liblocale.tex +527 −0
  458. sys/src/cmd/python/Doc/lib/liblogging.tex +1729 −0
  459. sys/src/cmd/python/Doc/lib/libmailbox.tex +1444 −0
  460. sys/src/cmd/python/Doc/lib/libmailcap.tex +82 −0
  461. sys/src/cmd/python/Doc/lib/libmain.tex +16 −0
  462. sys/src/cmd/python/Doc/lib/libmarshal.tex +117 −0
  463. sys/src/cmd/python/Doc/lib/libmath.tex +209 −0
  464. sys/src/cmd/python/Doc/lib/libmd5.tex +92 −0
  465. sys/src/cmd/python/Doc/lib/libmhlib.tex +168 −0
  466. sys/src/cmd/python/Doc/lib/libmimetools.tex +120 −0
  467. sys/src/cmd/python/Doc/lib/libmimetypes.tex +226 −0
  468. sys/src/cmd/python/Doc/lib/libmimewriter.tex +80 −0
  469. sys/src/cmd/python/Doc/lib/libmimify.tex +94 −0
  470. sys/src/cmd/python/Doc/lib/libmisc.tex +7 −0
  471. sys/src/cmd/python/Doc/lib/libmm.tex +8 −0
  472. sys/src/cmd/python/Doc/lib/libmmap.tex +171 −0
  473. sys/src/cmd/python/Doc/lib/libmodulefinder.tex +51 −0
  474. sys/src/cmd/python/Doc/lib/libmsilib.tex +485 −0
  475. sys/src/cmd/python/Doc/lib/libmsvcrt.tex +109 −0
  476. sys/src/cmd/python/Doc/lib/libmultifile.tex +175 −0
  477. sys/src/cmd/python/Doc/lib/libmutex.tex +57 −0
  478. sys/src/cmd/python/Doc/lib/libnetrc.tex +68 −0
  479. sys/src/cmd/python/Doc/lib/libnew.tex +63 −0
  480. sys/src/cmd/python/Doc/lib/libni.tex +63 −0
  481. sys/src/cmd/python/Doc/lib/libnis.tex +63 −0
  482. sys/src/cmd/python/Doc/lib/libnntplib.tex +355 −0
  483. sys/src/cmd/python/Doc/lib/libobjs.tex +24 −0
  484. sys/src/cmd/python/Doc/lib/liboperator.tex +530 −0
  485. sys/src/cmd/python/Doc/lib/liboptparse.tex +1888 −0
  486. sys/src/cmd/python/Doc/lib/libos.tex +2006 −0
  487. sys/src/cmd/python/Doc/lib/libossaudiodev.tex +401 −0
  488. sys/src/cmd/python/Doc/lib/libpanel.tex +74 −0
  489. sys/src/cmd/python/Doc/lib/libparser.tex +711 −0
  490. sys/src/cmd/python/Doc/lib/libpdb.tex +456 −0
  491. sys/src/cmd/python/Doc/lib/libpickle.tex +888 −0
  492. sys/src/cmd/python/Doc/lib/libpickletools.tex +34 −0
  493. sys/src/cmd/python/Doc/lib/libpipes.tex +84 −0
  494. sys/src/cmd/python/Doc/lib/libpkgutil.tex +45 −0
  495. sys/src/cmd/python/Doc/lib/libplatform.tex +221 −0
  496. sys/src/cmd/python/Doc/lib/libpopen2.tex +189 −0
  497. sys/src/cmd/python/Doc/lib/libpoplib.tex +181 −0
  498. sys/src/cmd/python/Doc/lib/libposix.tex +97 −0
  499. sys/src/cmd/python/Doc/lib/libposixfile.tex +175 −0
  500. sys/src/cmd/python/Doc/lib/libposixpath.tex +281 −0
  501. sys/src/cmd/python/Doc/lib/libpprint.tex +210 −0
  502. sys/src/cmd/python/Doc/lib/libprofile.tex +722 −0
  503. sys/src/cmd/python/Doc/lib/libpty.tex +44 −0
  504. sys/src/cmd/python/Doc/lib/libpwd.tex +57 −0
  505. sys/src/cmd/python/Doc/lib/libpyclbr.tex +102 −0
  506. sys/src/cmd/python/Doc/lib/libpycompile.tex +53 −0
  507. sys/src/cmd/python/Doc/lib/libpydoc.tex +67 −0
  508. sys/src/cmd/python/Doc/lib/libpyexpat.tex +777 −0
  509. sys/src/cmd/python/Doc/lib/libpython.tex +8 −0
  510. sys/src/cmd/python/Doc/lib/libqueue.tex +145 −0
  511. sys/src/cmd/python/Doc/lib/libquopri.tex +61 −0
  512. sys/src/cmd/python/Doc/lib/librandom.tex +309 −0
  513. sys/src/cmd/python/Doc/lib/libre.tex +954 −0
  514. sys/src/cmd/python/Doc/lib/libreadline.tex +196 −0
  515. sys/src/cmd/python/Doc/lib/librepr.tex +133 −0
  516. sys/src/cmd/python/Doc/lib/libresource.tex +215 −0
  517. sys/src/cmd/python/Doc/lib/librestricted.tex +66 −0
  518. sys/src/cmd/python/Doc/lib/librexec.tex +275 −0
  519. sys/src/cmd/python/Doc/lib/librfc822.tex +336 −0
  520. sys/src/cmd/python/Doc/lib/librgbimg.tex +54 −0
  521. sys/src/cmd/python/Doc/lib/librlcompleter.tex +65 −0
  522. sys/src/cmd/python/Doc/lib/librobotparser.tex +66 −0
  523. sys/src/cmd/python/Doc/lib/librunpy.tex +74 −0
  524. sys/src/cmd/python/Doc/lib/libsched.tex +97 −0
  525. sys/src/cmd/python/Doc/lib/libselect.tex +132 −0
  526. sys/src/cmd/python/Doc/lib/libsets.tex +264 −0
  527. sys/src/cmd/python/Doc/lib/libsgi.tex +7 −0
  528. sys/src/cmd/python/Doc/lib/libsgmllib.tex +271 −0
  529. sys/src/cmd/python/Doc/lib/libsha.tex +83 −0
  530. sys/src/cmd/python/Doc/lib/libshelve.tex +174 −0
  531. sys/src/cmd/python/Doc/lib/libshlex.tex +274 −0
  532. sys/src/cmd/python/Doc/lib/libshutil.tex +151 −0
  533. sys/src/cmd/python/Doc/lib/libsignal.tex +174 −0
  534. sys/src/cmd/python/Doc/lib/libsimplehttp.tex +86 −0
  535. sys/src/cmd/python/Doc/lib/libsimplexmlrpc.tex +228 −0
  536. sys/src/cmd/python/Doc/lib/libsite.tex +88 −0
  537. sys/src/cmd/python/Doc/lib/libsmtpd.tex +63 −0
  538. sys/src/cmd/python/Doc/lib/libsmtplib.tex +295 −0
  539. sys/src/cmd/python/Doc/lib/libsndhdr.tex +41 −0
  540. sys/src/cmd/python/Doc/lib/libsocket.tex +910 −0
  541. sys/src/cmd/python/Doc/lib/libsocksvr.tex +293 −0
  542. sys/src/cmd/python/Doc/lib/libsomeos.tex +10 −0
  543. sys/src/cmd/python/Doc/lib/libspwd.tex +48 −0
  544. sys/src/cmd/python/Doc/lib/libsqlite3.tex +642 −0
  545. sys/src/cmd/python/Doc/lib/libstat.tex +157 −0
  546. sys/src/cmd/python/Doc/lib/libstatvfs.tex +55 −0
  547. sys/src/cmd/python/Doc/lib/libstdtypes.tex +2095 −0
  548. sys/src/cmd/python/Doc/lib/libstdwin.tex +832 −0
  549. sys/src/cmd/python/Doc/lib/libstring.tex +451 −0
  550. sys/src/cmd/python/Doc/lib/libstringio.tex +121 −0
  551. sys/src/cmd/python/Doc/lib/libstringprep.tex +136 −0
  552. sys/src/cmd/python/Doc/lib/libstrings.tex +10 −0
  553. sys/src/cmd/python/Doc/lib/libstruct.tex +256 −0
  554. sys/src/cmd/python/Doc/lib/libsubprocess.tex +402 −0
  555. sys/src/cmd/python/Doc/lib/libsun.tex +5 −0
  556. sys/src/cmd/python/Doc/lib/libsunau.tex +218 −0
  557. sys/src/cmd/python/Doc/lib/libsunaudio.tex +146 −0
  558. sys/src/cmd/python/Doc/lib/libsymbol.tex +30 −0
  559. sys/src/cmd/python/Doc/lib/libsys.tex +617 −0
  560. sys/src/cmd/python/Doc/lib/libsyslog.tex +76 −0
  561. sys/src/cmd/python/Doc/lib/libtabnanny.tex +62 −0
  562. sys/src/cmd/python/Doc/lib/libtarfile.tex +497 −0
  563. sys/src/cmd/python/Doc/lib/libtelnetlib.tex +215 −0
  564. sys/src/cmd/python/Doc/lib/libtempfile.tex +194 −0
  565. sys/src/cmd/python/Doc/lib/libtermios.tex +106 −0
  566. sys/src/cmd/python/Doc/lib/libtest.tex +278 −0
  567. sys/src/cmd/python/Doc/lib/libtextwrap.tex +181 −0
  568. sys/src/cmd/python/Doc/lib/libthread.tex +173 −0
  569. sys/src/cmd/python/Doc/lib/libthreading.tex +716 −0
  570. sys/src/cmd/python/Doc/lib/libtime.tex +461 −0
  571. sys/src/cmd/python/Doc/lib/libtimeit.tex +224 −0
  572. sys/src/cmd/python/Doc/lib/libtoken.tex +44 −0
  573. sys/src/cmd/python/Doc/lib/libtokenize.tex +119 −0
  574. sys/src/cmd/python/Doc/lib/libtrace.tex +125 −0
  575. sys/src/cmd/python/Doc/lib/libtraceback.tex +157 −0
  576. sys/src/cmd/python/Doc/lib/libtty.tex +34 −0
  577. sys/src/cmd/python/Doc/lib/libturtle.tex +268 −0
  578. sys/src/cmd/python/Doc/lib/libtypes.tex +215 −0
  579. sys/src/cmd/python/Doc/lib/libundoc.tex +113 −0
  580. sys/src/cmd/python/Doc/lib/libunicodedata.tex +160 −0
  581. sys/src/cmd/python/Doc/lib/libunittest.tex +974 −0
  582. sys/src/cmd/python/Doc/lib/libunix.tex +8 −0
  583. sys/src/cmd/python/Doc/lib/liburllib.tex +497 −0
  584. sys/src/cmd/python/Doc/lib/liburllib2.tex +872 −0
  585. sys/src/cmd/python/Doc/lib/liburlparse.tex +253 −0
  586. sys/src/cmd/python/Doc/lib/libuser.tex +71 −0
  587. sys/src/cmd/python/Doc/lib/libuserdict.tex +181 −0
  588. sys/src/cmd/python/Doc/lib/libuu.tex +58 −0
  589. sys/src/cmd/python/Doc/lib/libuuid.tex +233 −0
  590. sys/src/cmd/python/Doc/lib/libwarnings.tex +253 −0
  591. sys/src/cmd/python/Doc/lib/libwave.tex +169 −0
  592. sys/src/cmd/python/Doc/lib/libweakref.tex +336 −0
  593. sys/src/cmd/python/Doc/lib/libwebbrowser.tex +173 −0
  594. sys/src/cmd/python/Doc/lib/libwhichdb.tex +20 −0
  595. sys/src/cmd/python/Doc/lib/libwinreg.tex +414 −0
  596. sys/src/cmd/python/Doc/lib/libwinsound.tex +142 −0
  597. sys/src/cmd/python/Doc/lib/libwsgiref.tex +782 −0
  598. sys/src/cmd/python/Doc/lib/libxdrlib.tex +251 −0
  599. sys/src/cmd/python/Doc/lib/libxmllib.tex +287 −0
  600. sys/src/cmd/python/Doc/lib/libxmlrpclib.tex +383 −0
  601. sys/src/cmd/python/Doc/lib/libzipfile.tex +309 −0
  602. sys/src/cmd/python/Doc/lib/libzipimport.tex +133 −0
  603. sys/src/cmd/python/Doc/lib/libzlib.tex +197 −0
  604. sys/src/cmd/python/Doc/lib/markup.tex +29 −0
  605. sys/src/cmd/python/Doc/lib/mimelib.tex +65 −0
  606. sys/src/cmd/python/Doc/lib/minidom-example.py +64 −0
  607. sys/src/cmd/python/Doc/lib/modules.tex +9 −0
  608. sys/src/cmd/python/Doc/lib/netdata.tex +6 −0
  609. sys/src/cmd/python/Doc/lib/numeric.tex +13 −0
  610. sys/src/cmd/python/Doc/lib/persistence.tex +15 −0
  611. sys/src/cmd/python/Doc/lib/required_1.py +20 −0
  612. sys/src/cmd/python/Doc/lib/required_2.py +41 −0
  613. sys/src/cmd/python/Doc/lib/sqlite3/adapter_datetime.py +14 −0
  614. sys/src/cmd/python/Doc/lib/sqlite3/adapter_point_1.py +16 −0
  615. sys/src/cmd/python/Doc/lib/sqlite3/adapter_point_2.py +17 −0
  616. sys/src/cmd/python/Doc/lib/sqlite3/collation_reverse.py +15 −0
  617. sys/src/cmd/python/Doc/lib/sqlite3/complete_statement.py +30 −0
  618. sys/src/cmd/python/Doc/lib/sqlite3/connect_db_1.py +3 −0
  619. sys/src/cmd/python/Doc/lib/sqlite3/connect_db_2.py +3 −0
  620. sys/src/cmd/python/Doc/lib/sqlite3/converter_point.py +47 −0
  621. sys/src/cmd/python/Doc/lib/sqlite3/countcursors.py +15 −0
  622. sys/src/cmd/python/Doc/lib/sqlite3/createdb.py +28 −0
  623. sys/src/cmd/python/Doc/lib/sqlite3/execsql_fetchonerow.py +17 −0
  624. sys/src/cmd/python/Doc/lib/sqlite3/execsql_printall_1.py +13 −0
  625. sys/src/cmd/python/Doc/lib/sqlite3/execute_1.py +11 −0
  626. sys/src/cmd/python/Doc/lib/sqlite3/execute_2.py +12 −0
  627. sys/src/cmd/python/Doc/lib/sqlite3/execute_3.py +12 −0
  628. sys/src/cmd/python/Doc/lib/sqlite3/executemany_1.py +24 −0
  629. sys/src/cmd/python/Doc/lib/sqlite3/executemany_2.py +15 −0
  630. sys/src/cmd/python/Doc/lib/sqlite3/executescript.py +24 −0
  631. sys/src/cmd/python/Doc/lib/sqlite3/insert_more_people.py +16 −0
  632. sys/src/cmd/python/Doc/lib/sqlite3/md5func.py +11 −0
  633. sys/src/cmd/python/Doc/lib/sqlite3/mysumaggr.py +20 −0
  634. sys/src/cmd/python/Doc/lib/sqlite3/parse_colnames.py +8 −0
  635. sys/src/cmd/python/Doc/lib/sqlite3/pysqlite_datetime.py +20 −0
  636. sys/src/cmd/python/Doc/lib/sqlite3/row_factory.py +13 −0
  637. sys/src/cmd/python/Doc/lib/sqlite3/rowclass.py +12 −0
  638. sys/src/cmd/python/Doc/lib/sqlite3/shared_cache.py +6 −0
  639. sys/src/cmd/python/Doc/lib/sqlite3/shortcut_methods.py +21 −0
  640. sys/src/cmd/python/Doc/lib/sqlite3/simple_tableprinter.py +26 −0
  641. sys/src/cmd/python/Doc/lib/sqlite3/text_factory.py +42 −0
  642. sys/src/cmd/python/Doc/lib/tkinter.tex +1873 −0
  643. sys/src/cmd/python/Doc/lib/tzinfo-examples.py +139 −0
  644. sys/src/cmd/python/Doc/lib/windows.tex +8 −0
  645. sys/src/cmd/python/Doc/lib/xmldom.tex +928 −0
  646. sys/src/cmd/python/Doc/lib/xmldomminidom.tex +285 −0
  647. sys/src/cmd/python/Doc/lib/xmldompulldom.tex +61 −0
  648. sys/src/cmd/python/Doc/lib/xmletree.tex +27 −0
  649. sys/src/cmd/python/Doc/lib/xmlsax.tex +143 −0
  650. sys/src/cmd/python/Doc/lib/xmlsaxhandler.tex +381 −0
  651. sys/src/cmd/python/Doc/lib/xmlsaxreader.tex +351 −0
  652. sys/src/cmd/python/Doc/lib/xmlsaxutils.tex +81 −0
  653. sys/src/cmd/python/Doc/mac/libaepack.tex +82 −0
  654. sys/src/cmd/python/Doc/mac/libaetools.tex +83 −0
  655. sys/src/cmd/python/Doc/mac/libaetypes.tex +135 −0
  656. sys/src/cmd/python/Doc/mac/libautogil.tex +26 −0
  657. sys/src/cmd/python/Doc/mac/libcolorpicker.tex +23 −0
  658. sys/src/cmd/python/Doc/mac/libframework.tex +314 −0
  659. sys/src/cmd/python/Doc/mac/libgensuitemodule.tex +64 −0
  660. sys/src/cmd/python/Doc/mac/libmac.tex +29 −0
  661. sys/src/cmd/python/Doc/mac/libmacfs.tex +241 −0
  662. sys/src/cmd/python/Doc/mac/libmacic.tex +123 −0
  663. sys/src/cmd/python/Doc/mac/libmacos.tex +90 −0
  664. sys/src/cmd/python/Doc/mac/libmacostools.tex +105 −0
  665. sys/src/cmd/python/Doc/mac/libmacui.tex +266 −0
  666. sys/src/cmd/python/Doc/mac/libminiae.tex +65 −0
  667. sys/src/cmd/python/Doc/mac/libscrap.tex +42 −0
  668. sys/src/cmd/python/Doc/mac/mac.tex +89 −0
  669. sys/src/cmd/python/Doc/mac/scripting.tex +101 −0
  670. sys/src/cmd/python/Doc/mac/toolbox.tex +173 −0
  671. sys/src/cmd/python/Doc/mac/undoc.tex +97 −0
  672. sys/src/cmd/python/Doc/mac/using.tex +218 −0
  673. sys/src/cmd/python/Doc/paper-a4/pypaper.sty +17 −0
  674. sys/src/cmd/python/Doc/perl/SynopsisTable.pm +95 −0
  675. sys/src/cmd/python/Doc/perl/distutils.perl +21 −0
  676. sys/src/cmd/python/Doc/perl/howto.perl +12 −0
  677. sys/src/cmd/python/Doc/perl/isilo.perl +12 −0
  678. sys/src/cmd/python/Doc/perl/l2hinit.perl +801 −0
  679. sys/src/cmd/python/Doc/perl/ltxmarkup.perl +67 −0
  680. sys/src/cmd/python/Doc/perl/manual.perl +15 −0
  681. sys/src/cmd/python/Doc/perl/python.perl +2172 −0
  682. sys/src/cmd/python/Doc/python-docs.txt +183 −0
  683. sys/src/cmd/python/Doc/ref/ref.tex +68 −0
  684. sys/src/cmd/python/Doc/ref/ref1.tex +136 −0
  685. sys/src/cmd/python/Doc/ref/ref2.tex +731 −0
  686. sys/src/cmd/python/Doc/ref/ref3.tex +2225 −0
  687. sys/src/cmd/python/Doc/ref/ref4.tex +219 −0
  688. sys/src/cmd/python/Doc/ref/ref5.tex +1325 −0
  689. sys/src/cmd/python/Doc/ref/ref6.tex +928 −0
  690. sys/src/cmd/python/Doc/ref/ref7.tex +544 −0
  691. sys/src/cmd/python/Doc/ref/ref8.tex +112 −0
  692. sys/src/cmd/python/Doc/ref/reswords.py +23 −0
  693. sys/src/cmd/python/Doc/templates/howto.tex +112 −0
  694. sys/src/cmd/python/Doc/templates/manual.tex +89 −0
  695. sys/src/cmd/python/Doc/templates/module.tex +170 −0
  696. sys/src/cmd/python/Doc/templates/whatsnewXY.tex +149 −0
  697. sys/src/cmd/python/Doc/tests/math.tex +16 −0
  698. sys/src/cmd/python/Doc/texinputs/distutils.sty +33 −0
  699. sys/src/cmd/python/Doc/texinputs/fancyhdr.sty +329 −0
  700. sys/src/cmd/python/Doc/texinputs/fncychap.sty +433 −0
  701. sys/src/cmd/python/Doc/texinputs/howto.cls +109 −0
  702. sys/src/cmd/python/Doc/texinputs/ltxmarkup.sty +40 −0
  703. sys/src/cmd/python/Doc/texinputs/manual.cls +155 −0
  704. sys/src/cmd/python/Doc/texinputs/pypaper.sty +18 −0
  705. sys/src/cmd/python/Doc/texinputs/python.ist +11 −0
  706. sys/src/cmd/python/Doc/texinputs/python.sty +1327 −0
  707. sys/src/cmd/python/Doc/texinputs/underscore.sty +232 −0
  708. sys/src/cmd/python/Doc/tools/anno-api.py +71 −0
  709. sys/src/cmd/python/Doc/tools/buildindex.py +388 −0
  710. sys/src/cmd/python/Doc/tools/checkargs.pm +112 −0
  711. sys/src/cmd/python/Doc/tools/cklatex +26 −0
  712. sys/src/cmd/python/Doc/tools/cmpcsyms +157 −0
  713. sys/src/cmd/python/Doc/tools/custlib.py +78 −0
  714. sys/src/cmd/python/Doc/tools/findcsyms +136 −0
  715. sys/src/cmd/python/Doc/tools/findmodrefs +63 −0
  716. sys/src/cmd/python/Doc/tools/findsyms +128 −0
  717. sys/src/cmd/python/Doc/tools/fix_hack +2 −0
  718. sys/src/cmd/python/Doc/tools/fix_libaux.sed +3 −0
  719. sys/src/cmd/python/Doc/tools/fixinfo.el +15 −0
  720. sys/src/cmd/python/Doc/tools/getpagecounts +97 −0
  721. sys/src/cmd/python/Doc/tools/getversioninfo +71 −0
  722. sys/src/cmd/python/Doc/tools/html2texi.pl +1750 −0
  723. sys/src/cmd/python/Doc/tools/indfix.py +100 −0
  724. sys/src/cmd/python/Doc/tools/keywords.py +19 −0
  725. sys/src/cmd/python/Doc/tools/listmodules +183 −0
  726. sys/src/cmd/python/Doc/tools/listmodules.py +126 −0
  727. sys/src/cmd/python/Doc/tools/makesec.sh +129 −0
  728. sys/src/cmd/python/Doc/tools/mkackshtml +66 −0
  729. sys/src/cmd/python/Doc/tools/mkhowto +659 −0
  730. sys/src/cmd/python/Doc/tools/mkinfo +65 −0
  731. sys/src/cmd/python/Doc/tools/mkmodindex +158 −0
  732. sys/src/cmd/python/Doc/tools/mkpkglist +85 −0
  733. sys/src/cmd/python/Doc/tools/mksourcepkg +164 −0
  734. sys/src/cmd/python/Doc/tools/node2label.pl +71 −0
  735. sys/src/cmd/python/Doc/tools/prechm.py +519 −0
  736. sys/src/cmd/python/Doc/tools/push-docs.sh +138 −0
  737. sys/src/cmd/python/Doc/tools/py2texi.el +970 −0
  738. sys/src/cmd/python/Doc/tools/refcounts.py +98 −0
  739. sys/src/cmd/python/Doc/tools/rewrite.py +54 −0
  740. sys/src/cmd/python/Doc/tools/sgmlconv/Makefile +67 −0
  741. sys/src/cmd/python/Doc/tools/sgmlconv/README +58 −0
  742. sys/src/cmd/python/Doc/tools/sgmlconv/conversion.xml +914 −0
  743. sys/src/cmd/python/Doc/tools/sgmlconv/docfixer.py +1073 −0
  744. sys/src/cmd/python/Doc/tools/sgmlconv/esis2sgml.py +264 −0
  745. sys/src/cmd/python/Doc/tools/sgmlconv/esistools.py +312 −0
  746. sys/src/cmd/python/Doc/tools/sgmlconv/latex2esis.py +565 −0
  747. sys/src/cmd/python/Doc/tools/sgmlconv/make.rules +48 −0
  748. sys/src/cmd/python/Doc/tools/support.py +202 −0
  749. sys/src/cmd/python/Doc/tools/toc2bkm.py +160 −0
  750. sys/src/cmd/python/Doc/tools/undoc_symbols.py +94 −0
  751. sys/src/cmd/python/Doc/tools/update-docs.sh +31 −0
  752. sys/src/cmd/python/Doc/tools/whichlibs +2 −0
  753. sys/src/cmd/python/Doc/tut/glossary.tex +352 −0
  754. sys/src/cmd/python/Doc/tut/tut.tex +5907 −0
  755. sys/src/cmd/python/Doc/whatsnew/Makefile +3 −0
  756. sys/src/cmd/python/Doc/whatsnew/whatsnew20.tex +1337 −0
  757. sys/src/cmd/python/Doc/whatsnew/whatsnew21.tex +868 −0
  758. sys/src/cmd/python/Doc/whatsnew/whatsnew22.tex +1466 −0
  759. sys/src/cmd/python/Doc/whatsnew/whatsnew23.tex +2380 −0
  760. sys/src/cmd/python/Doc/whatsnew/whatsnew24.tex +1757 −0
  761. sys/src/cmd/python/Doc/whatsnew/whatsnew25.tex +2530 −0
  762. sys/src/cmd/python/Extra/dummy.c +6 −0
  763. sys/src/cmd/python/Extra/mercurial/base85.c +155 −0
  764. sys/src/cmd/python/Extra/mercurial/bdiff.c +401 −0
  765. sys/src/cmd/python/Extra/mercurial/diffhelpers.c +156 −0
  766. sys/src/cmd/python/Extra/mercurial/mpatch.c +444 −0
  767. sys/src/cmd/python/Extra/mercurial/osutil.c +534 −0
  768. sys/src/cmd/python/Extra/mercurial/parsers.c +435 −0
  769. sys/src/cmd/python/Extra/mkfile +16 −0
  770. sys/src/cmd/python/Grammar/Grammar +148 −0
  771. sys/src/cmd/python/Include/Python-ast.h +501 −0
  772. sys/src/cmd/python/Include/Python.h +173 −0
  773. sys/src/cmd/python/Include/abstract.h +1276 −0
  774. sys/src/cmd/python/Include/asdl.h +45 −0
  775. sys/src/cmd/python/Include/ast.h +13 −0
  776. sys/src/cmd/python/Include/bitset.h +32 −0
  777. sys/src/cmd/python/Include/boolobject.h +36 −0
  778. sys/src/cmd/python/Include/bufferobject.h +33 −0
  779. sys/src/cmd/python/Include/cStringIO.h +70 −0
  780. sys/src/cmd/python/Include/cellobject.h +28 −0
  781. sys/src/cmd/python/Include/ceval.h +157 −0
  782. sys/src/cmd/python/Include/classobject.h +81 −0
  783. sys/src/cmd/python/Include/cobject.h +54 −0
  784. sys/src/cmd/python/Include/code.h +94 −0
  785. sys/src/cmd/python/Include/codecs.h +167 −0
  786. sys/src/cmd/python/Include/compile.h +39 −0
  787. sys/src/cmd/python/Include/complexobject.h +58 −0
  788. sys/src/cmd/python/Include/datetime.h +245 −0
  789. sys/src/cmd/python/Include/descrobject.h +91 −0
  790. sys/src/cmd/python/Include/dictobject.h +141 −0
  791. sys/src/cmd/python/Include/enumobject.h +17 −0
  792. sys/src/cmd/python/Include/errcode.h +36 −0
  793. sys/src/cmd/python/Include/eval.h +25 −0
  794. sys/src/cmd/python/Include/fileobject.h +63 −0
  795. sys/src/cmd/python/Include/floatobject.h +100 −0
  796. sys/src/cmd/python/Include/frameobject.h +81 −0
  797. sys/src/cmd/python/Include/funcobject.h +76 −0
  798. sys/src/cmd/python/Include/genobject.h +37 −0
  799. sys/src/cmd/python/Include/graminit.h +84 −0
  800. sys/src/cmd/python/Include/grammar.h +93 −0
  801. sys/src/cmd/python/Include/import.h +64 −0
  802. sys/src/cmd/python/Include/intobject.h +64 −0
  803. sys/src/cmd/python/Include/intrcheck.h +15 −0
  804. sys/src/cmd/python/Include/iterobject.h +23 −0
  805. sys/src/cmd/python/Include/listobject.h +67 −0
  806. sys/src/cmd/python/Include/longintrepr.h +63 −0
  807. sys/src/cmd/python/Include/longobject.h +114 −0
  808. sys/src/cmd/python/Include/marshal.h +25 −0
  809. sys/src/cmd/python/Include/metagrammar.h +18 −0
  810. sys/src/cmd/python/Include/methodobject.h +91 −0
  811. sys/src/cmd/python/Include/modsupport.h +133 −0
  812. sys/src/cmd/python/Include/moduleobject.h +24 −0
  813. sys/src/cmd/python/Include/node.h +40 −0
  814. sys/src/cmd/python/Include/object.h +868 −0
  815. sys/src/cmd/python/Include/objimpl.h +336 −0
  816. sys/src/cmd/python/Include/opcode.h +152 −0
  817. sys/src/cmd/python/Include/osdefs.h +55 −0
  818. sys/src/cmd/python/Include/parsetok.h +50 −0
  819. sys/src/cmd/python/Include/patchlevel.h +40 −0
  820. sys/src/cmd/python/Include/pgen.h +18 −0
  821. sys/src/cmd/python/Include/pgenheaders.h +42 −0
  822. sys/src/cmd/python/Include/py_curses.h +176 −0
  823. sys/src/cmd/python/Include/pyarena.h +62 −0
  824. sys/src/cmd/python/Include/pydebug.h +34 −0
  825. sys/src/cmd/python/Include/pyerrors.h +334 −0
  826. sys/src/cmd/python/Include/pyexpat.h +47 −0
  827. sys/src/cmd/python/Include/pyfpe.h +176 −0
  828. sys/src/cmd/python/Include/pygetopt.h +17 −0
  829. sys/src/cmd/python/Include/pymactoolbox.h +189 −0
  830. sys/src/cmd/python/Include/pymem.h +105 −0
  831. sys/src/cmd/python/Include/pyport.h +771 −0
  832. sys/src/cmd/python/Include/pystate.h +195 −0
  833. sys/src/cmd/python/Include/pystrtod.h +18 −0
  834. sys/src/cmd/python/Include/pythonrun.h +171 −0
  835. sys/src/cmd/python/Include/pythread.h +47 −0
  836. sys/src/cmd/python/Include/rangeobject.h +28 −0
  837. sys/src/cmd/python/Include/setobject.h +93 −0
  838. sys/src/cmd/python/Include/sliceobject.h +43 −0
  839. sys/src/cmd/python/Include/stringobject.h +183 −0
  840. sys/src/cmd/python/Include/structmember.h +93 −0
  841. sys/src/cmd/python/Include/structseq.h +41 −0
  842. sys/src/cmd/python/Include/symtable.h +103 −0
  843. sys/src/cmd/python/Include/sysmodule.h +30 −0
  844. sys/src/cmd/python/Include/timefuncs.h +23 −0
  845. sys/src/cmd/python/Include/token.h +83 −0
  846. sys/src/cmd/python/Include/traceback.h +30 −0
  847. sys/src/cmd/python/Include/tupleobject.h +57 −0
  848. sys/src/cmd/python/Include/ucnhash.h +31 −0
  849. sys/src/cmd/python/Include/unicodeobject.h +1265 −0
  850. sys/src/cmd/python/Include/weakrefobject.h +75 −0
  851. sys/src/cmd/python/LICENSE +270 −0
  852. sys/src/cmd/python/Misc/ACKS +698 −0
  853. sys/src/cmd/python/Misc/AIX-NOTES +155 −0
  854. sys/src/cmd/python/Misc/BeOS-NOTES +43 −0
  855. sys/src/cmd/python/Misc/BeOS-setup.py +574 −0
  856. sys/src/cmd/python/Misc/NEWS +2782 −0
  857. sys/src/cmd/python/Misc/NEWS.help +73 −0
  858. sys/src/cmd/python/Misc/PURIFY.README +97 −0
  859. sys/src/cmd/python/Misc/Porting +42 −0
  860. sys/src/cmd/python/Misc/README +33 −0
  861. sys/src/cmd/python/Misc/README.OpenBSD +38 −0
  862. sys/src/cmd/python/Misc/README.coverity +22 −0
  863. sys/src/cmd/python/Misc/README.klocwork +30 −0
  864. sys/src/cmd/python/Misc/README.valgrind +97 −0
  865. sys/src/cmd/python/Misc/RFD +114 −0
  866. sys/src/cmd/python/Misc/RPM/README +16 −0
  867. sys/src/cmd/python/Misc/RPM/python-2.5.spec +395 −0
  868. sys/src/cmd/python/Misc/SpecialBuilds.txt +261 −0
  869. sys/src/cmd/python/Misc/Vim/python.vim +147 −0
  870. sys/src/cmd/python/Misc/Vim/syntax_test.py +63 −0
  871. sys/src/cmd/python/Misc/Vim/vim_syntax.py +226 −0
  872. sys/src/cmd/python/Misc/Vim/vimrc +95 −0
  873. sys/src/cmd/python/Misc/build.sh +227 −0
  874. sys/src/cmd/python/Misc/cheatsheet +2279 −0
  875. sys/src/cmd/python/Misc/developers.txt +141 −0
  876. sys/src/cmd/python/Misc/find_recursionlimit.py +87 −0
  877. sys/src/cmd/python/Misc/gdbinit +140 −0
  878. sys/src/cmd/python/Misc/indent.pro +15 −0
  879. sys/src/cmd/python/Misc/pymemcompat.h +85 −0
  880. sys/src/cmd/python/Misc/python-config.in +53 −0
  881. sys/src/cmd/python/Misc/python-mode.el +3768 −0
  882. sys/src/cmd/python/Misc/python.man +397 −0
  883. sys/src/cmd/python/Misc/setuid-prog.c +176 −0
  884. sys/src/cmd/python/Misc/valgrind-python.supp +349 −0
  885. sys/src/cmd/python/Misc/vgrindefs +10 −0
  886. sys/src/cmd/python/Modules/Setup +488 −0
  887. sys/src/cmd/python/Modules/Setup.config +13 −0
  888. sys/src/cmd/python/Modules/Setup.config.in +13 −0
  889. sys/src/cmd/python/Modules/Setup.dist +487 −0
  890. sys/src/cmd/python/Modules/Setup.local +1 −0
  891. sys/src/cmd/python/Modules/_bisectmodule.c +235 −0
  892. sys/src/cmd/python/Modules/_bsddb.c +6047 −0
  893. sys/src/cmd/python/Modules/_codecsmodule.c +934 −0
  894. sys/src/cmd/python/Modules/_csv.c +1604 −0
sys/src/cmd/python/Demo/README+61−0
@@ -0,0 +1,61 @@
1This directory contains various demonstrations of what you can do with
2Python. They were all written by me except where explicitly stated
3otherwise -- in general, demos contributed by others ends up in the
4../Contrib directory, unless I think they're of utmost general
5importance (like Matt Conway's Tk demos).
6
7A fair number of utilities that are useful when while developing
8Python code can be found in the ../Tools directory -- some of these
9can also be considered good examples of how to write Python code.
10
11Finally, in order to save disk space and net bandwidth, not all
12subdirectories listed here are distributed. They are listed just
13in case I change my mind about them.
14
15
16cgi CGI examples (see also ../Tools/faqwiz/.)
17
18classes Some examples of how to use classes.
19
20comparisons A set of responses to a really old language-comparison
21 challenge.
22
23curses A set of curses demos.
24
25embed An example of embedding Python in another application
26 (see also pysvr).
27
28imputil Demonstration subclasses of imputil.Importer.
29
30md5test Test program for the optional md5 module.
31
32metaclasses The code from the 1.5 metaclasses paper on the web.
33
34parser Example using the parser module.
35
36pdist Old, unfinished code messing with CVS, RCS and remote
37 files.
38
39pysvr An example of embedding Python in a threaded
40 application.
41
42rpc A set of classes for building clients and servers for
43 Sun RPC.
44
45scripts Some useful Python scripts that I put in my bin
46 directory. No optional built-in modules needed.
47
48sockets Examples for the new built-in module 'socket'.
49
50threads Demos that use the 'thread' module. (Currently these
51 only run on SGIs, but this may change in the future.)
52
53tix Demos using the Tix widget set addition to Tkinter.
54
55tkinter Demos using the Tk interface (including Matt Conway's
56 excellent set of demos).
57
58xml Some XML demos.
59
60zlib Some demos for the zlib module (see also the standard
61 library module gzip.py).
sys/src/cmd/python/Demo/cgi/README+11−0
@@ -0,0 +1,11 @@
1CGI Examples
2------------
3
4Here are some example CGI programs. For a larger example, see
5../../Tools/faqwiz/.
6
7cgi0.sh -- A shell script to test your server is configured for CGI
8cgi1.py -- A Python script to test your server is configured for CGI
9cgi2.py -- A Python script showing how to parse a form
10cgi3.py -- A Python script for driving an arbitrary CGI application
11wiki.py -- Sample CGI application: a minimal Wiki implementation
sys/src/cmd/python/Demo/cgi/cgi0.sh+8−0
@@ -0,0 +1,8 @@
1#! /bin/sh
2
3# If you can't get this to work, your web server isn't set up right
4
5echo Content-type: text/plain
6echo
7echo Hello world
8echo This is cgi0.sh
sys/src/cmd/python/Demo/cgi/cgi1.py+14−0
@@ -0,0 +1,14 @@
1#!/usr/local/bin/python
2
3"""CGI test 1 - check server setup."""
4
5# Until you get this to work, your web server isn't set up right or
6# your Python isn't set up right.
7
8# If cgi0.sh works but cgi1.py doesn't, check the #! line and the file
9# permissions. The docs for the cgi.py module have debugging tips.
10
11print "Content-type: text/html"
12print
13print "<h1>Hello world</h1>"
14print "<p>This is cgi1.py"
sys/src/cmd/python/Demo/cgi/cgi2.py+22−0
@@ -0,0 +1,22 @@
1#!/usr/local/bin/python
2
3"""CGI test 2 - basic use of cgi module."""
4
5import cgitb; cgitb.enable()
6
7import cgi
8
9def main():
10 form = cgi.FieldStorage()
11 print "Content-type: text/html"
12 print
13 if not form:
14 print "<h1>No Form Keys</h1>"
15 else:
16 print "<h1>Form Keys</h1>"
17 for key in form.keys():
18 value = form[key].value
19 print "<p>", cgi.escape(key), ":", cgi.escape(value)
20
21if __name__ == "__main__":
22 main()
sys/src/cmd/python/Demo/cgi/cgi3.py+10−0
@@ -0,0 +1,10 @@
1#!/usr/local/bin/python
2
3"""CGI test 3 (persistent data)."""
4
5import cgitb; cgitb.enable()
6
7from wiki import main
8
9if __name__ == "__main__":
10 main()
sys/src/cmd/python/Demo/cgi/wiki.py+123−0
@@ -0,0 +1,123 @@
1"""Wiki main program. Imported and run by cgi3.py."""
2
3import os, re, cgi, sys, tempfile
4escape = cgi.escape
5
6def main():
7 form = cgi.FieldStorage()
8 print "Content-type: text/html"
9 print
10 cmd = form.getvalue("cmd", "view")
11 page = form.getvalue("page", "FrontPage")
12 wiki = WikiPage(page)
13 method = getattr(wiki, 'cmd_' + cmd, None) or wiki.cmd_view
14 method(form)
15
16class WikiPage:
17
18 homedir = tempfile.gettempdir()
19 scripturl = os.path.basename(sys.argv[0])
20
21 def __init__(self, name):
22 if not self.iswikiword(name):
23 raise ValueError, "page name is not a wiki word"
24 self.name = name
25 self.load()
26
27 def cmd_view(self, form):
28 print "<h1>", escape(self.splitwikiword(self.name)), "</h1>"
29 print "<p>"
30 for line in self.data.splitlines():
31 line = line.rstrip()
32 if not line:
33 print "<p>"
34 else:
35 print self.formatline(line)
36 print "<hr>"
37 print "<p>", self.mklink("edit", self.name, "Edit this page") + ";"
38 print self.mklink("view", "FrontPage", "go to front page") + "."
39
40 def formatline(self, line):
41 words = []
42 for word in re.split('(\W+)', line):
43 if self.iswikiword(word):
44 if os.path.isfile(self.mkfile(word)):
45 word = self.mklink("view", word, word)
46 else:
47 word = self.mklink("new", word, word + "*")
48 else:
49 word = escape(word)
50 words.append(word)
51 return "".join(words)
52
53 def cmd_edit(self, form, label="Change"):
54 print "<h1>", label, self.name, "</h1>"
55 print '<form method="POST" action="%s">' % self.scripturl
56 s = '<textarea cols="70" rows="20" name="text">%s</textarea>'
57 print s % self.data
58 print '<input type="hidden" name="cmd" value="create">'
59 print '<input type="hidden" name="page" value="%s">' % self.name
60 print '<br>'
61 print '<input type="submit" value="%s Page">' % label
62 print "</form>"
63
64 def cmd_create(self, form):
65 self.data = form.getvalue("text", "").strip()
66 error = self.store()
67 if error:
68 print "<h1>I'm sorry. That didn't work</h1>"
69 print "<p>An error occurred while attempting to write the file:"
70 print "<p>", escape(error)
71 else:
72 # Use a redirect directive, to avoid "reload page" problems
73 print "<head>"
74 s = '<meta http-equiv="refresh" content="1; URL=%s">'
75 print s % (self.scripturl + "?cmd=view&page=" + self.name)
76 print "<head>"
77 print "<h1>OK</h1>"
78 print "<p>If nothing happens, please click here:",
79 print self.mklink("view", self.name, self.name)
80
81 def cmd_new(self, form):
82 self.cmd_edit(form, label="Create")
83
84 def iswikiword(self, word):
85 return re.match("[A-Z][a-z]+([A-Z][a-z]*)+", word)
86
87 def splitwikiword(self, word):
88 chars = []
89 for c in word:
90 if chars and c.isupper():
91 chars.append(' ')
92 chars.append(c)
93 return "".join(chars)
94
95 def mkfile(self, name=None):
96 if name is None:
97 name = self.name
98 return os.path.join(self.homedir, name + ".txt")
99
100 def mklink(self, cmd, page, text):
101 link = self.scripturl + "?cmd=" + cmd + "&page=" + page
102 return '<a href="%s">%s</a>' % (link, text)
103
104 def load(self):
105 try:
106 f = open(self.mkfile())
107 data = f.read().strip()
108 f.close()
109 except IOError:
110 data = ""
111 self.data = data
112
113 def store(self):
114 data = self.data
115 try:
116 f = open(self.mkfile(), "w")
117 f.write(data)
118 if data and not data.endswith('\n'):
119 f.write('\n')
120 f.close()
121 return ""
122 except IOError, err:
123 return "IOError: %s" % str(err)
sys/src/cmd/python/Demo/classes/Complex.py+320−0
@@ -0,0 +1,320 @@
1# Complex numbers
2# ---------------
3
4# [Now that Python has a complex data type built-in, this is not very
5# useful, but it's still a nice example class]
6
7# This module represents complex numbers as instances of the class Complex.
8# A Complex instance z has two data attribues, z.re (the real part) and z.im
9# (the imaginary part). In fact, z.re and z.im can have any value -- all
10# arithmetic operators work regardless of the type of z.re and z.im (as long
11# as they support numerical operations).
12#
13# The following functions exist (Complex is actually a class):
14# Complex([re [,im]) -> creates a complex number from a real and an imaginary part
15# IsComplex(z) -> true iff z is a complex number (== has .re and .im attributes)
16# ToComplex(z) -> a complex number equal to z; z itself if IsComplex(z) is true
17# if z is a tuple(re, im) it will also be converted
18# PolarToComplex([r [,phi [,fullcircle]]]) ->
19# the complex number z for which r == z.radius() and phi == z.angle(fullcircle)
20# (r and phi default to 0)
21# exp(z) -> returns the complex exponential of z. Equivalent to pow(math.e,z).
22#
23# Complex numbers have the following methods:
24# z.abs() -> absolute value of z
25# z.radius() == z.abs()
26# z.angle([fullcircle]) -> angle from positive X axis; fullcircle gives units
27# z.phi([fullcircle]) == z.angle(fullcircle)
28#
29# These standard functions and unary operators accept complex arguments:
30# abs(z)
31# -z
32# +z
33# not z
34# repr(z) == `z`
35# str(z)
36# hash(z) -> a combination of hash(z.re) and hash(z.im) such that if z.im is zero
37# the result equals hash(z.re)
38# Note that hex(z) and oct(z) are not defined.
39#
40# These conversions accept complex arguments only if their imaginary part is zero:
41# int(z)
42# long(z)
43# float(z)
44#
45# The following operators accept two complex numbers, or one complex number
46# and one real number (int, long or float):
47# z1 + z2
48# z1 - z2
49# z1 * z2
50# z1 / z2
51# pow(z1, z2)
52# cmp(z1, z2)
53# Note that z1 % z2 and divmod(z1, z2) are not defined,
54# nor are shift and mask operations.
55#
56# The standard module math does not support complex numbers.
57# The cmath modules should be used instead.
58#
59# Idea:
60# add a class Polar(r, phi) and mixed-mode arithmetic which
61# chooses the most appropriate type for the result:
62# Complex for +,-,cmp
63# Polar for *,/,pow
64
65import math
66import sys
67
68twopi = math.pi*2.0
69halfpi = math.pi/2.0
70
71def IsComplex(obj):
72 return hasattr(obj, 're') and hasattr(obj, 'im')
73
74def ToComplex(obj):
75 if IsComplex(obj):
76 return obj
77 elif isinstance(obj, tuple):
78 return Complex(*obj)
79 else:
80 return Complex(obj)
81
82def PolarToComplex(r = 0, phi = 0, fullcircle = twopi):
83 phi = phi * (twopi / fullcircle)
84 return Complex(math.cos(phi)*r, math.sin(phi)*r)
85
86def Re(obj):
87 if IsComplex(obj):
88 return obj.re
89 return obj
90
91def Im(obj):
92 if IsComplex(obj):
93 return obj.im
94 return 0
95
96class Complex:
97
98 def __init__(self, re=0, im=0):
99 _re = 0
100 _im = 0
101 if IsComplex(re):
102 _re = re.re
103 _im = re.im
104 else:
105 _re = re
106 if IsComplex(im):
107 _re = _re - im.im
108 _im = _im + im.re
109 else:
110 _im = _im + im
111 # this class is immutable, so setting self.re directly is
112 # not possible.
113 self.__dict__['re'] = _re
114 self.__dict__['im'] = _im
115
116 def __setattr__(self, name, value):
117 raise TypeError, 'Complex numbers are immutable'
118
119 def __hash__(self):
120 if not self.im:
121 return hash(self.re)
122 return hash((self.re, self.im))
123
124 def __repr__(self):
125 if not self.im:
126 return 'Complex(%r)' % (self.re,)
127 else:
128 return 'Complex(%r, %r)' % (self.re, self.im)
129
130 def __str__(self):
131 if not self.im:
132 return repr(self.re)
133 else:
134 return 'Complex(%r, %r)' % (self.re, self.im)
135
136 def __neg__(self):
137 return Complex(-self.re, -self.im)
138
139 def __pos__(self):
140 return self
141
142 def __abs__(self):
143 return math.hypot(self.re, self.im)
144
145 def __int__(self):
146 if self.im:
147 raise ValueError, "can't convert Complex with nonzero im to int"
148 return int(self.re)
149
150 def __long__(self):
151 if self.im:
152 raise ValueError, "can't convert Complex with nonzero im to long"
153 return long(self.re)
154
155 def __float__(self):
156 if self.im:
157 raise ValueError, "can't convert Complex with nonzero im to float"
158 return float(self.re)
159
160 def __cmp__(self, other):
161 other = ToComplex(other)
162 return cmp((self.re, self.im), (other.re, other.im))
163
164 def __rcmp__(self, other):
165 other = ToComplex(other)
166 return cmp(other, self)
167
168 def __nonzero__(self):
169 return not (self.re == self.im == 0)
170
171 abs = radius = __abs__
172
173 def angle(self, fullcircle = twopi):
174 return (fullcircle/twopi) * ((halfpi - math.atan2(self.re, self.im)) % twopi)
175
176 phi = angle
177
178 def __add__(self, other):
179 other = ToComplex(other)
180 return Complex(self.re + other.re, self.im + other.im)
181
182 __radd__ = __add__
183
184 def __sub__(self, other):
185 other = ToComplex(other)
186 return Complex(self.re - other.re, self.im - other.im)
187
188 def __rsub__(self, other):
189 other = ToComplex(other)
190 return other - self
191
192 def __mul__(self, other):
193 other = ToComplex(other)
194 return Complex(self.re*other.re - self.im*other.im,
195 self.re*other.im + self.im*other.re)
196
197 __rmul__ = __mul__
198
199 def __div__(self, other):
200 other = ToComplex(other)
201 d = float(other.re*other.re + other.im*other.im)
202 if not d: raise ZeroDivisionError, 'Complex division'
203 return Complex((self.re*other.re + self.im*other.im) / d,
204 (self.im*other.re - self.re*other.im) / d)
205
206 def __rdiv__(self, other):
207 other = ToComplex(other)
208 return other / self
209
210 def __pow__(self, n, z=None):
211 if z is not None:
212 raise TypeError, 'Complex does not support ternary pow()'
213 if IsComplex(n):
214 if n.im:
215 if self.im: raise TypeError, 'Complex to the Complex power'
216 else: return exp(math.log(self.re)*n)
217 n = n.re
218 r = pow(self.abs(), n)
219 phi = n*self.angle()
220 return Complex(math.cos(phi)*r, math.sin(phi)*r)
221
222 def __rpow__(self, base):
223 base = ToComplex(base)
224 return pow(base, self)
225
226def exp(z):
227 r = math.exp(z.re)
228 return Complex(math.cos(z.im)*r,math.sin(z.im)*r)
229
230
231def checkop(expr, a, b, value, fuzz = 1e-6):
232 print ' ', a, 'and', b,
233 try:
234 result = eval(expr)
235 except:
236 result = sys.exc_type
237 print '->', result
238 if isinstance(result, str) or isinstance(value, str):
239 ok = (result == value)
240 else:
241 ok = abs(result - value) <= fuzz
242 if not ok:
243 print '!!\t!!\t!! should be', value, 'diff', abs(result - value)
244
245def test():
246 print 'test constructors'
247 constructor_test = (
248 # "expect" is an array [re,im] "got" the Complex.
249 ( (0,0), Complex() ),
250 ( (0,0), Complex() ),
251 ( (1,0), Complex(1) ),
252 ( (0,1), Complex(0,1) ),
253 ( (1,2), Complex(Complex(1,2)) ),
254 ( (1,3), Complex(Complex(1,2),1) ),
255 ( (0,0), Complex(0,Complex(0,0)) ),
256 ( (3,4), Complex(3,Complex(4)) ),
257 ( (-1,3), Complex(1,Complex(3,2)) ),
258 ( (-7,6), Complex(Complex(1,2),Complex(4,8)) ) )
259 cnt = [0,0]
260 for t in constructor_test:
261 cnt[0] += 1
262 if ((t[0][0]!=t[1].re)or(t[0][1]!=t[1].im)):
263 print " expected", t[0], "got", t[1]
264 cnt[1] += 1
265 print " ", cnt[1], "of", cnt[0], "tests failed"
266 # test operators
267 testsuite = {
268 'a+b': [
269 (1, 10, 11),
270 (1, Complex(0,10), Complex(1,10)),
271 (Complex(0,10), 1, Complex(1,10)),
272 (Complex(0,10), Complex(1), Complex(1,10)),
273 (Complex(1), Complex(0,10), Complex(1,10)),
274 ],
275 'a-b': [
276 (1, 10, -9),
277 (1, Complex(0,10), Complex(1,-10)),
278 (Complex(0,10), 1, Complex(-1,10)),
279 (Complex(0,10), Complex(1), Complex(-1,10)),
280 (Complex(1), Complex(0,10), Complex(1,-10)),
281 ],
282 'a*b': [
283 (1, 10, 10),
284 (1, Complex(0,10), Complex(0, 10)),
285 (Complex(0,10), 1, Complex(0,10)),
286 (Complex(0,10), Complex(1), Complex(0,10)),
287 (Complex(1), Complex(0,10), Complex(0,10)),
288 ],
289 'a/b': [
290 (1., 10, 0.1),
291 (1, Complex(0,10), Complex(0, -0.1)),
292 (Complex(0, 10), 1, Complex(0, 10)),
293 (Complex(0, 10), Complex(1), Complex(0, 10)),
294 (Complex(1), Complex(0,10), Complex(0, -0.1)),
295 ],
296 'pow(a,b)': [
297 (1, 10, 1),
298 (1, Complex(0,10), 1),
299 (Complex(0,10), 1, Complex(0,10)),
300 (Complex(0,10), Complex(1), Complex(0,10)),
301 (Complex(1), Complex(0,10), 1),
302 (2, Complex(4,0), 16),
303 ],
304 'cmp(a,b)': [
305 (1, 10, -1),
306 (1, Complex(0,10), 1),
307 (Complex(0,10), 1, -1),
308 (Complex(0,10), Complex(1), -1),
309 (Complex(1), Complex(0,10), 1),
310 ],
311 }
312 for expr in sorted(testsuite):
313 print expr + ':'
314 t = (expr,)
315 for item in testsuite[expr]:
316 checkop(*(t+item))
317
318
319if __name__ == '__main__':
320 test()
sys/src/cmd/python/Demo/classes/Dates.py+222−0
@@ -0,0 +1,222 @@
1# Class Date supplies date objects that support date arithmetic.
2#
3# Date(month,day,year) returns a Date object. An instance prints as,
4# e.g., 'Mon 16 Aug 1993'.
5#
6# Addition, subtraction, comparison operators, min, max, and sorting
7# all work as expected for date objects: int+date or date+int returns
8# the date `int' days from `date'; date+date raises an exception;
9# date-int returns the date `int' days before `date'; date2-date1 returns
10# an integer, the number of days from date1 to date2; int-date raises an
11# exception; date1 < date2 is true iff date1 occurs before date2 (&
12# similarly for other comparisons); min(date1,date2) is the earlier of
13# the two dates and max(date1,date2) the later; and date objects can be
14# used as dictionary keys.
15#
16# Date objects support one visible method, date.weekday(). This returns
17# the day of the week the date falls on, as a string.
18#
19# Date objects also have 4 read-only data attributes:
20# .month in 1..12
21# .day in 1..31
22# .year int or long int
23# .ord the ordinal of the date relative to an arbitrary staring point
24#
25# The Dates module also supplies function today(), which returns the
26# current date as a date object.
27#
28# Those entranced by calendar trivia will be disappointed, as no attempt
29# has been made to accommodate the Julian (etc) system. On the other
30# hand, at least this package knows that 2000 is a leap year but 2100
31# isn't, and works fine for years with a hundred decimal digits <wink>.
32
33# Tim Peters tim@ksr.com
34# not speaking for Kendall Square Research Corp
35
36# Adapted to Python 1.1 (where some hacks to overcome coercion are unnecessary)
37# by Guido van Rossum
38
39# Note that as of Python 2.3, a datetime module is included in the stardard
40# library.
41
42# vi:set tabsize=8:
43
44_MONTH_NAMES = [ 'January', 'February', 'March', 'April', 'May',
45 'June', 'July', 'August', 'September', 'October',
46 'November', 'December' ]
47
48_DAY_NAMES = [ 'Friday', 'Saturday', 'Sunday', 'Monday',
49 'Tuesday', 'Wednesday', 'Thursday' ]
50
51_DAYS_IN_MONTH = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]
52
53_DAYS_BEFORE_MONTH = []
54dbm = 0
55for dim in _DAYS_IN_MONTH:
56 _DAYS_BEFORE_MONTH.append(dbm)
57 dbm = dbm + dim
58del dbm, dim
59
60_INT_TYPES = type(1), type(1L)
61
62def _is_leap(year): # 1 if leap year, else 0
63 if year % 4 != 0: return 0
64 if year % 400 == 0: return 1
65 return year % 100 != 0
66
67def _days_in_year(year): # number of days in year
68 return 365 + _is_leap(year)
69
70def _days_before_year(year): # number of days before year
71 return year*365L + (year+3)/4 - (year+99)/100 + (year+399)/400
72
73def _days_in_month(month, year): # number of days in month of year
74 if month == 2 and _is_leap(year): return 29
75 return _DAYS_IN_MONTH[month-1]
76
77def _days_before_month(month, year): # number of days in year before month
78 return _DAYS_BEFORE_MONTH[month-1] + (month > 2 and _is_leap(year))
79
80def _date2num(date): # compute ordinal of date.month,day,year
81 return _days_before_year(date.year) + \
82 _days_before_month(date.month, date.year) + \
83 date.day
84
85_DI400Y = _days_before_year(400) # number of days in 400 years
86
87def _num2date(n): # return date with ordinal n
88 if type(n) not in _INT_TYPES:
89 raise TypeError, 'argument must be integer: %r' % type(n)
90
91 ans = Date(1,1,1) # arguments irrelevant; just getting a Date obj
92 del ans.ord, ans.month, ans.day, ans.year # un-initialize it
93 ans.ord = n
94
95 n400 = (n-1)/_DI400Y # # of 400-year blocks preceding
96 year, n = 400 * n400, n - _DI400Y * n400
97 more = n / 365
98 dby = _days_before_year(more)
99 if dby >= n:
100 more = more - 1
101 dby = dby - _days_in_year(more)
102 year, n = year + more, int(n - dby)
103
104 try: year = int(year) # chop to int, if it fits
105 except (ValueError, OverflowError): pass
106
107 month = min(n/29 + 1, 12)
108 dbm = _days_before_month(month, year)
109 if dbm >= n:
110 month = month - 1
111 dbm = dbm - _days_in_month(month, year)
112
113 ans.month, ans.day, ans.year = month, n-dbm, year
114 return ans
115
116def _num2day(n): # return weekday name of day with ordinal n
117 return _DAY_NAMES[ int(n % 7) ]
118
119
120class Date:
121 def __init__(self, month, day, year):
122 if not 1 <= month <= 12:
123 raise ValueError, 'month must be in 1..12: %r' % (month,)
124 dim = _days_in_month(month, year)
125 if not 1 <= day <= dim:
126 raise ValueError, 'day must be in 1..%r: %r' % (dim, day)
127 self.month, self.day, self.year = month, day, year
128 self.ord = _date2num(self)
129
130 # don't allow setting existing attributes
131 def __setattr__(self, name, value):
132 if self.__dict__.has_key(name):
133 raise AttributeError, 'read-only attribute ' + name
134 self.__dict__[name] = value
135
136 def __cmp__(self, other):
137 return cmp(self.ord, other.ord)
138
139 # define a hash function so dates can be used as dictionary keys
140 def __hash__(self):
141 return hash(self.ord)
142
143 # print as, e.g., Mon 16 Aug 1993
144 def __repr__(self):
145 return '%.3s %2d %.3s %r' % (
146 self.weekday(),
147 self.day,
148 _MONTH_NAMES[self.month-1],
149 self.year)
150
151 # Python 1.1 coerces neither int+date nor date+int
152 def __add__(self, n):
153 if type(n) not in _INT_TYPES:
154 raise TypeError, 'can\'t add %r to date' % type(n)
155 return _num2date(self.ord + n)
156 __radd__ = __add__ # handle int+date
157
158 # Python 1.1 coerces neither date-int nor date-date
159 def __sub__(self, other):
160 if type(other) in _INT_TYPES: # date-int
161 return _num2date(self.ord - other)
162 else:
163 return self.ord - other.ord # date-date
164
165 # complain about int-date
166 def __rsub__(self, other):
167 raise TypeError, 'Can\'t subtract date from integer'
168
169 def weekday(self):
170 return _num2day(self.ord)
171
172def today():
173 import time
174 local = time.localtime(time.time())
175 return Date(local[1], local[2], local[0])
176
177DateTestError = 'DateTestError'
178def test(firstyear, lastyear):
179 a = Date(9,30,1913)
180 b = Date(9,30,1914)
181 if repr(a) != 'Tue 30 Sep 1913':
182 raise DateTestError, '__repr__ failure'
183 if (not a < b) or a == b or a > b or b != b:
184 raise DateTestError, '__cmp__ failure'
185 if a+365 != b or 365+a != b:
186 raise DateTestError, '__add__ failure'
187 if b-a != 365 or b-365 != a:
188 raise DateTestError, '__sub__ failure'
189 try:
190 x = 1 - a
191 raise DateTestError, 'int-date should have failed'
192 except TypeError:
193 pass
194 try:
195 x = a + b
196 raise DateTestError, 'date+date should have failed'
197 except TypeError:
198 pass
199 if a.weekday() != 'Tuesday':
200 raise DateTestError, 'weekday() failure'
201 if max(a,b) is not b or min(a,b) is not a:
202 raise DateTestError, 'min/max failure'
203 d = {a-1:b, b:a+1}
204 if d[b-366] != b or d[a+(b-a)] != Date(10,1,1913):
205 raise DateTestError, 'dictionary failure'
206
207 # verify date<->number conversions for first and last days for
208 # all years in firstyear .. lastyear
209
210 lord = _days_before_year(firstyear)
211 y = firstyear
212 while y <= lastyear:
213 ford = lord + 1
214 lord = ford + _days_in_year(y) - 1
215 fd, ld = Date(1,1,y), Date(12,31,y)
216 if (fd.ord,ld.ord) != (ford,lord):
217 raise DateTestError, ('date->num failed', y)
218 fd, ld = _num2date(ford), _num2date(lord)
219 if (1,1,y,12,31,y) != \
220 (fd.month,fd.day,fd.year,ld.month,ld.day,ld.year):
221 raise DateTestError, ('num->date failed', y)
222 y = y + 1
sys/src/cmd/python/Demo/classes/Dbm.py+66−0
@@ -0,0 +1,66 @@
1# A wrapper around the (optional) built-in class dbm, supporting keys
2# and values of almost any type instead of just string.
3# (Actually, this works only for keys and values that can be read back
4# correctly after being converted to a string.)
5
6
7class Dbm:
8
9 def __init__(self, filename, mode, perm):
10 import dbm
11 self.db = dbm.open(filename, mode, perm)
12
13 def __repr__(self):
14 s = ''
15 for key in self.keys():
16 t = repr(key) + ': ' + repr(self[key])
17 if s: t = ', ' + t
18 s = s + t
19 return '{' + s + '}'
20
21 def __len__(self):
22 return len(self.db)
23
24 def __getitem__(self, key):
25 return eval(self.db[repr(key)])
26
27 def __setitem__(self, key, value):
28 self.db[repr(key)] = repr(value)
29
30 def __delitem__(self, key):
31 del self.db[repr(key)]
32
33 def keys(self):
34 res = []
35 for key in self.db.keys():
36 res.append(eval(key))
37 return res
38
39 def has_key(self, key):
40 return self.db.has_key(repr(key))
41
42
43def test():
44 d = Dbm('@dbm', 'rw', 0600)
45 print d
46 while 1:
47 try:
48 key = input('key: ')
49 if d.has_key(key):
50 value = d[key]
51 print 'currently:', value
52 value = input('value: ')
53 if value == None:
54 del d[key]
55 else:
56 d[key] = value
57 except KeyboardInterrupt:
58 print ''
59 print d
60 except EOFError:
61 print '[eof]'
62 break
63 print d
64
65
66test()
sys/src/cmd/python/Demo/classes/README+13−0
@@ -0,0 +1,13 @@
1Examples of classes that implement special operators (see reference manual):
2
3Complex.py Complex numbers
4Dates.py Date manipulation package by Tim Peters
5Dbm.py Wrapper around built-in dbm, supporting arbitrary values
6Range.py Example of a generator: re-implement built-in range()
7Rat.py Rational numbers
8Rev.py Yield the reverse of a sequence
9Vec.py A simple vector class
10bitvec.py A bit-vector class by Jan-Hein B\"uhrman
11
12(For straightforward examples of basic class features, such as use of
13methods and inheritance, see the library code.)
sys/src/cmd/python/Demo/classes/Range.py+93−0
@@ -0,0 +1,93 @@
1"""Example of a generator: re-implement the built-in range function
2without actually constructing the list of values.
3
4OldStyleRange is coded in the way required to work in a 'for' loop before
5iterators were introduced into the language; using __getitem__ and __len__ .
6
7"""
8def handleargs(arglist):
9 """Take list of arguments and extract/create proper start, stop, and step
10 values and return in a tuple"""
11 try:
12 if len(arglist) == 1:
13 return 0, int(arglist[0]), 1
14 elif len(arglist) == 2:
15 return int(arglist[0]), int(arglist[1]), 1
16 elif len(arglist) == 3:
17 if arglist[2] == 0:
18 raise ValueError("step argument must not be zero")
19 return tuple(int(x) for x in arglist)
20 else:
21 raise TypeError("range() accepts 1-3 arguments, given", len(arglist))
22 except TypeError:
23 raise TypeError("range() arguments must be numbers or strings "
24 "representing numbers")
25
26def genrange(*a):
27 """Function to implement 'range' as a generator"""
28 start, stop, step = handleargs(a)
29 value = start
30 while value < stop:
31 yield value
32 value += step
33
34class oldrange:
35 """Class implementing a range object.
36 To the user the instances feel like immutable sequences
37 (and you can't concatenate or slice them)
38
39 Done using the old way (pre-iterators; __len__ and __getitem__) to have an
40 object be used by a 'for' loop.
41
42 """
43
44 def __init__(self, *a):
45 """ Initialize start, stop, and step values along with calculating the
46 nubmer of values (what __len__ will return) in the range"""
47 self.start, self.stop, self.step = handleargs(a)
48 self.len = max(0, (self.stop - self.start) // self.step)
49
50 def __repr__(self):
51 """implement repr(x) which is also used by print"""
52 return 'range(%r, %r, %r)' % (self.start, self.stop, self.step)
53
54 def __len__(self):
55 """implement len(x)"""
56 return self.len
57
58 def __getitem__(self, i):
59 """implement x[i]"""
60 if 0 <= i <= self.len:
61 return self.start + self.step * i
62 else:
63 raise IndexError, 'range[i] index out of range'
64
65
66def test():
67 import time, __builtin__
68 #Just a quick sanity check
69 correct_result = __builtin__.range(5, 100, 3)
70 oldrange_result = list(oldrange(5, 100, 3))
71 genrange_result = list(genrange(5, 100, 3))
72 if genrange_result != correct_result or oldrange_result != correct_result:
73 raise Exception("error in implementation:\ncorrect = %s"
74 "\nold-style = %s\ngenerator = %s" %
75 (correct_result, oldrange_result, genrange_result))
76 print "Timings for range(1000):"
77 t1 = time.time()
78 for i in oldrange(1000):
79 pass
80 t2 = time.time()
81 for i in genrange(1000):
82 pass
83 t3 = time.time()
84 for i in __builtin__.range(1000):
85 pass
86 t4 = time.time()
87 print t2-t1, 'sec (old-style class)'
88 print t3-t2, 'sec (generator)'
89 print t4-t3, 'sec (built-in)'
90
91
92if __name__ == '__main__':
93 test()
sys/src/cmd/python/Demo/classes/Rat.py+310−0
@@ -0,0 +1,310 @@
1'''\
2This module implements rational numbers.
3
4The entry point of this module is the function
5 rat(numerator, denominator)
6If either numerator or denominator is of an integral or rational type,
7the result is a rational number, else, the result is the simplest of
8the types float and complex which can hold numerator/denominator.
9If denominator is omitted, it defaults to 1.
10Rational numbers can be used in calculations with any other numeric
11type. The result of the calculation will be rational if possible.
12
13There is also a test function with calling sequence
14 test()
15The documentation string of the test function contains the expected
16output.
17'''
18
19# Contributed by Sjoerd Mullender
20
21from types import *
22
23def gcd(a, b):
24 '''Calculate the Greatest Common Divisor.'''
25 while b:
26 a, b = b, a%b
27 return a
28
29def rat(num, den = 1):
30 # must check complex before float
31 if isinstance(num, complex) or isinstance(den, complex):
32 # numerator or denominator is complex: return a complex
33 return complex(num) / complex(den)
34 if isinstance(num, float) or isinstance(den, float):
35 # numerator or denominator is float: return a float
36 return float(num) / float(den)
37 # otherwise return a rational
38 return Rat(num, den)
39
40class Rat:
41 '''This class implements rational numbers.'''
42
43 def __init__(self, num, den = 1):
44 if den == 0:
45 raise ZeroDivisionError, 'rat(x, 0)'
46
47 # normalize
48
49 # must check complex before float
50 if (isinstance(num, complex) or
51 isinstance(den, complex)):
52 # numerator or denominator is complex:
53 # normalized form has denominator == 1+0j
54 self.__num = complex(num) / complex(den)
55 self.__den = complex(1)
56 return
57 if isinstance(num, float) or isinstance(den, float):
58 # numerator or denominator is float:
59 # normalized form has denominator == 1.0
60 self.__num = float(num) / float(den)
61 self.__den = 1.0
62 return
63 if (isinstance(num, self.__class__) or
64 isinstance(den, self.__class__)):
65 # numerator or denominator is rational
66 new = num / den
67 if not isinstance(new, self.__class__):
68 self.__num = new
69 if isinstance(new, complex):
70 self.__den = complex(1)
71 else:
72 self.__den = 1.0
73 else:
74 self.__num = new.__num
75 self.__den = new.__den
76 else:
77 # make sure numerator and denominator don't
78 # have common factors
79 # this also makes sure that denominator > 0
80 g = gcd(num, den)
81 self.__num = num / g
82 self.__den = den / g
83 # try making numerator and denominator of IntType if they fit
84 try:
85 numi = int(self.__num)
86 deni = int(self.__den)
87 except (OverflowError, TypeError):
88 pass
89 else:
90 if self.__num == numi and self.__den == deni:
91 self.__num = numi
92 self.__den = deni
93
94 def __repr__(self):
95 return 'Rat(%s,%s)' % (self.__num, self.__den)
96
97 def __str__(self):
98 if self.__den == 1:
99 return str(self.__num)
100 else:
101 return '(%s/%s)' % (str(self.__num), str(self.__den))
102
103 # a + b
104 def __add__(a, b):
105 try:
106 return rat(a.__num * b.__den + b.__num * a.__den,
107 a.__den * b.__den)
108 except OverflowError:
109 return rat(long(a.__num) * long(b.__den) +
110 long(b.__num) * long(a.__den),
111 long(a.__den) * long(b.__den))
112
113 def __radd__(b, a):
114 return Rat(a) + b
115
116 # a - b
117 def __sub__(a, b):
118 try:
119 return rat(a.__num * b.__den - b.__num * a.__den,
120 a.__den * b.__den)
121 except OverflowError:
122 return rat(long(a.__num) * long(b.__den) -
123 long(b.__num) * long(a.__den),
124 long(a.__den) * long(b.__den))
125
126 def __rsub__(b, a):
127 return Rat(a) - b
128
129 # a * b
130 def __mul__(a, b):
131 try:
132 return rat(a.__num * b.__num, a.__den * b.__den)
133 except OverflowError:
134 return rat(long(a.__num) * long(b.__num),
135 long(a.__den) * long(b.__den))
136
137 def __rmul__(b, a):
138 return Rat(a) * b
139
140 # a / b
141 def __div__(a, b):
142 try:
143 return rat(a.__num * b.__den, a.__den * b.__num)
144 except OverflowError:
145 return rat(long(a.__num) * long(b.__den),
146 long(a.__den) * long(b.__num))
147
148 def __rdiv__(b, a):
149 return Rat(a) / b
150
151 # a % b
152 def __mod__(a, b):
153 div = a / b
154 try:
155 div = int(div)
156 except OverflowError:
157 div = long(div)
158 return a - b * div
159
160 def __rmod__(b, a):
161 return Rat(a) % b
162
163 # a ** b
164 def __pow__(a, b):
165 if b.__den != 1:
166 if isinstance(a.__num, complex):
167 a = complex(a)
168 else:
169 a = float(a)
170 if isinstance(b.__num, complex):
171 b = complex(b)
172 else:
173 b = float(b)
174 return a ** b
175 try:
176 return rat(a.__num ** b.__num, a.__den ** b.__num)
177 except OverflowError:
178 return rat(long(a.__num) ** b.__num,
179 long(a.__den) ** b.__num)
180
181 def __rpow__(b, a):
182 return Rat(a) ** b
183
184 # -a
185 def __neg__(a):
186 try:
187 return rat(-a.__num, a.__den)
188 except OverflowError:
189 # a.__num == sys.maxint
190 return rat(-long(a.__num), a.__den)
191
192 # abs(a)
193 def __abs__(a):
194 return rat(abs(a.__num), a.__den)
195
196 # int(a)
197 def __int__(a):
198 return int(a.__num / a.__den)
199
200 # long(a)
201 def __long__(a):
202 return long(a.__num) / long(a.__den)
203
204 # float(a)
205 def __float__(a):
206 return float(a.__num) / float(a.__den)
207
208 # complex(a)
209 def __complex__(a):
210 return complex(a.__num) / complex(a.__den)
211
212 # cmp(a,b)
213 def __cmp__(a, b):
214 diff = Rat(a - b)
215 if diff.__num < 0:
216 return -1
217 elif diff.__num > 0:
218 return 1
219 else:
220 return 0
221
222 def __rcmp__(b, a):
223 return cmp(Rat(a), b)
224
225 # a != 0
226 def __nonzero__(a):
227 return a.__num != 0
228
229 # coercion
230 def __coerce__(a, b):
231 return a, Rat(b)
232
233def test():
234 '''\
235 Test function for rat module.
236
237 The expected output is (module some differences in floating
238 precission):
239 -1
240 -1
241 0 0L 0.1 (0.1+0j)
242 [Rat(1,2), Rat(-3,10), Rat(1,25), Rat(1,4)]
243 [Rat(-3,10), Rat(1,25), Rat(1,4), Rat(1,2)]
244 0
245 (11/10)
246 (11/10)
247 1.1
248 OK
249 2 1.5 (3/2) (1.5+1.5j) (15707963/5000000)
250 2 2 2.0 (2+0j)
251
252 4 0 4 1 4 0
253 3.5 0.5 3.0 1.33333333333 2.82842712475 1
254 (7/2) (1/2) 3 (4/3) 2.82842712475 1
255 (3.5+1.5j) (0.5-1.5j) (3+3j) (0.666666666667-0.666666666667j) (1.43248815986+2.43884761145j) 1
256 1.5 1 1.5 (1.5+0j)
257
258 3.5 -0.5 3.0 0.75 2.25 -1
259 3.0 0.0 2.25 1.0 1.83711730709 0
260 3.0 0.0 2.25 1.0 1.83711730709 1
261 (3+1.5j) -1.5j (2.25+2.25j) (0.5-0.5j) (1.50768393746+1.04970907623j) -1
262 (3/2) 1 1.5 (1.5+0j)
263
264 (7/2) (-1/2) 3 (3/4) (9/4) -1
265 3.0 0.0 2.25 1.0 1.83711730709 -1
266 3 0 (9/4) 1 1.83711730709 0
267 (3+1.5j) -1.5j (2.25+2.25j) (0.5-0.5j) (1.50768393746+1.04970907623j) -1
268 (1.5+1.5j) (1.5+1.5j)
269
270 (3.5+1.5j) (-0.5+1.5j) (3+3j) (0.75+0.75j) 4.5j -1
271 (3+1.5j) 1.5j (2.25+2.25j) (1+1j) (1.18235814075+2.85446505899j) 1
272 (3+1.5j) 1.5j (2.25+2.25j) (1+1j) (1.18235814075+2.85446505899j) 1
273 (3+3j) 0j 4.5j (1+0j) (-0.638110484918+0.705394566962j) 0
274 '''
275 print rat(-1L, 1)
276 print rat(1, -1)
277 a = rat(1, 10)
278 print int(a), long(a), float(a), complex(a)
279 b = rat(2, 5)
280 l = [a+b, a-b, a*b, a/b]
281 print l
282 l.sort()
283 print l
284 print rat(0, 1)
285 print a+1
286 print a+1L
287 print a+1.0
288 try:
289 print rat(1, 0)
290 raise SystemError, 'should have been ZeroDivisionError'
291 except ZeroDivisionError:
292 print 'OK'
293 print rat(2), rat(1.5), rat(3, 2), rat(1.5+1.5j), rat(31415926,10000000)
294 list = [2, 1.5, rat(3,2), 1.5+1.5j]
295 for i in list:
296 print i,
297 if not isinstance(i, complex):
298 print int(i), float(i),
299 print complex(i)
300 print
301 for j in list:
302 print i + j, i - j, i * j, i / j, i ** j,
303 if not (isinstance(i, complex) or
304 isinstance(j, complex)):
305 print cmp(i, j)
306 print
307
308
309if __name__ == '__main__':
310 test()
sys/src/cmd/python/Demo/classes/Rev.py+95−0
@@ -0,0 +1,95 @@
1'''
2A class which presents the reverse of a sequence without duplicating it.
3From: "Steven D. Majewski" <sdm7g@elvis.med.virginia.edu>
4
5It works on mutable or inmutable sequences.
6
7>>> chars = list(Rev('Hello World!'))
8>>> print ''.join(chars)
9!dlroW olleH
10
11The .forw is so you can use anonymous sequences in __init__, and still
12keep a reference the forward sequence. )
13If you give it a non-anonymous mutable sequence, the reverse sequence
14will track the updated values. ( but not reassignment! - another
15good reason to use anonymous values in creating the sequence to avoid
16confusion. Maybe it should be change to copy input sequence to break
17the connection completely ? )
18
19>>> nnn = range(3)
20>>> rnn = Rev(nnn)
21>>> for n in rnn: print n
22...
232
241
250
26>>> for n in range(4, 6): nnn.append(n) # update nnn
27...
28>>> for n in rnn: print n # prints reversed updated values
29...
305
314
322
331
340
35>>> nnn = nnn[1:-1]
36>>> nnn
37[1, 2, 4]
38>>> for n in rnn: print n # prints reversed values of old nnn
39...
405
414
422
431
440
45
46#
47>>> WH = Rev('Hello World!')
48>>> print WH.forw, WH.back
49Hello World! !dlroW olleH
50>>> nnn = Rev(range(1, 10))
51>>> print nnn.forw
52[1, 2, 3, 4, 5, 6, 7, 8, 9]
53>>> print nnn.back
54[9, 8, 7, 6, 5, 4, 3, 2, 1]
55
56>>> rrr = Rev(nnn)
57>>> rrr
58<1, 2, 3, 4, 5, 6, 7, 8, 9>
59
60'''
61
62class Rev:
63 def __init__(self, seq):
64 self.forw = seq
65 self.back = self
66
67 def __len__(self):
68 return len(self.forw)
69
70 def __getitem__(self, j):
71 return self.forw[-(j + 1)]
72
73 def __repr__(self):
74 seq = self.forw
75 if isinstance(seq, list):
76 wrap = '[]'
77 sep = ', '
78 elif isinstance(seq, tuple):
79 wrap = '()'
80 sep = ', '
81 elif isinstance(seq, str):
82 wrap = ''
83 sep = ''
84 else:
85 wrap = '<>'
86 sep = ', '
87 outstrs = [str(item) for item in self.back]
88 return wrap[:1] + sep.join(outstrs) + wrap[-1:]
89
90def _test():
91 import doctest, Rev
92 return doctest.testmod(Rev)
93
94if __name__ == "__main__":
95 _test()
sys/src/cmd/python/Demo/classes/Vec.py+54−0
@@ -0,0 +1,54 @@
1# A simple vector class
2
3
4def vec(*v):
5 return Vec(*v)
6
7
8class Vec:
9
10 def __init__(self, *v):
11 self.v = list(v)
12
13 def fromlist(self, v):
14 if not isinstance(v, list):
15 raise TypeError
16 self.v = v[:]
17 return self
18
19 def __repr__(self):
20 return 'vec(' + repr(self.v)[1:-1] + ')'
21
22 def __len__(self):
23 return len(self.v)
24
25 def __getitem__(self, i):
26 return self.v[i]
27
28 def __add__(self, other):
29 # Element-wise addition
30 v = map(lambda x, y: x+y, self, other)
31 return Vec().fromlist(v)
32
33 def __sub__(self, other):
34 # Element-wise subtraction
35 v = map(lambda x, y: x-y, self, other)
36 return Vec().fromlist(v)
37
38 def __mul__(self, scalar):
39 # Multiply by scalar
40 v = map(lambda x: x*scalar, self.v)
41 return Vec().fromlist(v)
42
43
44
45def test():
46 a = vec(1, 2, 3)
47 b = vec(3, 2, 1)
48 print a
49 print b
50 print a+b
51 print a-b
52 print a*3.0
53
54test()
sys/src/cmd/python/Demo/classes/bitvec.py+332−0
@@ -0,0 +1,332 @@
1#
2# this is a rather strict implementation of a bit vector class
3# it is accessed the same way as an array of python-ints, except
4# the value must be 0 or 1
5#
6
7import sys; rprt = sys.stderr.write #for debugging
8
9error = 'bitvec.error'
10
11
12def _check_value(value):
13 if type(value) != type(0) or not 0 <= value < 2:
14 raise error, 'bitvec() items must have int value 0 or 1'
15
16
17import math
18
19def _compute_len(param):
20 mant, l = math.frexp(float(param))
21 bitmask = 1L << l
22 if bitmask <= param:
23 raise 'FATAL', '(param, l) = %r' % ((param, l),)
24 while l:
25 bitmask = bitmask >> 1
26 if param & bitmask:
27 break
28 l = l - 1
29 return l
30
31
32def _check_key(len, key):
33 if type(key) != type(0):
34 raise TypeError, 'sequence subscript not int'
35 if key < 0:
36 key = key + len
37 if not 0 <= key < len:
38 raise IndexError, 'list index out of range'
39 return key
40
41def _check_slice(len, i, j):
42 #the type is ok, Python already checked that
43 i, j = max(i, 0), min(len, j)
44 if i > j:
45 i = j
46 return i, j
47
48
49class BitVec:
50
51 def __init__(self, *params):
52 self._data = 0L
53 self._len = 0
54 if not len(params):
55 pass
56 elif len(params) == 1:
57 param, = params
58 if type(param) == type([]):
59 value = 0L
60 bit_mask = 1L
61 for item in param:
62 # strict check
63 #_check_value(item)
64 if item:
65 value = value | bit_mask
66 bit_mask = bit_mask << 1
67 self._data = value
68 self._len = len(param)
69 elif type(param) == type(0L):
70 if param < 0:
71 raise error, 'bitvec() can\'t handle negative longs'
72 self._data = param
73 self._len = _compute_len(param)
74 else:
75 raise error, 'bitvec() requires array or long parameter'
76 elif len(params) == 2:
77 param, length = params
78 if type(param) == type(0L):
79 if param < 0:
80 raise error, \
81 'can\'t handle negative longs'
82 self._data = param
83 if type(length) != type(0):
84 raise error, 'bitvec()\'s 2nd parameter must be int'
85 computed_length = _compute_len(param)
86 if computed_length > length:
87 print 'warning: bitvec() value is longer than the length indicates, truncating value'
88 self._data = self._data & \
89 ((1L << length) - 1)
90 self._len = length
91 else:
92 raise error, 'bitvec() requires array or long parameter'
93 else:
94 raise error, 'bitvec() requires 0 -- 2 parameter(s)'
95
96
97 def append(self, item):
98 #_check_value(item)
99 #self[self._len:self._len] = [item]
100 self[self._len:self._len] = \
101 BitVec(long(not not item), 1)
102
103
104 def count(self, value):
105 #_check_value(value)
106 if value:
107 data = self._data
108 else:
109 data = (~self)._data
110 count = 0
111 while data:
112 data, count = data >> 1, count + (data & 1 != 0)
113 return count
114
115
116 def index(self, value):
117 #_check_value(value):
118 if value:
119 data = self._data
120 else:
121 data = (~self)._data
122 index = 0
123 if not data:
124 raise ValueError, 'list.index(x): x not in list'
125 while not (data & 1):
126 data, index = data >> 1, index + 1
127 return index
128
129
130 def insert(self, index, item):
131 #_check_value(item)
132 #self[index:index] = [item]
133 self[index:index] = BitVec(long(not not item), 1)
134
135
136 def remove(self, value):
137 del self[self.index(value)]
138
139
140 def reverse(self):
141 #ouch, this one is expensive!
142 #for i in self._len>>1: self[i], self[l-i] = self[l-i], self[i]
143 data, result = self._data, 0L
144 for i in range(self._len):
145 if not data:
146 result = result << (self._len - i)
147 break
148 result, data = (result << 1) | (data & 1), data >> 1
149 self._data = result
150
151
152 def sort(self):
153 c = self.count(1)
154 self._data = ((1L << c) - 1) << (self._len - c)
155
156
157 def copy(self):
158 return BitVec(self._data, self._len)
159
160
161 def seq(self):
162 result = []
163 for i in self:
164 result.append(i)
165 return result
166
167
168 def __repr__(self):
169 ##rprt('<bitvec class instance object>.' + '__repr__()\n')
170 return 'bitvec(%r, %r)' % (self._data, self._len)
171
172 def __cmp__(self, other, *rest):
173 #rprt('%r.__cmp__%r\n' % (self, (other,) + rest))
174 if type(other) != type(self):
175 other = apply(bitvec, (other, ) + rest)
176 #expensive solution... recursive binary, with slicing
177 length = self._len
178 if length == 0 or other._len == 0:
179 return cmp(length, other._len)
180 if length != other._len:
181 min_length = min(length, other._len)
182 return cmp(self[:min_length], other[:min_length]) or \
183 cmp(self[min_length:], other[min_length:])
184 #the lengths are the same now...
185 if self._data == other._data:
186 return 0
187 if length == 1:
188 return cmp(self[0], other[0])
189 else:
190 length = length >> 1
191 return cmp(self[:length], other[:length]) or \
192 cmp(self[length:], other[length:])
193
194
195 def __len__(self):
196 #rprt('%r.__len__()\n' % (self,))
197 return self._len
198
199 def __getitem__(self, key):
200 #rprt('%r.__getitem__(%r)\n' % (self, key))
201 key = _check_key(self._len, key)
202 return self._data & (1L << key) != 0
203
204 def __setitem__(self, key, value):
205 #rprt('%r.__setitem__(%r, %r)\n' % (self, key, value))
206 key = _check_key(self._len, key)
207 #_check_value(value)
208 if value:
209 self._data = self._data | (1L << key)
210 else:
211 self._data = self._data & ~(1L << key)
212
213 def __delitem__(self, key):
214 #rprt('%r.__delitem__(%r)\n' % (self, key))
215 key = _check_key(self._len, key)
216 #el cheapo solution...
217 self._data = self[:key]._data | self[key+1:]._data >> key
218 self._len = self._len - 1
219
220 def __getslice__(self, i, j):
221 #rprt('%r.__getslice__(%r, %r)\n' % (self, i, j))
222 i, j = _check_slice(self._len, i, j)
223 if i >= j:
224 return BitVec(0L, 0)
225 if i:
226 ndata = self._data >> i
227 else:
228 ndata = self._data
229 nlength = j - i
230 if j != self._len:
231 #we'll have to invent faster variants here
232 #e.g. mod_2exp
233 ndata = ndata & ((1L << nlength) - 1)
234 return BitVec(ndata, nlength)
235
236 def __setslice__(self, i, j, sequence, *rest):
237 #rprt('%s.__setslice__%r\n' % (self, (i, j, sequence) + rest))
238 i, j = _check_slice(self._len, i, j)
239 if type(sequence) != type(self):
240 sequence = apply(bitvec, (sequence, ) + rest)
241 #sequence is now of our own type
242 ls_part = self[:i]
243 ms_part = self[j:]
244 self._data = ls_part._data | \
245 ((sequence._data | \
246 (ms_part._data << sequence._len)) << ls_part._len)
247 self._len = self._len - j + i + sequence._len
248
249 def __delslice__(self, i, j):
250 #rprt('%r.__delslice__(%r, %r)\n' % (self, i, j))
251 i, j = _check_slice(self._len, i, j)
252 if i == 0 and j == self._len:
253 self._data, self._len = 0L, 0
254 elif i < j:
255 self._data = self[:i]._data | (self[j:]._data >> i)
256 self._len = self._len - j + i
257
258 def __add__(self, other):
259 #rprt('%r.__add__(%r)\n' % (self, other))
260 retval = self.copy()
261 retval[self._len:self._len] = other
262 return retval
263
264 def __mul__(self, multiplier):
265 #rprt('%r.__mul__(%r)\n' % (self, multiplier))
266 if type(multiplier) != type(0):
267 raise TypeError, 'sequence subscript not int'
268 if multiplier <= 0:
269 return BitVec(0L, 0)
270 elif multiplier == 1:
271 return self.copy()
272 #handle special cases all 0 or all 1...
273 if self._data == 0L:
274 return BitVec(0L, self._len * multiplier)
275 elif (~self)._data == 0L:
276 return ~BitVec(0L, self._len * multiplier)
277 #otherwise el cheapo again...
278 retval = BitVec(0L, 0)
279 while multiplier:
280 retval, multiplier = retval + self, multiplier - 1
281 return retval
282
283 def __and__(self, otherseq, *rest):
284 #rprt('%r.__and__%r\n' % (self, (otherseq,) + rest))
285 if type(otherseq) != type(self):
286 otherseq = apply(bitvec, (otherseq, ) + rest)
287 #sequence is now of our own type
288 return BitVec(self._data & otherseq._data, \
289 min(self._len, otherseq._len))
290
291
292 def __xor__(self, otherseq, *rest):
293 #rprt('%r.__xor__%r\n' % (self, (otherseq,) + rest))
294 if type(otherseq) != type(self):
295 otherseq = apply(bitvec, (otherseq, ) + rest)
296 #sequence is now of our own type
297 return BitVec(self._data ^ otherseq._data, \
298 max(self._len, otherseq._len))
299
300
301 def __or__(self, otherseq, *rest):
302 #rprt('%r.__or__%r\n' % (self, (otherseq,) + rest))
303 if type(otherseq) != type(self):
304 otherseq = apply(bitvec, (otherseq, ) + rest)
305 #sequence is now of our own type
306 return BitVec(self._data | otherseq._data, \
307 max(self._len, otherseq._len))
308
309
310 def __invert__(self):
311 #rprt('%r.__invert__()\n' % (self,))
312 return BitVec(~self._data & ((1L << self._len) - 1), \
313 self._len)
314
315 def __coerce__(self, otherseq, *rest):
316 #needed for *some* of the arithmetic operations
317 #rprt('%r.__coerce__%r\n' % (self, (otherseq,) + rest))
318 if type(otherseq) != type(self):
319 otherseq = apply(bitvec, (otherseq, ) + rest)
320 return self, otherseq
321
322 def __int__(self):
323 return int(self._data)
324
325 def __long__(self):
326 return long(self._data)
327
328 def __float__(self):
329 return float(self._data)
330
331
332bitvec = BitVec
sys/src/cmd/python/Demo/comparisons/README+60−0
@@ -0,0 +1,60 @@
1Subject: Re: What language would you use?
2From: Tom Christiansen <tchrist@mox.perl.com>
3Date: 6 Nov 1994 15:14:51 GMT
4Newsgroups: comp.lang.python,comp.lang.tcl,comp.lang.scheme,comp.lang.misc,comp.lang.perl
5Message-Id: <39irtb$3t4@csnews.cs.Colorado.EDU>
6References: <39b7ha$j9v@zeno.nscf.org> <39hhjp$lgn@csnews.cs.Colorado.EDU> <39hvsu$dus@mathserv.mps.ohio-state.edu>
7
8[...]
9If you're really into benchmarks, I'd love it if someone were to code up
10the following problems in tcl, python, and scheme (and whatever else you'd
11like). Separate versions (one optimized for speed, one for beauty :-) are
12ok. Post your code so we can time it on our own systems.
13
140) Factorial Test (numerics and function calls)
15
16 (we did this already)
17
181) Regular Expressions Test
19
20 Read a file of (extended per egrep) regular expressions (one per line),
21 and apply those to all files whose names are listed on the command line.
22 Basically, an 'egrep -f' simulator. Test it with 20 "vt100" patterns
23 against a five /etc/termcap files. Tests using more elaborate patters
24 would also be interesting. Your code should not break if given hundreds
25 of regular expressions or binary files to scan.
26
272) Sorting Test
28
29 Sort an input file that consists of lines like this
30
31 var1=23 other=14 ditto=23 fred=2
32
33 such that each output line is sorted WRT to the number. Order
34 of output lines does not change. Resolve collisions using the
35 variable name. e.g.
36
37 fred=2 other=14 ditto=23 var1=23
38
39 Lines may be up to several kilobytes in length and contain
40 zillions of variables.
41
423) System Test
43
44 Given a list of directories, report any bogus symbolic links contained
45 anywhere in those subtrees. A bogus symbolic link is one that cannot
46 be resolved because it points to a nonexistent or otherwise
47 unresolvable file. Do *not* use an external find executable.
48 Directories may be very very deep. Print a warning immediately if the
49 system you're running on doesn't support symbolic links.
50
51
52I'll post perl solutions if people post the others.
53
54
55--tom
56--
57Tom Christiansen Perl Consultant, Gamer, Hiker tchrist@mox.perl.com
58
59 "But Billy! A *small* allowance prepares you for a lifetime of small
60 salaries and for your Social Security payments." --Family Circus
sys/src/cmd/python/Demo/comparisons/patterns+4−0
@@ -0,0 +1,4 @@
1^def
2^class
3^import
4^from
sys/src/cmd/python/Demo/comparisons/regextest.py+47−0
@@ -0,0 +1,47 @@
1#! /usr/bin/env python
2
3# 1) Regular Expressions Test
4#
5# Read a file of (extended per egrep) regular expressions (one per line),
6# and apply those to all files whose names are listed on the command line.
7# Basically, an 'egrep -f' simulator. Test it with 20 "vt100" patterns
8# against a five /etc/termcap files. Tests using more elaborate patters
9# would also be interesting. Your code should not break if given hundreds
10# of regular expressions or binary files to scan.
11
12# This implementation:
13# - combines all patterns into a single one using ( ... | ... | ... )
14# - reads patterns from stdin, scans files given as command line arguments
15# - produces output in the format <file>:<lineno>:<line>
16# - is only about 2.5 times as slow as egrep (though I couldn't run
17# Tom's test -- this system, a vanilla SGI, only has /etc/terminfo)
18
19import string
20import sys
21import re
22
23def main():
24 pats = map(chomp, sys.stdin.readlines())
25 bigpat = '(' + '|'.join(pats) + ')'
26 prog = re.compile(bigpat)
27
28 for file in sys.argv[1:]:
29 try:
30 fp = open(file, 'r')
31 except IOError, msg:
32 print "%s: %s" % (file, msg)
33 continue
34 lineno = 0
35 while 1:
36 line = fp.readline()
37 if not line:
38 break
39 lineno = lineno + 1
40 if prog.search(line):
41 print "%s:%s:%s" % (file, lineno, line),
42
43def chomp(s):
44 return s.rstrip('\n')
45
46if __name__ == '__main__':
47 main()
sys/src/cmd/python/Demo/comparisons/sortingtest.py+51−0
@@ -0,0 +1,51 @@
1#! /usr/bin/env python
2
3# 2) Sorting Test
4#
5# Sort an input file that consists of lines like this
6#
7# var1=23 other=14 ditto=23 fred=2
8#
9# such that each output line is sorted WRT to the number. Order
10# of output lines does not change. Resolve collisions using the
11# variable name. e.g.
12#
13# fred=2 other=14 ditto=23 var1=23
14#
15# Lines may be up to several kilobytes in length and contain
16# zillions of variables.
17
18# This implementation:
19# - Reads stdin, writes stdout
20# - Uses any amount of whitespace to separate fields
21# - Allows signed numbers
22# - Treats illegally formatted fields as field=0
23# - Outputs the sorted fields with exactly one space between them
24# - Handles blank input lines correctly
25
26import re
27import string
28import sys
29
30def main():
31 prog = re.compile('^(.*)=([-+]?[0-9]+)')
32 def makekey(item, prog=prog):
33 match = prog.match(item)
34 if match:
35 var, num = match.group(1, 2)
36 return string.atoi(num), var
37 else:
38 # Bad input -- pretend it's a var with value 0
39 return 0, item
40 while 1:
41 line = sys.stdin.readline()
42 if not line:
43 break
44 items = line.split()
45 items = map(makekey, items)
46 items.sort()
47 for num, var in items:
48 print "%s=%s" % (var, num),
49 print
50
51main()
sys/src/cmd/python/Demo/comparisons/systemtest.py+74−0
@@ -0,0 +1,74 @@
1#! /usr/bin/env python
2
3# 3) System Test
4#
5# Given a list of directories, report any bogus symbolic links contained
6# anywhere in those subtrees. A bogus symbolic link is one that cannot
7# be resolved because it points to a nonexistent or otherwise
8# unresolvable file. Do *not* use an external find executable.
9# Directories may be very very deep. Print a warning immediately if the
10# system you're running on doesn't support symbolic links.
11
12# This implementation:
13# - takes one optional argument, using the current directory as default
14# - uses chdir to increase performance
15# - sorts the names per directory
16# - prints output lines of the form "path1 -> path2" as it goes
17# - prints error messages about directories it can't list or chdir into
18
19import os
20import sys
21from stat import *
22
23def main():
24 try:
25 # Note: can't test for presence of lstat -- it's always there
26 dummy = os.readlink
27 except AttributeError:
28 print "This system doesn't have symbolic links"
29 sys.exit(0)
30 if sys.argv[1:]:
31 prefix = sys.argv[1]
32 else:
33 prefix = ''
34 if prefix:
35 os.chdir(prefix)
36 if prefix[-1:] != '/': prefix = prefix + '/'
37 reportboguslinks(prefix)
38 else:
39 reportboguslinks('')
40
41def reportboguslinks(prefix):
42 try:
43 names = os.listdir('.')
44 except os.error, msg:
45 print "%s%s: can't list: %s" % (prefix, '.', msg)
46 return
47 names.sort()
48 for name in names:
49 if name == os.curdir or name == os.pardir:
50 continue
51 try:
52 mode = os.lstat(name)[ST_MODE]
53 except os.error:
54 print "%s%s: can't stat: %s" % (prefix, name, msg)
55 continue
56 if S_ISLNK(mode):
57 try:
58 os.stat(name)
59 except os.error:
60 print "%s%s -> %s" % \
61 (prefix, name, os.readlink(name))
62 elif S_ISDIR(mode):
63 try:
64 os.chdir(name)
65 except os.error, msg:
66 print "%s%s: can't chdir: %s" % \
67 (prefix, name, msg)
68 continue
69 try:
70 reportboguslinks(prefix + name + '/')
71 finally:
72 os.chdir('..')
73
74main()
sys/src/cmd/python/Demo/curses/README+25−0
@@ -0,0 +1,25 @@
1This is a collection of demos and tests for the curses module.
2
3ncurses demos
4=============
5
6These demos are converted from the C versions in the ncurses
7distribution, and were contributed by Thomas Gellekum <tg@FreeBSD.org>
8I didn't strive for a `pythonic' style, but bluntly copied the
9originals. I won't attempt to `beautify' the program anytime soon, but
10I wouldn't mind someone else making an effort in that direction, of
11course.
12
13ncurses.py -- currently only a panels demo
14rain.py -- raindrops keep falling on my desktop
15tclock.py -- ASCII clock, by Howard Jones
16xmas.py -- I'm dreaming of an ASCII christmas
17
18Please submit bugfixes and new contributions to the Python bug tracker.
19
20
21Other demos
22===========
23
24life.py -- Simple game of Life
25repeat.py -- Repeatedly execute a shell command (like watch(1))
sys/src/cmd/python/Demo/curses/life.py+216−0
@@ -0,0 +1,216 @@
1#!/usr/bin/env python
2# life.py -- A curses-based version of Conway's Game of Life.
3# Contributed by AMK
4#
5# An empty board will be displayed, and the following commands are available:
6# E : Erase the board
7# R : Fill the board randomly
8# S : Step for a single generation
9# C : Update continuously until a key is struck
10# Q : Quit
11# Cursor keys : Move the cursor around the board
12# Space or Enter : Toggle the contents of the cursor's position
13#
14# TODO :
15# Support the mouse
16# Use colour if available
17# Make board updates faster
18#
19
20import random, string, traceback
21import curses
22
23class LifeBoard:
24 """Encapsulates a Life board
25
26 Attributes:
27 X,Y : horizontal and vertical size of the board
28 state : dictionary mapping (x,y) to 0 or 1
29
30 Methods:
31 display(update_board) -- If update_board is true, compute the
32 next generation. Then display the state
33 of the board and refresh the screen.
34 erase() -- clear the entire board
35 makeRandom() -- fill the board randomly
36 set(y,x) -- set the given cell to Live; doesn't refresh the screen
37 toggle(y,x) -- change the given cell from live to dead, or vice
38 versa, and refresh the screen display
39
40 """
41 def __init__(self, scr, char=ord('*')):
42 """Create a new LifeBoard instance.
43
44 scr -- curses screen object to use for display
45 char -- character used to render live cells (default: '*')
46 """
47 self.state = {}
48 self.scr = scr
49 Y, X = self.scr.getmaxyx()
50 self.X, self.Y = X-2, Y-2-1
51 self.char = char
52 self.scr.clear()
53
54 # Draw a border around the board
55 border_line = '+'+(self.X*'-')+'+'
56 self.scr.addstr(0, 0, border_line)
57 self.scr.addstr(self.Y+1,0, border_line)
58 for y in range(0, self.Y):
59 self.scr.addstr(1+y, 0, '|')
60 self.scr.addstr(1+y, self.X+1, '|')
61 self.scr.refresh()
62
63 def set(self, y, x):
64 """Set a cell to the live state"""
65 if x<0 or self.X<=x or y<0 or self.Y<=y:
66 raise ValueError, "Coordinates out of range %i,%i"% (y,x)
67 self.state[x,y] = 1
68
69 def toggle(self, y, x):
70 """Toggle a cell's state between live and dead"""
71 if x<0 or self.X<=x or y<0 or self.Y<=y:
72 raise ValueError, "Coordinates out of range %i,%i"% (y,x)
73 if self.state.has_key( (x,y) ):
74 del self.state[x,y]
75 self.scr.addch(y+1, x+1, ' ')
76 else:
77 self.state[x,y] = 1
78 self.scr.addch(y+1, x+1, self.char)
79 self.scr.refresh()
80
81 def erase(self):
82 """Clear the entire board and update the board display"""
83 self.state = {}
84 self.display(update_board=False)
85
86 def display(self, update_board=True):
87 """Display the whole board, optionally computing one generation"""
88 M,N = self.X, self.Y
89 if not update_board:
90 for i in range(0, M):
91 for j in range(0, N):
92 if self.state.has_key( (i,j) ):
93 self.scr.addch(j+1, i+1, self.char)
94 else:
95 self.scr.addch(j+1, i+1, ' ')
96 self.scr.refresh()
97 return
98
99 d = {}
100 self.boring = 1
101 for i in range(0, M):
102 L = range( max(0, i-1), min(M, i+2) )
103 for j in range(0, N):
104 s = 0
105 live = self.state.has_key( (i,j) )
106 for k in range( max(0, j-1), min(N, j+2) ):
107 for l in L:
108 if self.state.has_key( (l,k) ):
109 s += 1
110 s -= live
111 if s == 3:
112 # Birth
113 d[i,j] = 1
114 self.scr.addch(j+1, i+1, self.char)
115 if not live: self.boring = 0
116 elif s == 2 and live: d[i,j] = 1 # Survival
117 elif live:
118 # Death
119 self.scr.addch(j+1, i+1, ' ')
120 self.boring = 0
121 self.state = d
122 self.scr.refresh()
123
124 def makeRandom(self):
125 "Fill the board with a random pattern"
126 self.state = {}
127 for i in range(0, self.X):
128 for j in range(0, self.Y):
129 if random.random() > 0.5:
130 self.set(j,i)
131
132
133def erase_menu(stdscr, menu_y):
134 "Clear the space where the menu resides"
135 stdscr.move(menu_y, 0)
136 stdscr.clrtoeol()
137 stdscr.move(menu_y+1, 0)
138 stdscr.clrtoeol()
139
140def display_menu(stdscr, menu_y):
141 "Display the menu of possible keystroke commands"
142 erase_menu(stdscr, menu_y)
143 stdscr.addstr(menu_y, 4,
144 'Use the cursor keys to move, and space or Enter to toggle a cell.')
145 stdscr.addstr(menu_y+1, 4,
146 'E)rase the board, R)andom fill, S)tep once or C)ontinuously, Q)uit')
147
148def keyloop(stdscr):
149 # Clear the screen and display the menu of keys
150 stdscr.clear()
151 stdscr_y, stdscr_x = stdscr.getmaxyx()
152 menu_y = (stdscr_y-3)-1
153 display_menu(stdscr, menu_y)
154
155 # Allocate a subwindow for the Life board and create the board object
156 subwin = stdscr.subwin(stdscr_y-3, stdscr_x, 0, 0)
157 board = LifeBoard(subwin, char=ord('*'))
158 board.display(update_board=False)
159
160 # xpos, ypos are the cursor's position
161 xpos, ypos = board.X/2, board.Y/2
162
163 # Main loop:
164 while (1):
165 stdscr.move(1+ypos, 1+xpos) # Move the cursor
166 c = stdscr.getch() # Get a keystroke
167 if 0<c<256:
168 c = chr(c)
169 if c in ' \n':
170 board.toggle(ypos, xpos)
171 elif c in 'Cc':
172 erase_menu(stdscr, menu_y)
173 stdscr.addstr(menu_y, 6, ' Hit any key to stop continuously '
174 'updating the screen.')
175 stdscr.refresh()
176 # Activate nodelay mode; getch() will return -1
177 # if no keystroke is available, instead of waiting.
178 stdscr.nodelay(1)
179 while (1):
180 c = stdscr.getch()
181 if c != -1:
182 break
183 stdscr.addstr(0,0, '/')
184 stdscr.refresh()
185 board.display()
186 stdscr.addstr(0,0, '+')
187 stdscr.refresh()
188
189 stdscr.nodelay(0) # Disable nodelay mode
190 display_menu(stdscr, menu_y)
191
192 elif c in 'Ee':
193 board.erase()
194 elif c in 'Qq':
195 break
196 elif c in 'Rr':
197 board.makeRandom()
198 board.display(update_board=False)
199 elif c in 'Ss':
200 board.display()
201 else: pass # Ignore incorrect keys
202 elif c == curses.KEY_UP and ypos>0: ypos -= 1
203 elif c == curses.KEY_DOWN and ypos<board.Y-1: ypos += 1
204 elif c == curses.KEY_LEFT and xpos>0: xpos -= 1
205 elif c == curses.KEY_RIGHT and xpos<board.X-1: xpos += 1
206 else:
207 # Ignore incorrect keys
208 pass
209
210
211def main(stdscr):
212 keyloop(stdscr) # Enter the main loop
213
214
215if __name__ == '__main__':
216 curses.wrapper(main)
sys/src/cmd/python/Demo/curses/ncurses.py+273−0
@@ -0,0 +1,273 @@
1#!/usr/bin/env python
2#
3# $Id: ncurses.py 36559 2004-07-18 05:56:09Z tim_one $
4#
5# (n)curses exerciser in Python, an interactive test for the curses
6# module. Currently, only the panel demos are ported.
7
8import curses
9from curses import panel
10
11def wGetchar(win = None):
12 if win == None: win = stdscr
13 return win.getch()
14
15def Getchar():
16 wGetchar()
17
18#
19# Panels tester
20#
21def wait_a_while():
22 if nap_msec == 1:
23 Getchar()
24 else:
25 curses.napms(nap_msec)
26
27def saywhat(text):
28 stdscr.move(curses.LINES - 1, 0)
29 stdscr.clrtoeol()
30 stdscr.addstr(text)
31
32def mkpanel(color, rows, cols, tly, tlx):
33 win = curses.newwin(rows, cols, tly, tlx)
34 pan = panel.new_panel(win)
35 if curses.has_colors():
36 if color == curses.COLOR_BLUE:
37 fg = curses.COLOR_WHITE
38 else:
39 fg = curses.COLOR_BLACK
40 bg = color
41 curses.init_pair(color, fg, bg)
42 win.bkgdset(ord(' '), curses.color_pair(color))
43 else:
44 win.bkgdset(ord(' '), curses.A_BOLD)
45
46 return pan
47
48def pflush():
49 panel.update_panels()
50 curses.doupdate()
51
52def fill_panel(pan):
53 win = pan.window()
54 num = pan.userptr()[1]
55
56 win.move(1, 1)
57 win.addstr("-pan%c-" % num)
58 win.clrtoeol()
59 win.box()
60
61 maxy, maxx = win.getmaxyx()
62 for y in range(2, maxy - 1):
63 for x in range(1, maxx - 1):
64 win.move(y, x)
65 win.addch(num)
66
67def demo_panels(win):
68 global stdscr, nap_msec, mod
69 stdscr = win
70 nap_msec = 1
71 mod = ["test", "TEST", "(**)", "*()*", "<-->", "LAST"]
72
73 stdscr.refresh()
74
75 for y in range(0, curses.LINES - 1):
76 for x in range(0, curses.COLS):
77 stdscr.addstr("%d" % ((y + x) % 10))
78 for y in range(0, 1):
79 p1 = mkpanel(curses.COLOR_RED,
80 curses.LINES / 2 - 2,
81 curses.COLS / 8 + 1,
82 0,
83 0)
84 p1.set_userptr("p1")
85
86 p2 = mkpanel(curses.COLOR_GREEN,
87 curses.LINES / 2 + 1,
88 curses.COLS / 7,
89 curses.LINES / 4,
90 curses.COLS / 10)
91 p2.set_userptr("p2")
92
93 p3 = mkpanel(curses.COLOR_YELLOW,
94 curses.LINES / 4,
95 curses.COLS / 10,
96 curses.LINES / 2,
97 curses.COLS / 9)
98 p3.set_userptr("p3")
99
100 p4 = mkpanel(curses.COLOR_BLUE,
101 curses.LINES / 2 - 2,
102 curses.COLS / 8,
103 curses.LINES / 2 - 2,
104 curses.COLS / 3)
105 p4.set_userptr("p4")
106
107 p5 = mkpanel(curses.COLOR_MAGENTA,
108 curses.LINES / 2 - 2,
109 curses.COLS / 8,
110 curses.LINES / 2,
111 curses.COLS / 2 - 2)
112 p5.set_userptr("p5")
113
114 fill_panel(p1)
115 fill_panel(p2)
116 fill_panel(p3)
117 fill_panel(p4)
118 fill_panel(p5)
119 p4.hide()
120 p5.hide()
121 pflush()
122 saywhat("press any key to continue")
123 wait_a_while()
124
125 saywhat("h3 s1 s2 s4 s5;press any key to continue")
126 p1.move(0, 0)
127 p3.hide()
128 p1.show()
129 p2.show()
130 p4.show()
131 p5.show()
132 pflush()
133 wait_a_while()
134
135 saywhat("s1; press any key to continue")
136 p1.show()
137 pflush()
138 wait_a_while()
139
140 saywhat("s2; press any key to continue")
141 p2.show()
142 pflush()
143 wait_a_while()
144
145 saywhat("m2; press any key to continue")
146 p2.move(curses.LINES / 3 + 1, curses.COLS / 8)
147 pflush()
148 wait_a_while()
149
150 saywhat("s3; press any key to continue")
151 p3.show()
152 pflush()
153 wait_a_while()
154
155 saywhat("m3; press any key to continue")
156 p3.move(curses.LINES / 4 + 1, curses.COLS / 15)
157 pflush()
158 wait_a_while()
159
160 saywhat("b3; press any key to continue")
161 p3.bottom()
162 pflush()
163 wait_a_while()
164
165 saywhat("s4; press any key to continue")
166 p4.show()
167 pflush()
168 wait_a_while()
169
170 saywhat("s5; press any key to continue")
171 p5.show()
172 pflush()
173 wait_a_while()
174
175 saywhat("t3; press any key to continue")
176 p3.top()
177 pflush()
178 wait_a_while()
179
180 saywhat("t1; press any key to continue")
181 p1.show()
182 pflush()
183 wait_a_while()
184
185 saywhat("t2; press any key to continue")
186 p2.show()
187 pflush()
188 wait_a_while()
189
190 saywhat("t3; press any key to continue")
191 p3.show()
192 pflush()
193 wait_a_while()
194
195 saywhat("t4; press any key to continue")
196 p4.show()
197 pflush()
198 wait_a_while()
199
200 for itmp in range(0, 6):
201 w4 = p4.window()
202 w5 = p5.window()
203
204 saywhat("m4; press any key to continue")
205 w4.move(curses.LINES / 8, 1)
206 w4.addstr(mod[itmp])
207 p4.move(curses.LINES / 6, itmp * curses.COLS / 8)
208 w5.move(curses.LINES / 6, 1)
209 w5.addstr(mod[itmp])
210 pflush()
211 wait_a_while()
212
213 saywhat("m5; press any key to continue")
214 w4.move(curses.LINES / 6, 1)
215 w4.addstr(mod[itmp])
216 p5.move(curses.LINES / 3 - 1, itmp * 10 + 6)
217 w5.move(curses.LINES / 8, 1)
218 w5.addstr(mod[itmp])
219 pflush()
220 wait_a_while()
221
222 saywhat("m4; press any key to continue")
223 p4.move(curses.LINES / 6, (itmp + 1) * curses.COLS / 8)
224 pflush()
225 wait_a_while()
226
227 saywhat("t5; press any key to continue")
228 p5.top()
229 pflush()
230 wait_a_while()
231
232 saywhat("t2; press any key to continue")
233 p2.top()
234 pflush()
235 wait_a_while()
236
237 saywhat("t1; press any key to continue")
238 p1.top()
239 pflush()
240 wait_a_while()
241
242 saywhat("d2; press any key to continue")
243 del p2
244 pflush()
245 wait_a_while()
246
247 saywhat("h3; press any key to continue")
248 p3.hide()
249 pflush()
250 wait_a_while()
251
252 saywhat("d1; press any key to continue")
253 del p1
254 pflush()
255 wait_a_while()
256
257 saywhat("d4; press any key to continue")
258 del p4
259 pflush()
260 wait_a_while()
261
262 saywhat("d5; press any key to continue")
263 del p5
264 pflush()
265 wait_a_while()
266 if nap_msec == 1:
267 break
268 nap_msec = 100
269
270#
271# one fine day there'll be the menu at this place
272#
273curses.wrapper(demo_panels)
sys/src/cmd/python/Demo/curses/rain.py+94−0
@@ -0,0 +1,94 @@
1#!/bin/python
2#
3# $Id: rain.py 46625 2006-06-03 23:02:15Z andrew.kuchling $
4#
5# somebody should probably check the randrange()s...
6
7import curses
8from random import randrange
9
10def next_j(j):
11 if j == 0:
12 j = 4
13 else:
14 j -= 1
15
16 if curses.has_colors():
17 z = randrange(0, 3)
18 color = curses.color_pair(z)
19 if z:
20 color = color | curses.A_BOLD
21 stdscr.attrset(color)
22
23 return j
24
25def main(win):
26 # we know that the first argument from curses.wrapper() is stdscr.
27 # Initialize it globally for convenience.
28 global stdscr
29 stdscr = win
30
31 if curses.has_colors():
32 bg = curses.COLOR_BLACK
33 curses.init_pair(1, curses.COLOR_BLUE, bg)
34 curses.init_pair(2, curses.COLOR_CYAN, bg)
35
36 curses.nl()
37 curses.noecho()
38 # XXX curs_set() always returns ERR
39 # curses.curs_set(0)
40 stdscr.timeout(0)
41
42 c = curses.COLS - 4
43 r = curses.LINES - 4
44 xpos = [0] * c
45 ypos = [0] * r
46 for j in range(4, -1, -1):
47 xpos[j] = randrange(0, c) + 2
48 ypos[j] = randrange(0, r) + 2
49
50 j = 0
51 while True:
52 x = randrange(0, c) + 2
53 y = randrange(0, r) + 2
54
55 stdscr.addch(y, x, ord('.'))
56
57 stdscr.addch(ypos[j], xpos[j], ord('o'))
58
59 j = next_j(j)
60 stdscr.addch(ypos[j], xpos[j], ord('O'))
61
62 j = next_j(j)
63 stdscr.addch( ypos[j] - 1, xpos[j], ord('-'))
64 stdscr.addstr(ypos[j], xpos[j] - 1, "|.|")
65 stdscr.addch( ypos[j] + 1, xpos[j], ord('-'))
66
67 j = next_j(j)
68 stdscr.addch( ypos[j] - 2, xpos[j], ord('-'))
69 stdscr.addstr(ypos[j] - 1, xpos[j] - 1, "/ \\")
70 stdscr.addstr(ypos[j], xpos[j] - 2, "| O |")
71 stdscr.addstr(ypos[j] + 1, xpos[j] - 1, "\\ /")
72 stdscr.addch( ypos[j] + 2, xpos[j], ord('-'))
73
74 j = next_j(j)
75 stdscr.addch( ypos[j] - 2, xpos[j], ord(' '))
76 stdscr.addstr(ypos[j] - 1, xpos[j] - 1, " ")
77 stdscr.addstr(ypos[j], xpos[j] - 2, " ")
78 stdscr.addstr(ypos[j] + 1, xpos[j] - 1, " ")
79 stdscr.addch( ypos[j] + 2, xpos[j], ord(' '))
80
81 xpos[j] = x
82 ypos[j] = y
83
84 ch = stdscr.getch()
85 if ch == ord('q') or ch == ord('Q'):
86 return
87 elif ch == ord('s'):
88 stdscr.nodelay(0)
89 elif ch == ord(' '):
90 stdscr.nodelay(1)
91
92 curses.napms(50)
93
94curses.wrapper(main)
sys/src/cmd/python/Demo/curses/repeat.py+58−0
@@ -0,0 +1,58 @@
1#! /usr/bin/env python
2
3"""repeat <shell-command>
4
5This simple program repeatedly (at 1-second intervals) executes the
6shell command given on the command line and displays the output (or as
7much of it as fits on the screen). It uses curses to paint each new
8output on top of the old output, so that if nothing changes, the
9screen doesn't change. This is handy to watch for changes in e.g. a
10directory or process listing.
11
12To end, hit Control-C.
13"""
14
15# Author: Guido van Rossum
16
17# Disclaimer: there's a Linux program named 'watch' that does the same
18# thing. Honestly, I didn't know of its existence when I wrote this!
19
20# To do: add features until it has the same functionality as watch(1);
21# then compare code size and development time.
22
23import os
24import sys
25import time
26import curses
27
28def main():
29 if not sys.argv[1:]:
30 print __doc__
31 sys.exit(0)
32 cmd = " ".join(sys.argv[1:])
33 p = os.popen(cmd, "r")
34 text = p.read()
35 sts = p.close()
36 if sts:
37 print >>sys.stderr, "Exit code:", sts
38 sys.exit(sts)
39 w = curses.initscr()
40 try:
41 while True:
42 w.erase()
43 try:
44 w.addstr(text)
45 except curses.error:
46 pass
47 w.refresh()
48 time.sleep(1)
49 p = os.popen(cmd, "r")
50 text = p.read()
51 sts = p.close()
52 if sts:
53 print >>sys.stderr, "Exit code:", sts
54 sys.exit(sts)
55 finally:
56 curses.endwin()
57
58main()
sys/src/cmd/python/Demo/curses/tclock.py+147−0
@@ -0,0 +1,147 @@
1#!/usr/bin/env python
2#
3# $Id: tclock.py 46626 2006-06-03 23:07:21Z andrew.kuchling $
4#
5# From tclock.c, Copyright Howard Jones <ha.jones@ic.ac.uk>, September 1994.
6
7from math import *
8import curses, time
9
10ASPECT = 2.2
11
12def sign(_x):
13 if _x < 0: return -1
14 return 1
15
16def A2XY(angle, radius):
17 return (int(round(ASPECT * radius * sin(angle))),
18 int(round(radius * cos(angle))))
19
20def plot(x, y, col):
21 stdscr.addch(y, x, col)
22
23# draw a diagonal line using Bresenham's algorithm
24def dline(pair, from_x, from_y, x2, y2, ch):
25 if curses.has_colors():
26 stdscr.attrset(curses.color_pair(pair))
27
28 dx = x2 - from_x
29 dy = y2 - from_y
30
31 ax = abs(dx * 2)
32 ay = abs(dy * 2)
33
34 sx = sign(dx)
35 sy = sign(dy)
36
37 x = from_x
38 y = from_y
39
40 if ax > ay:
41 d = ay - ax // 2
42
43 while True:
44 plot(x, y, ch)
45 if x == x2:
46 return
47
48 if d >= 0:
49 y += sy
50 d -= ax
51 x += sx
52 d += ay
53 else:
54 d = ax - ay // 2
55
56 while True:
57 plot(x, y, ch)
58 if y == y2:
59 return
60
61 if d >= 0:
62 x += sx
63 d -= ay
64 y += sy
65 d += ax
66
67def main(win):
68 global stdscr
69 stdscr = win
70
71 lastbeep = -1
72 my_bg = curses.COLOR_BLACK
73
74 stdscr.nodelay(1)
75 stdscr.timeout(0)
76# curses.curs_set(0)
77 if curses.has_colors():
78 curses.init_pair(1, curses.COLOR_RED, my_bg)
79 curses.init_pair(2, curses.COLOR_MAGENTA, my_bg)
80 curses.init_pair(3, curses.COLOR_GREEN, my_bg)
81
82 cx = (curses.COLS - 1) // 2
83 cy = curses.LINES // 2
84 ch = min( cy-1, int(cx // ASPECT) - 1)
85 mradius = (3 * ch) // 4
86 hradius = ch // 2
87 sradius = 5 * ch // 6
88
89 for i in range(0, 12):
90 sangle = (i + 1) * 2.0 * pi / 12.0
91 sdx, sdy = A2XY(sangle, sradius)
92
93 stdscr.addstr(cy - sdy, cx + sdx, "%d" % (i + 1))
94
95 stdscr.addstr(0, 0,
96 "ASCII Clock by Howard Jones <ha.jones@ic.ac.uk>, 1994")
97
98 sradius = max(sradius-4, 8)
99
100 while True:
101 curses.napms(1000)
102
103 tim = time.time()
104 t = time.localtime(tim)
105
106 hours = t[3] + t[4] / 60.0
107 if hours > 12.0:
108 hours -= 12.0
109
110 mangle = t[4] * 2 * pi / 60.0
111 mdx, mdy = A2XY(mangle, mradius)
112
113 hangle = hours * 2 * pi / 12.0
114 hdx, hdy = A2XY(hangle, hradius)
115
116 sangle = t[5] * 2 * pi / 60.0
117 sdx, sdy = A2XY(sangle, sradius)
118
119 dline(3, cx, cy, cx + mdx, cy - mdy, ord('#'))
120
121 stdscr.attrset(curses.A_REVERSE)
122 dline(2, cx, cy, cx + hdx, cy - hdy, ord('.'))
123 stdscr.attroff(curses.A_REVERSE)
124
125 if curses.has_colors():
126 stdscr.attrset(curses.color_pair(1))
127
128 plot(cx + sdx, cy - sdy, ord('O'))
129
130 if curses.has_colors():
131 stdscr.attrset(curses.color_pair(0))
132
133 stdscr.addstr(curses.LINES - 2, 0, time.ctime(tim))
134 stdscr.refresh()
135 if (t[5] % 5) == 0 and t[5] != lastbeep:
136 lastbeep = t[5]
137 curses.beep()
138
139 ch = stdscr.getch()
140 if ch == ord('q'):
141 return 0
142
143 plot(cx + sdx, cy - sdy, ord(' '))
144 dline(0, cx, cy, cx + hdx, cy - hdy, ord(' '))
145 dline(0, cx, cy, cx + mdx, cy - mdy, ord(' '))
146
147curses.wrapper(main)
sys/src/cmd/python/Demo/curses/xmas.py+906−0
@@ -0,0 +1,906 @@
1# asciixmas
2# December 1989 Larry Bartz Indianapolis, IN
3#
4# $Id: xmas.py 46623 2006-06-03 22:59:23Z andrew.kuchling $
5#
6# I'm dreaming of an ascii character-based monochrome Christmas,
7# Just like the ones I used to know!
8# Via a full duplex communications channel,
9# At 9600 bits per second,
10# Even though it's kinda slow.
11#
12# I'm dreaming of an ascii character-based monochrome Christmas,
13# With ev'ry C program I write!
14# May your screen be merry and bright!
15# And may all your Christmases be amber or green,
16# (for reduced eyestrain and improved visibility)!
17#
18#
19# Notes on the Python version:
20# I used a couple of `try...except curses.error' to get around some functions
21# returning ERR. The errors come from using wrapping functions to fill
22# windows to the last character cell. The C version doesn't have this problem,
23# it simply ignores any return values.
24#
25
26import curses
27import sys
28
29FROMWHO = "Thomas Gellekum <tg@FreeBSD.org>"
30
31def set_color(win, color):
32 if curses.has_colors():
33 n = color + 1
34 curses.init_pair(n, color, my_bg)
35 win.attroff(curses.A_COLOR)
36 win.attron(curses.color_pair(n))
37
38def unset_color(win):
39 if curses.has_colors():
40 win.attrset(curses.color_pair(0))
41
42def look_out(msecs):
43 curses.napms(msecs)
44 if stdscr.getch() != -1:
45 curses.beep()
46 sys.exit(0)
47
48def boxit():
49 for y in range(0, 20):
50 stdscr.addch(y, 7, ord('|'))
51
52 for x in range(8, 80):
53 stdscr.addch(19, x, ord('_'))
54
55 for x in range(0, 80):
56 stdscr.addch(22, x, ord('_'))
57
58 return
59
60def seas():
61 stdscr.addch(4, 1, ord('S'))
62 stdscr.addch(6, 1, ord('E'))
63 stdscr.addch(8, 1, ord('A'))
64 stdscr.addch(10, 1, ord('S'))
65 stdscr.addch(12, 1, ord('O'))
66 stdscr.addch(14, 1, ord('N'))
67 stdscr.addch(16, 1, ord("'"))
68 stdscr.addch(18, 1, ord('S'))
69
70 return
71
72def greet():
73 stdscr.addch(3, 5, ord('G'))
74 stdscr.addch(5, 5, ord('R'))
75 stdscr.addch(7, 5, ord('E'))
76 stdscr.addch(9, 5, ord('E'))
77 stdscr.addch(11, 5, ord('T'))
78 stdscr.addch(13, 5, ord('I'))
79 stdscr.addch(15, 5, ord('N'))
80 stdscr.addch(17, 5, ord('G'))
81 stdscr.addch(19, 5, ord('S'))
82
83 return
84
85def fromwho():
86 stdscr.addstr(21, 13, FROMWHO)
87 return
88
89def tree():
90 set_color(treescrn, curses.COLOR_GREEN)
91 treescrn.addch(1, 11, ord('/'))
92 treescrn.addch(2, 11, ord('/'))
93 treescrn.addch(3, 10, ord('/'))
94 treescrn.addch(4, 9, ord('/'))
95 treescrn.addch(5, 9, ord('/'))
96 treescrn.addch(6, 8, ord('/'))
97 treescrn.addch(7, 7, ord('/'))
98 treescrn.addch(8, 6, ord('/'))
99 treescrn.addch(9, 6, ord('/'))
100 treescrn.addch(10, 5, ord('/'))
101 treescrn.addch(11, 3, ord('/'))
102 treescrn.addch(12, 2, ord('/'))
103
104 treescrn.addch(1, 13, ord('\\'))
105 treescrn.addch(2, 13, ord('\\'))
106 treescrn.addch(3, 14, ord('\\'))
107 treescrn.addch(4, 15, ord('\\'))
108 treescrn.addch(5, 15, ord('\\'))
109 treescrn.addch(6, 16, ord('\\'))
110 treescrn.addch(7, 17, ord('\\'))
111 treescrn.addch(8, 18, ord('\\'))
112 treescrn.addch(9, 18, ord('\\'))
113 treescrn.addch(10, 19, ord('\\'))
114 treescrn.addch(11, 21, ord('\\'))
115 treescrn.addch(12, 22, ord('\\'))
116
117 treescrn.addch(4, 10, ord('_'))
118 treescrn.addch(4, 14, ord('_'))
119 treescrn.addch(8, 7, ord('_'))
120 treescrn.addch(8, 17, ord('_'))
121
122 treescrn.addstr(13, 0, "//////////// \\\\\\\\\\\\\\\\\\\\\\\\")
123
124 treescrn.addstr(14, 11, "| |")
125 treescrn.addstr(15, 11, "|_|")
126
127 unset_color(treescrn)
128 treescrn.refresh()
129 w_del_msg.refresh()
130
131 return
132
133def balls():
134 treescrn.overlay(treescrn2)
135
136 set_color(treescrn2, curses.COLOR_BLUE)
137 treescrn2.addch(3, 9, ord('@'))
138 treescrn2.addch(3, 15, ord('@'))
139 treescrn2.addch(4, 8, ord('@'))
140 treescrn2.addch(4, 16, ord('@'))
141 treescrn2.addch(5, 7, ord('@'))
142 treescrn2.addch(5, 17, ord('@'))
143 treescrn2.addch(7, 6, ord('@'))
144 treescrn2.addch(7, 18, ord('@'))
145 treescrn2.addch(8, 5, ord('@'))
146 treescrn2.addch(8, 19, ord('@'))
147 treescrn2.addch(10, 4, ord('@'))
148 treescrn2.addch(10, 20, ord('@'))
149 treescrn2.addch(11, 2, ord('@'))
150 treescrn2.addch(11, 22, ord('@'))
151 treescrn2.addch(12, 1, ord('@'))
152 treescrn2.addch(12, 23, ord('@'))
153
154 unset_color(treescrn2)
155 treescrn2.refresh()
156 w_del_msg.refresh()
157 return
158
159def star():
160 treescrn2.attrset(curses.A_BOLD | curses.A_BLINK)
161 set_color(treescrn2, curses.COLOR_YELLOW)
162
163 treescrn2.addch(0, 12, ord('*'))
164 treescrn2.standend()
165
166 unset_color(treescrn2)
167 treescrn2.refresh()
168 w_del_msg.refresh()
169 return
170
171def strng1():
172 treescrn2.attrset(curses.A_BOLD | curses.A_BLINK)
173 set_color(treescrn2, curses.COLOR_WHITE)
174
175 treescrn2.addch(3, 13, ord('\''))
176 treescrn2.addch(3, 12, ord(':'))
177 treescrn2.addch(3, 11, ord('.'))
178
179 treescrn2.attroff(curses.A_BOLD | curses.A_BLINK)
180 unset_color(treescrn2)
181
182 treescrn2.refresh()
183 w_del_msg.refresh()
184 return
185
186def strng2():
187 treescrn2.attrset(curses.A_BOLD | curses.A_BLINK)
188 set_color(treescrn2, curses.COLOR_WHITE)
189
190 treescrn2.addch(5, 14, ord('\''))
191 treescrn2.addch(5, 13, ord(':'))
192 treescrn2.addch(5, 12, ord('.'))
193 treescrn2.addch(5, 11, ord(','))
194 treescrn2.addch(6, 10, ord('\''))
195 treescrn2.addch(6, 9, ord(':'))
196
197 treescrn2.attroff(curses.A_BOLD | curses.A_BLINK)
198 unset_color(treescrn2)
199
200 treescrn2.refresh()
201 w_del_msg.refresh()
202 return
203
204def strng3():
205 treescrn2.attrset(curses.A_BOLD | curses.A_BLINK)
206 set_color(treescrn2, curses.COLOR_WHITE)
207
208 treescrn2.addch(7, 16, ord('\''))
209 treescrn2.addch(7, 15, ord(':'))
210 treescrn2.addch(7, 14, ord('.'))
211 treescrn2.addch(7, 13, ord(','))
212 treescrn2.addch(8, 12, ord('\''))
213 treescrn2.addch(8, 11, ord(':'))
214 treescrn2.addch(8, 10, ord('.'))
215 treescrn2.addch(8, 9, ord(','))
216
217 treescrn2.attroff(curses.A_BOLD | curses.A_BLINK)
218 unset_color(treescrn2)
219
220 treescrn2.refresh()
221 w_del_msg.refresh()
222 return
223
224def strng4():
225 treescrn2.attrset(curses.A_BOLD | curses.A_BLINK)
226 set_color(treescrn2, curses.COLOR_WHITE)
227
228 treescrn2.addch(9, 17, ord('\''))
229 treescrn2.addch(9, 16, ord(':'))
230 treescrn2.addch(9, 15, ord('.'))
231 treescrn2.addch(9, 14, ord(','))
232 treescrn2.addch(10, 13, ord('\''))
233 treescrn2.addch(10, 12, ord(':'))
234 treescrn2.addch(10, 11, ord('.'))
235 treescrn2.addch(10, 10, ord(','))
236 treescrn2.addch(11, 9, ord('\''))
237 treescrn2.addch(11, 8, ord(':'))
238 treescrn2.addch(11, 7, ord('.'))
239 treescrn2.addch(11, 6, ord(','))
240 treescrn2.addch(12, 5, ord('\''))
241
242 treescrn2.attroff(curses.A_BOLD | curses.A_BLINK)
243 unset_color(treescrn2)
244
245 treescrn2.refresh()
246 w_del_msg.refresh()
247 return
248
249def strng5():
250 treescrn2.attrset(curses.A_BOLD | curses.A_BLINK)
251 set_color(treescrn2, curses.COLOR_WHITE)
252
253 treescrn2.addch(11, 19, ord('\''))
254 treescrn2.addch(11, 18, ord(':'))
255 treescrn2.addch(11, 17, ord('.'))
256 treescrn2.addch(11, 16, ord(','))
257 treescrn2.addch(12, 15, ord('\''))
258 treescrn2.addch(12, 14, ord(':'))
259 treescrn2.addch(12, 13, ord('.'))
260 treescrn2.addch(12, 12, ord(','))
261
262 treescrn2.attroff(curses.A_BOLD | curses.A_BLINK)
263 unset_color(treescrn2)
264
265 # save a fully lit tree
266 treescrn2.overlay(treescrn)
267
268 treescrn2.refresh()
269 w_del_msg.refresh()
270 return
271
272def blinkit():
273 treescrn8.touchwin()
274
275 for cycle in range(5):
276 if cycle == 0:
277 treescrn3.overlay(treescrn8)
278 treescrn8.refresh()
279 w_del_msg.refresh()
280 break
281 elif cycle == 1:
282 treescrn4.overlay(treescrn8)
283 treescrn8.refresh()
284 w_del_msg.refresh()
285 break
286 elif cycle == 2:
287 treescrn5.overlay(treescrn8)
288 treescrn8.refresh()
289 w_del_msg.refresh()
290 break
291 elif cycle == 3:
292 treescrn6.overlay(treescrn8)
293 treescrn8.refresh()
294 w_del_msg.refresh()
295 break
296 elif cycle == 4:
297 treescrn7.overlay(treescrn8)
298 treescrn8.refresh()
299 w_del_msg.refresh()
300 break
301
302 treescrn8.touchwin()
303
304 # ALL ON
305 treescrn.overlay(treescrn8)
306 treescrn8.refresh()
307 w_del_msg.refresh()
308
309 return
310
311def deer_step(win, y, x):
312 win.mvwin(y, x)
313 win.refresh()
314 w_del_msg.refresh()
315 look_out(5)
316
317def reindeer():
318 y_pos = 0
319
320 for x_pos in range(70, 62, -1):
321 if x_pos < 66: y_pos = 1
322 for looper in range(0, 4):
323 dotdeer0.addch(y_pos, x_pos, ord('.'))
324 dotdeer0.refresh()
325 w_del_msg.refresh()
326 dotdeer0.erase()
327 dotdeer0.refresh()
328 w_del_msg.refresh()
329 look_out(50)
330
331 y_pos = 2
332
333 for x_pos in range(x_pos - 1, 50, -1):
334 for looper in range(0, 4):
335 if x_pos < 56:
336 y_pos = 3
337
338 try:
339 stardeer0.addch(y_pos, x_pos, ord('*'))
340 except curses.error:
341 pass
342 stardeer0.refresh()
343 w_del_msg.refresh()
344 stardeer0.erase()
345 stardeer0.refresh()
346 w_del_msg.refresh()
347 else:
348 dotdeer0.addch(y_pos, x_pos, ord('*'))
349 dotdeer0.refresh()
350 w_del_msg.refresh()
351 dotdeer0.erase()
352 dotdeer0.refresh()
353 w_del_msg.refresh()
354
355 x_pos = 58
356
357 for y_pos in range(2, 5):
358 lildeer0.touchwin()
359 lildeer0.refresh()
360 w_del_msg.refresh()
361
362 for looper in range(0, 4):
363 deer_step(lildeer3, y_pos, x_pos)
364 deer_step(lildeer2, y_pos, x_pos)
365 deer_step(lildeer1, y_pos, x_pos)
366 deer_step(lildeer2, y_pos, x_pos)
367 deer_step(lildeer3, y_pos, x_pos)
368
369 lildeer0.touchwin()
370 lildeer0.refresh()
371 w_del_msg.refresh()
372
373 x_pos -= 2
374
375 x_pos = 35
376
377 for y_pos in range(5, 10):
378
379 middeer0.touchwin()
380 middeer0.refresh()
381 w_del_msg.refresh()
382
383 for looper in range(2):
384 deer_step(middeer3, y_pos, x_pos)
385 deer_step(middeer2, y_pos, x_pos)
386 deer_step(middeer1, y_pos, x_pos)
387 deer_step(middeer2, y_pos, x_pos)
388 deer_step(middeer3, y_pos, x_pos)
389
390 middeer0.touchwin()
391 middeer0.refresh()
392 w_del_msg.refresh()
393
394 x_pos -= 3
395
396 look_out(300)
397
398 y_pos = 1
399
400 for x_pos in range(8, 16):
401 deer_step(bigdeer4, y_pos, x_pos)
402 deer_step(bigdeer3, y_pos, x_pos)
403 deer_step(bigdeer2, y_pos, x_pos)
404 deer_step(bigdeer1, y_pos, x_pos)
405 deer_step(bigdeer2, y_pos, x_pos)
406 deer_step(bigdeer3, y_pos, x_pos)
407 deer_step(bigdeer4, y_pos, x_pos)
408 deer_step(bigdeer0, y_pos, x_pos)
409
410 x_pos -= 1
411
412 for looper in range(0, 6):
413 deer_step(lookdeer4, y_pos, x_pos)
414 deer_step(lookdeer3, y_pos, x_pos)
415 deer_step(lookdeer2, y_pos, x_pos)
416 deer_step(lookdeer1, y_pos, x_pos)
417 deer_step(lookdeer2, y_pos, x_pos)
418 deer_step(lookdeer3, y_pos, x_pos)
419 deer_step(lookdeer4, y_pos, x_pos)
420
421 deer_step(lookdeer0, y_pos, x_pos)
422
423 for y_pos in range(y_pos, 10):
424 for looper in range(0, 2):
425 deer_step(bigdeer4, y_pos, x_pos)
426 deer_step(bigdeer3, y_pos, x_pos)
427 deer_step(bigdeer2, y_pos, x_pos)
428 deer_step(bigdeer1, y_pos, x_pos)
429 deer_step(bigdeer2, y_pos, x_pos)
430 deer_step(bigdeer3, y_pos, x_pos)
431 deer_step(bigdeer4, y_pos, x_pos)
432 deer_step(bigdeer0, y_pos, x_pos)
433
434 y_pos -= 1
435
436 deer_step(lookdeer3, y_pos, x_pos)
437 return
438
439def main(win):
440 global stdscr
441 stdscr = win
442
443 global my_bg, y_pos, x_pos
444 global treescrn, treescrn2, treescrn3, treescrn4
445 global treescrn5, treescrn6, treescrn7, treescrn8
446 global dotdeer0, stardeer0
447 global lildeer0, lildeer1, lildeer2, lildeer3
448 global middeer0, middeer1, middeer2, middeer3
449 global bigdeer0, bigdeer1, bigdeer2, bigdeer3, bigdeer4
450 global lookdeer0, lookdeer1, lookdeer2, lookdeer3, lookdeer4
451 global w_holiday, w_del_msg
452
453 my_bg = curses.COLOR_BLACK
454 # curses.curs_set(0)
455
456 treescrn = curses.newwin(16, 27, 3, 53)
457 treescrn2 = curses.newwin(16, 27, 3, 53)
458 treescrn3 = curses.newwin(16, 27, 3, 53)
459 treescrn4 = curses.newwin(16, 27, 3, 53)
460 treescrn5 = curses.newwin(16, 27, 3, 53)
461 treescrn6 = curses.newwin(16, 27, 3, 53)
462 treescrn7 = curses.newwin(16, 27, 3, 53)
463 treescrn8 = curses.newwin(16, 27, 3, 53)
464
465 dotdeer0 = curses.newwin(3, 71, 0, 8)
466
467 stardeer0 = curses.newwin(4, 56, 0, 8)
468
469 lildeer0 = curses.newwin(7, 53, 0, 8)
470 lildeer1 = curses.newwin(2, 4, 0, 0)
471 lildeer2 = curses.newwin(2, 4, 0, 0)
472 lildeer3 = curses.newwin(2, 4, 0, 0)
473
474 middeer0 = curses.newwin(15, 42, 0, 8)
475 middeer1 = curses.newwin(3, 7, 0, 0)
476 middeer2 = curses.newwin(3, 7, 0, 0)
477 middeer3 = curses.newwin(3, 7, 0, 0)
478
479 bigdeer0 = curses.newwin(10, 23, 0, 0)
480 bigdeer1 = curses.newwin(10, 23, 0, 0)
481 bigdeer2 = curses.newwin(10, 23, 0, 0)
482 bigdeer3 = curses.newwin(10, 23, 0, 0)
483 bigdeer4 = curses.newwin(10, 23, 0, 0)
484
485 lookdeer0 = curses.newwin(10, 25, 0, 0)
486 lookdeer1 = curses.newwin(10, 25, 0, 0)
487 lookdeer2 = curses.newwin(10, 25, 0, 0)
488 lookdeer3 = curses.newwin(10, 25, 0, 0)
489 lookdeer4 = curses.newwin(10, 25, 0, 0)
490
491 w_holiday = curses.newwin(1, 27, 3, 27)
492
493 w_del_msg = curses.newwin(1, 20, 23, 60)
494
495 try:
496 w_del_msg.addstr(0, 0, "Hit any key to quit")
497 except curses.error:
498 pass
499
500 try:
501 w_holiday.addstr(0, 0, "H A P P Y H O L I D A Y S")
502 except curses.error:
503 pass
504
505 # set up the windows for our various reindeer
506 lildeer1.addch(0, 0, ord('V'))
507 lildeer1.addch(1, 0, ord('@'))
508 lildeer1.addch(1, 1, ord('<'))
509 lildeer1.addch(1, 2, ord('>'))
510 try:
511 lildeer1.addch(1, 3, ord('~'))
512 except curses.error:
513 pass
514
515 lildeer2.addch(0, 0, ord('V'))
516 lildeer2.addch(1, 0, ord('@'))
517 lildeer2.addch(1, 1, ord('|'))
518 lildeer2.addch(1, 2, ord('|'))
519 try:
520 lildeer2.addch(1, 3, ord('~'))
521 except curses.error:
522 pass
523
524 lildeer3.addch(0, 0, ord('V'))
525 lildeer3.addch(1, 0, ord('@'))
526 lildeer3.addch(1, 1, ord('>'))
527 lildeer3.addch(1, 2, ord('<'))
528 try:
529 lildeer2.addch(1, 3, ord('~')) # XXX
530 except curses.error:
531 pass
532
533 middeer1.addch(0, 2, ord('y'))
534 middeer1.addch(0, 3, ord('y'))
535 middeer1.addch(1, 2, ord('0'))
536 middeer1.addch(1, 3, ord('('))
537 middeer1.addch(1, 4, ord('='))
538 middeer1.addch(1, 5, ord(')'))
539 middeer1.addch(1, 6, ord('~'))
540 middeer1.addch(2, 3, ord('\\'))
541 middeer1.addch(2, 5, ord('/'))
542
543 middeer2.addch(0, 2, ord('y'))
544 middeer2.addch(0, 3, ord('y'))
545 middeer2.addch(1, 2, ord('0'))
546 middeer2.addch(1, 3, ord('('))
547 middeer2.addch(1, 4, ord('='))
548 middeer2.addch(1, 5, ord(')'))
549 middeer2.addch(1, 6, ord('~'))
550 middeer2.addch(2, 3, ord('|'))
551 middeer2.addch(2, 5, ord('|'))
552
553 middeer3.addch(0, 2, ord('y'))
554 middeer3.addch(0, 3, ord('y'))
555 middeer3.addch(1, 2, ord('0'))
556 middeer3.addch(1, 3, ord('('))
557 middeer3.addch(1, 4, ord('='))
558 middeer3.addch(1, 5, ord(')'))
559 middeer3.addch(1, 6, ord('~'))
560 middeer3.addch(2, 3, ord('/'))
561 middeer3.addch(2, 5, ord('\\'))
562
563 bigdeer1.addch(0, 17, ord('\\'))
564 bigdeer1.addch(0, 18, ord('/'))
565 bigdeer1.addch(0, 19, ord('\\'))
566 bigdeer1.addch(0, 20, ord('/'))
567 bigdeer1.addch(1, 18, ord('\\'))
568 bigdeer1.addch(1, 20, ord('/'))
569 bigdeer1.addch(2, 19, ord('|'))
570 bigdeer1.addch(2, 20, ord('_'))
571 bigdeer1.addch(3, 18, ord('/'))
572 bigdeer1.addch(3, 19, ord('^'))
573 bigdeer1.addch(3, 20, ord('0'))
574 bigdeer1.addch(3, 21, ord('\\'))
575 bigdeer1.addch(4, 17, ord('/'))
576 bigdeer1.addch(4, 18, ord('/'))
577 bigdeer1.addch(4, 19, ord('\\'))
578 bigdeer1.addch(4, 22, ord('\\'))
579 bigdeer1.addstr(5, 7, "^~~~~~~~~// ~~U")
580 bigdeer1.addstr(6, 7, "( \\_____( /") # ))
581 bigdeer1.addstr(7, 8, "( ) /")
582 bigdeer1.addstr(8, 9, "\\\\ /")
583 bigdeer1.addstr(9, 11, "\\>/>")
584
585 bigdeer2.addch(0, 17, ord('\\'))
586 bigdeer2.addch(0, 18, ord('/'))
587 bigdeer2.addch(0, 19, ord('\\'))
588 bigdeer2.addch(0, 20, ord('/'))
589 bigdeer2.addch(1, 18, ord('\\'))
590 bigdeer2.addch(1, 20, ord('/'))
591 bigdeer2.addch(2, 19, ord('|'))
592 bigdeer2.addch(2, 20, ord('_'))
593 bigdeer2.addch(3, 18, ord('/'))
594 bigdeer2.addch(3, 19, ord('^'))
595 bigdeer2.addch(3, 20, ord('0'))
596 bigdeer2.addch(3, 21, ord('\\'))
597 bigdeer2.addch(4, 17, ord('/'))
598 bigdeer2.addch(4, 18, ord('/'))
599 bigdeer2.addch(4, 19, ord('\\'))
600 bigdeer2.addch(4, 22, ord('\\'))
601 bigdeer2.addstr(5, 7, "^~~~~~~~~// ~~U")
602 bigdeer2.addstr(6, 7, "(( )____( /") # ))
603 bigdeer2.addstr(7, 7, "( / |")
604 bigdeer2.addstr(8, 8, "\\/ |")
605 bigdeer2.addstr(9, 9, "|> |>")
606
607 bigdeer3.addch(0, 17, ord('\\'))
608 bigdeer3.addch(0, 18, ord('/'))
609 bigdeer3.addch(0, 19, ord('\\'))
610 bigdeer3.addch(0, 20, ord('/'))
611 bigdeer3.addch(1, 18, ord('\\'))
612 bigdeer3.addch(1, 20, ord('/'))
613 bigdeer3.addch(2, 19, ord('|'))
614 bigdeer3.addch(2, 20, ord('_'))
615 bigdeer3.addch(3, 18, ord('/'))
616 bigdeer3.addch(3, 19, ord('^'))
617 bigdeer3.addch(3, 20, ord('0'))
618 bigdeer3.addch(3, 21, ord('\\'))
619 bigdeer3.addch(4, 17, ord('/'))
620 bigdeer3.addch(4, 18, ord('/'))
621 bigdeer3.addch(4, 19, ord('\\'))
622 bigdeer3.addch(4, 22, ord('\\'))
623 bigdeer3.addstr(5, 7, "^~~~~~~~~// ~~U")
624 bigdeer3.addstr(6, 6, "( ()_____( /") # ))
625 bigdeer3.addstr(7, 6, "/ / /")
626 bigdeer3.addstr(8, 5, "|/ \\")
627 bigdeer3.addstr(9, 5, "/> \\>")
628
629 bigdeer4.addch(0, 17, ord('\\'))
630 bigdeer4.addch(0, 18, ord('/'))
631 bigdeer4.addch(0, 19, ord('\\'))
632 bigdeer4.addch(0, 20, ord('/'))
633 bigdeer4.addch(1, 18, ord('\\'))
634 bigdeer4.addch(1, 20, ord('/'))
635 bigdeer4.addch(2, 19, ord('|'))
636 bigdeer4.addch(2, 20, ord('_'))
637 bigdeer4.addch(3, 18, ord('/'))
638 bigdeer4.addch(3, 19, ord('^'))
639 bigdeer4.addch(3, 20, ord('0'))
640 bigdeer4.addch(3, 21, ord('\\'))
641 bigdeer4.addch(4, 17, ord('/'))
642 bigdeer4.addch(4, 18, ord('/'))
643 bigdeer4.addch(4, 19, ord('\\'))
644 bigdeer4.addch(4, 22, ord('\\'))
645 bigdeer4.addstr(5, 7, "^~~~~~~~~// ~~U")
646 bigdeer4.addstr(6, 6, "( )______( /") # )
647 bigdeer4.addstr(7, 5, "(/ \\") # )
648 bigdeer4.addstr(8, 0, "v___= ----^")
649
650 lookdeer1.addstr(0, 16, "\\/ \\/")
651 lookdeer1.addstr(1, 17, "\\Y/ \\Y/")
652 lookdeer1.addstr(2, 19, "\\=/")
653 lookdeer1.addstr(3, 17, "^\\o o/^")
654 lookdeer1.addstr(4, 17, "//( )")
655 lookdeer1.addstr(5, 7, "^~~~~~~~~// \\O/")
656 lookdeer1.addstr(6, 7, "( \\_____( /") # ))
657 lookdeer1.addstr(7, 8, "( ) /")
658 lookdeer1.addstr(8, 9, "\\\\ /")
659 lookdeer1.addstr(9, 11, "\\>/>")
660
661 lookdeer2.addstr(0, 16, "\\/ \\/")
662 lookdeer2.addstr(1, 17, "\\Y/ \\Y/")
663 lookdeer2.addstr(2, 19, "\\=/")
664 lookdeer2.addstr(3, 17, "^\\o o/^")
665 lookdeer2.addstr(4, 17, "//( )")
666 lookdeer2.addstr(5, 7, "^~~~~~~~~// \\O/")
667 lookdeer2.addstr(6, 7, "(( )____( /") # ))
668 lookdeer2.addstr(7, 7, "( / |")
669 lookdeer2.addstr(8, 8, "\\/ |")
670 lookdeer2.addstr(9, 9, "|> |>")
671
672 lookdeer3.addstr(0, 16, "\\/ \\/")
673 lookdeer3.addstr(1, 17, "\\Y/ \\Y/")
674 lookdeer3.addstr(2, 19, "\\=/")
675 lookdeer3.addstr(3, 17, "^\\o o/^")
676 lookdeer3.addstr(4, 17, "//( )")
677 lookdeer3.addstr(5, 7, "^~~~~~~~~// \\O/")
678 lookdeer3.addstr(6, 6, "( ()_____( /") # ))
679 lookdeer3.addstr(7, 6, "/ / /")
680 lookdeer3.addstr(8, 5, "|/ \\")
681 lookdeer3.addstr(9, 5, "/> \\>")
682
683 lookdeer4.addstr(0, 16, "\\/ \\/")
684 lookdeer4.addstr(1, 17, "\\Y/ \\Y/")
685 lookdeer4.addstr(2, 19, "\\=/")
686 lookdeer4.addstr(3, 17, "^\\o o/^")
687 lookdeer4.addstr(4, 17, "//( )")
688 lookdeer4.addstr(5, 7, "^~~~~~~~~// \\O/")
689 lookdeer4.addstr(6, 6, "( )______( /") # )
690 lookdeer4.addstr(7, 5, "(/ \\") # )
691 lookdeer4.addstr(8, 0, "v___= ----^")
692
693 ###############################################
694 curses.cbreak()
695 stdscr.nodelay(1)
696
697 while 1:
698 stdscr.clear()
699 treescrn.erase()
700 w_del_msg.touchwin()
701 treescrn.touchwin()
702 treescrn2.erase()
703 treescrn2.touchwin()
704 treescrn8.erase()
705 treescrn8.touchwin()
706 stdscr.refresh()
707 look_out(150)
708 boxit()
709 stdscr.refresh()
710 look_out(150)
711 seas()
712 stdscr.refresh()
713 greet()
714 stdscr.refresh()
715 look_out(150)
716 fromwho()
717 stdscr.refresh()
718 look_out(150)
719 tree()
720 look_out(150)
721 balls()
722 look_out(150)
723 star()
724 look_out(150)
725 strng1()
726 strng2()
727 strng3()
728 strng4()
729 strng5()
730
731 # set up the windows for our blinking trees
732 #
733 # treescrn3
734 treescrn.overlay(treescrn3)
735
736 # balls
737 treescrn3.addch(4, 18, ord(' '))
738 treescrn3.addch(7, 6, ord(' '))
739 treescrn3.addch(8, 19, ord(' '))
740 treescrn3.addch(11, 22, ord(' '))
741
742 # star
743 treescrn3.addch(0, 12, ord('*'))
744
745 # strng1
746 treescrn3.addch(3, 11, ord(' '))
747
748 # strng2
749 treescrn3.addch(5, 13, ord(' '))
750 treescrn3.addch(6, 10, ord(' '))
751
752 # strng3
753 treescrn3.addch(7, 16, ord(' '))
754 treescrn3.addch(7, 14, ord(' '))
755
756 # strng4
757 treescrn3.addch(10, 13, ord(' '))
758 treescrn3.addch(10, 10, ord(' '))
759 treescrn3.addch(11, 8, ord(' '))
760
761 # strng5
762 treescrn3.addch(11, 18, ord(' '))
763 treescrn3.addch(12, 13, ord(' '))
764
765 # treescrn4
766 treescrn.overlay(treescrn4)
767
768 # balls
769 treescrn4.addch(3, 9, ord(' '))
770 treescrn4.addch(4, 16, ord(' '))
771 treescrn4.addch(7, 6, ord(' '))
772 treescrn4.addch(8, 19, ord(' '))
773 treescrn4.addch(11, 2, ord(' '))
774 treescrn4.addch(12, 23, ord(' '))
775
776 # star
777 treescrn4.standout()
778 treescrn4.addch(0, 12, ord('*'))
779 treescrn4.standend()
780
781 # strng1
782 treescrn4.addch(3, 13, ord(' '))
783
784 # strng2
785
786 # strng3
787 treescrn4.addch(7, 15, ord(' '))
788 treescrn4.addch(8, 11, ord(' '))
789
790 # strng4
791 treescrn4.addch(9, 16, ord(' '))
792 treescrn4.addch(10, 12, ord(' '))
793 treescrn4.addch(11, 8, ord(' '))
794
795 # strng5
796 treescrn4.addch(11, 18, ord(' '))
797 treescrn4.addch(12, 14, ord(' '))
798
799 # treescrn5
800 treescrn.overlay(treescrn5)
801
802 # balls
803 treescrn5.addch(3, 15, ord(' '))
804 treescrn5.addch(10, 20, ord(' '))
805 treescrn5.addch(12, 1, ord(' '))
806
807 # star
808 treescrn5.addch(0, 12, ord(' '))
809
810 # strng1
811 treescrn5.addch(3, 11, ord(' '))
812
813 # strng2
814 treescrn5.addch(5, 12, ord(' '))
815
816 # strng3
817 treescrn5.addch(7, 14, ord(' '))
818 treescrn5.addch(8, 10, ord(' '))
819
820 # strng4
821 treescrn5.addch(9, 15, ord(' '))
822 treescrn5.addch(10, 11, ord(' '))
823 treescrn5.addch(11, 7, ord(' '))
824
825 # strng5
826 treescrn5.addch(11, 17, ord(' '))
827 treescrn5.addch(12, 13, ord(' '))
828
829 # treescrn6
830 treescrn.overlay(treescrn6)
831
832 # balls
833 treescrn6.addch(6, 7, ord(' '))
834 treescrn6.addch(7, 18, ord(' '))
835 treescrn6.addch(10, 4, ord(' '))
836 treescrn6.addch(11, 23, ord(' '))
837
838 # star
839 treescrn6.standout()
840 treescrn6.addch(0, 12, ord('*'))
841 treescrn6.standend()
842
843 # strng1
844
845 # strng2
846 treescrn6.addch(5, 11, ord(' '))
847
848 # strng3
849 treescrn6.addch(7, 13, ord(' '))
850 treescrn6.addch(8, 9, ord(' '))
851
852 # strng4
853 treescrn6.addch(9, 14, ord(' '))
854 treescrn6.addch(10, 10, ord(' '))
855 treescrn6.addch(11, 6, ord(' '))
856
857 # strng5
858 treescrn6.addch(11, 16, ord(' '))
859 treescrn6.addch(12, 12, ord(' '))
860
861 # treescrn7
862
863 treescrn.overlay(treescrn7)
864
865 # balls
866 treescrn7.addch(3, 15, ord(' '))
867 treescrn7.addch(6, 7, ord(' '))
868 treescrn7.addch(7, 18, ord(' '))
869 treescrn7.addch(10, 4, ord(' '))
870 treescrn7.addch(11, 22, ord(' '))
871
872 # star
873 treescrn7.addch(0, 12, ord('*'))
874
875 # strng1
876 treescrn7.addch(3, 12, ord(' '))
877
878 # strng2
879 treescrn7.addch(5, 13, ord(' '))
880 treescrn7.addch(6, 9, ord(' '))
881
882 # strng3
883 treescrn7.addch(7, 15, ord(' '))
884 treescrn7.addch(8, 11, ord(' '))
885
886 # strng4
887 treescrn7.addch(9, 16, ord(' '))
888 treescrn7.addch(10, 12, ord(' '))
889 treescrn7.addch(11, 8, ord(' '))
890
891 # strng5
892 treescrn7.addch(11, 18, ord(' '))
893 treescrn7.addch(12, 14, ord(' '))
894
895 look_out(150)
896 reindeer()
897
898 w_holiday.touchwin()
899 w_holiday.refresh()
900 w_del_msg.refresh()
901
902 look_out(500)
903 for i in range(0, 20):
904 blinkit()
905
906curses.wrapper(main)
sys/src/cmd/python/Demo/embed/Makefile+57−0
@@ -0,0 +1,57 @@
1# Makefile for embedded Python use demo.
2# (This version tailored for my Red Hat Linux 6.1 setup;
3# edit lines marked with XXX.)
4
5# XXX The compiler you are using
6CC= gcc
7
8# XXX Top of the build tree and source tree
9blddir= ../..
10srcdir= ../..
11
12# Python version
13VERSION= 2.5
14
15# Compiler flags
16OPT= -g
17INCLUDES= -I$(srcdir)/Include -I$(blddir)
18CFLAGS= $(OPT)
19CPPFLAGS= $(INCLUDES)
20
21# The Python library
22LIBPYTHON= $(blddir)/libpython$(VERSION).a
23
24# XXX edit LIBS (in particular) to match $(blddir)/Modules/Makefile
25LIBS= -lnsl -ldl -lreadline -ltermcap -lieee -lpthread -lutil
26LDFLAGS= -Xlinker -export-dynamic
27SYSLIBS= -lm
28MODLIBS=
29ALLLIBS= $(LIBPYTHON) $(MODLIBS) $(LIBS) $(SYSLIBS)
30
31# Build the demo applications
32all: demo loop importexc
33demo: demo.o
34 $(CC) $(LDFLAGS) demo.o $(ALLLIBS) -o demo
35
36loop: loop.o
37 $(CC) $(LDFLAGS) loop.o $(ALLLIBS) -o loop
38
39importexc: importexc.o
40 $(CC) $(LDFLAGS) importexc.o $(ALLLIBS) -o importexc
41
42# Administrative targets
43
44test: demo
45 ./demo
46
47COMMAND="print 'hello world'"
48looptest: loop
49 ./loop $(COMMAND)
50
51clean:
52 -rm -f *.o core
53
54clobber: clean
55 -rm -f *~ @* '#'* demo loop importexc
56
57realclean: clobber
sys/src/cmd/python/Demo/embed/README+19−0
@@ -0,0 +1,19 @@
1This directory show how to embed the Python interpreter in your own
2application. The file demo.c shows you all that is needed in your C
3code.
4
5To build it, you may have to edit the Makefile:
6
71) set blddir to the directory where you built Python, if it isn't in
8the source directory (../..)
9
102) change the variables that together define the list of libraries
11(MODLIBS, LIBS, SYSLIBS) to link with, to match their definitions in
12$(blddir)/Modules/Makefile
13
14An additional test program, loop.c, is used to experiment with memory
15leakage caused by repeated initialization and finalization of the
16interpreter. It can be build by saying "make loop" and tested with
17"make looptest". Command line usage is "./loop <python-command>",
18e.g. "./loop 'print 2+2'" should spit out an endless number of lines
19containing the number 4.
sys/src/cmd/python/Demo/embed/demo.c+65−0
@@ -0,0 +1,65 @@
1/* Example of embedding Python in another program */
2
3#include "Python.h"
4
5void initxyzzy(void); /* Forward */
6
7main(int argc, char **argv)
8{
9 /* Pass argv[0] to the Python interpreter */
10 Py_SetProgramName(argv[0]);
11
12 /* Initialize the Python interpreter. Required. */
13 Py_Initialize();
14
15 /* Add a static module */
16 initxyzzy();
17
18 /* Define sys.argv. It is up to the application if you
19 want this; you can also let it undefined (since the Python
20 code is generally not a main program it has no business
21 touching sys.argv...) */
22 PySys_SetArgv(argc, argv);
23
24 /* Do some application specific code */
25 printf("Hello, brave new world\n\n");
26
27 /* Execute some Python statements (in module __main__) */
28 PyRun_SimpleString("import sys\n");
29 PyRun_SimpleString("print sys.builtin_module_names\n");
30 PyRun_SimpleString("print sys.modules.keys()\n");
31 PyRun_SimpleString("print sys.executable\n");
32 PyRun_SimpleString("print sys.argv\n");
33
34 /* Note that you can call any public function of the Python
35 interpreter here, e.g. call_object(). */
36
37 /* Some more application specific code */
38 printf("\nGoodbye, cruel world\n");
39
40 /* Exit, cleaning up the interpreter */
41 Py_Exit(0);
42 /*NOTREACHED*/
43}
44
45/* A static module */
46
47/* 'self' is not used */
48static PyObject *
49xyzzy_foo(PyObject *self, PyObject* args)
50{
51 return PyInt_FromLong(42L);
52}
53
54static PyMethodDef xyzzy_methods[] = {
55 {"foo", xyzzy_foo, METH_NOARGS,
56 "Return the meaning of everything."},
57 {NULL, NULL} /* sentinel */
58};
59
60void
61initxyzzy(void)
62{
63 PyImport_AddModule("xyzzy");
64 Py_InitModule("xyzzy", xyzzy_methods);
65}
sys/src/cmd/python/Demo/embed/importexc.c+17−0
@@ -0,0 +1,17 @@
1#include <Python.h>
2
3char* cmd = "import exceptions";
4
5int main()
6{
7 Py_Initialize();
8 PyEval_InitThreads();
9 PyRun_SimpleString(cmd);
10 Py_EndInterpreter(PyThreadState_Get());
11
12 Py_NewInterpreter();
13 PyRun_SimpleString(cmd);
14 Py_Finalize();
15
16 return 0;
17}
sys/src/cmd/python/Demo/embed/loop.c+33−0
@@ -0,0 +1,33 @@
1/* Simple program that repeatedly calls Py_Initialize(), does something, and
2 then calls Py_Finalize(). This should help finding leaks related to
3 initialization. */
4
5#include "Python.h"
6
7main(int argc, char **argv)
8{
9 int count = -1;
10 char *command;
11
12 if (argc < 2 || argc > 3) {
13 fprintf(stderr, "usage: loop <python-command> [count]\n");
14 exit(2);
15 }
16 command = argv[1];
17
18 if (argc == 3) {
19 count = atoi(argv[2]);
20 }
21
22 Py_SetProgramName(argv[0]);
23
24 /* uncomment this if you don't want to load site.py */
25 /* Py_NoSiteFlag = 1; */
26
27 while (count == -1 || --count >= 0 ) {
28 Py_Initialize();
29 PyRun_SimpleString(command);
30 Py_Finalize();
31 }
32 return 0;
33}
sys/src/cmd/python/Demo/imputil/importers.py+248−0
@@ -0,0 +1,248 @@
1#
2# importers.py
3#
4# Demonstration subclasses of imputil.Importer
5#
6
7# There should be consideration for the imports below if it is desirable
8# to have "all" modules be imported through the imputil system.
9
10# these are C extensions
11import sys
12import imp
13import struct
14import marshal
15
16# these are .py modules
17import imputil
18import os
19
20######################################################################
21
22_TupleType = type(())
23_StringType = type('')
24
25######################################################################
26
27# byte-compiled file suffic character
28_suffix_char = __debug__ and 'c' or 'o'
29
30# byte-compiled file suffix
31_suffix = '.py' + _suffix_char
32
33# the C_EXTENSION suffixes
34_c_suffixes = filter(lambda x: x[2] == imp.C_EXTENSION, imp.get_suffixes())
35
36def _timestamp(pathname):
37 "Return the file modification time as a Long."
38 try:
39 s = os.stat(pathname)
40 except OSError:
41 return None
42 return long(s[8])
43
44def _fs_import(dir, modname, fqname):
45 "Fetch a module from the filesystem."
46
47 pathname = os.path.join(dir, modname)
48 if os.path.isdir(pathname):
49 values = { '__pkgdir__' : pathname, '__path__' : [ pathname ] }
50 ispkg = 1
51 pathname = os.path.join(pathname, '__init__')
52 else:
53 values = { }
54 ispkg = 0
55
56 # look for dynload modules
57 for desc in _c_suffixes:
58 file = pathname + desc[0]
59 try:
60 fp = open(file, desc[1])
61 except IOError:
62 pass
63 else:
64 module = imp.load_module(fqname, fp, file, desc)
65 values['__file__'] = file
66 return 0, module, values
67
68 t_py = _timestamp(pathname + '.py')
69 t_pyc = _timestamp(pathname + _suffix)
70 if t_py is None and t_pyc is None:
71 return None
72 code = None
73 if t_py is None or (t_pyc is not None and t_pyc >= t_py):
74 file = pathname + _suffix
75 f = open(file, 'rb')
76 if f.read(4) == imp.get_magic():
77 t = struct.unpack('<I', f.read(4))[0]
78 if t == t_py:
79 code = marshal.load(f)
80 f.close()
81 if code is None:
82 file = pathname + '.py'
83 code = _compile(file, t_py)
84
85 values['__file__'] = file
86 return ispkg, code, values
87
88######################################################################
89#
90# Simple function-based importer
91#
92class FuncImporter(imputil.Importer):
93 "Importer subclass to delegate to a function rather than method overrides."
94 def __init__(self, func):
95 self.func = func
96 def get_code(self, parent, modname, fqname):
97 return self.func(parent, modname, fqname)
98
99def install_with(func):
100 FuncImporter(func).install()
101
102
103######################################################################
104#
105# Base class for archive-based importing
106#
107class PackageArchiveImporter(imputil.Importer):
108 """Importer subclass to import from (file) archives.
109
110 This Importer handles imports of the style <archive>.<subfile>, where
111 <archive> can be located using a subclass-specific mechanism and the
112 <subfile> is found in the archive using a subclass-specific mechanism.
113
114 This class defines two hooks for subclasses: one to locate an archive
115 (and possibly return some context for future subfile lookups), and one
116 to locate subfiles.
117 """
118
119 def get_code(self, parent, modname, fqname):
120 if parent:
121 # the Importer._finish_import logic ensures that we handle imports
122 # under the top level module (package / archive).
123 assert parent.__importer__ == self
124
125 # if a parent "package" is provided, then we are importing a
126 # sub-file from the archive.
127 result = self.get_subfile(parent.__archive__, modname)
128 if result is None:
129 return None
130 if isinstance(result, _TupleType):
131 assert len(result) == 2
132 return (0,) + result
133 return 0, result, {}
134
135 # no parent was provided, so the archive should exist somewhere on the
136 # default "path".
137 archive = self.get_archive(modname)
138 if archive is None:
139 return None
140 return 1, "", {'__archive__':archive}
141
142 def get_archive(self, modname):
143 """Get an archive of modules.
144
145 This method should locate an archive and return a value which can be
146 used by get_subfile to load modules from it. The value may be a simple
147 pathname, an open file, or a complex object that caches information
148 for future imports.
149
150 Return None if the archive was not found.
151 """
152 raise RuntimeError, "get_archive not implemented"
153
154 def get_subfile(self, archive, modname):
155 """Get code from a subfile in the specified archive.
156
157 Given the specified archive (as returned by get_archive()), locate
158 and return a code object for the specified module name.
159
160 A 2-tuple may be returned, consisting of a code object and a dict
161 of name/values to place into the target module.
162
163 Return None if the subfile was not found.
164 """
165 raise RuntimeError, "get_subfile not implemented"
166
167
168class PackageArchive(PackageArchiveImporter):
169 "PackageArchiveImporter subclass that refers to a specific archive."
170
171 def __init__(self, modname, archive_pathname):
172 self.__modname = modname
173 self.__path = archive_pathname
174
175 def get_archive(self, modname):
176 if modname == self.__modname:
177 return self.__path
178 return None
179
180 # get_subfile is passed the full pathname of the archive
181
182
183######################################################################
184#
185# Emulate the standard directory-based import mechanism
186#
187class DirectoryImporter(imputil.Importer):
188 "Importer subclass to emulate the standard importer."
189
190 def __init__(self, dir):
191 self.dir = dir
192
193 def get_code(self, parent, modname, fqname):
194 if parent:
195 dir = parent.__pkgdir__
196 else:
197 dir = self.dir
198
199 # Return the module (and other info) if found in the specified
200 # directory. Otherwise, return None.
201 return _fs_import(dir, modname, fqname)
202
203 def __repr__(self):
204 return '<%s.%s for "%s" at 0x%x>' % (self.__class__.__module__,
205 self.__class__.__name__,
206 self.dir,
207 id(self))
208
209
210######################################################################
211#
212# Emulate the standard path-style import mechanism
213#
214class PathImporter(imputil.Importer):
215 def __init__(self, path=sys.path):
216 self.path = path
217
218 def get_code(self, parent, modname, fqname):
219 if parent:
220 # we are looking for a module inside of a specific package
221 return _fs_import(parent.__pkgdir__, modname, fqname)
222
223 # scan sys.path, looking for the requested module
224 for dir in self.path:
225 if isinstance(dir, _StringType):
226 result = _fs_import(dir, modname, fqname)
227 if result:
228 return result
229
230 # not found
231 return None
232
233######################################################################
234
235def _test_dir():
236 "Debug/test function to create DirectoryImporters from sys.path."
237 imputil.ImportManager().install()
238 path = sys.path[:]
239 path.reverse()
240 for d in path:
241 sys.path.insert(0, DirectoryImporter(d))
242 sys.path.insert(0, imputil.BuiltinImporter())
243
244def _test_revamp():
245 "Debug/test function for the revamped import system."
246 imputil.ImportManager().install()
247 sys.path.insert(0, PathImporter())
248 sys.path.insert(0, imputil.BuiltinImporter())
sys/src/cmd/python/Demo/imputil/knee.py+126−0
@@ -0,0 +1,126 @@
1"""An Python re-implementation of hierarchical module import.
2
3This code is intended to be read, not executed. However, it does work
4-- all you need to do to enable it is "import knee".
5
6(The name is a pun on the klunkier predecessor of this module, "ni".)
7
8"""
9
10import sys, imp, __builtin__
11
12
13# Replacement for __import__()
14def import_hook(name, globals=None, locals=None, fromlist=None):
15 parent = determine_parent(globals)
16 q, tail = find_head_package(parent, name)
17 m = load_tail(q, tail)
18 if not fromlist:
19 return q
20 if hasattr(m, "__path__"):
21 ensure_fromlist(m, fromlist)
22 return m
23
24def determine_parent(globals):
25 if not globals or not globals.has_key("__name__"):
26 return None
27 pname = globals['__name__']
28 if globals.has_key("__path__"):
29 parent = sys.modules[pname]
30 assert globals is parent.__dict__
31 return parent
32 if '.' in pname:
33 i = pname.rfind('.')
34 pname = pname[:i]
35 parent = sys.modules[pname]
36 assert parent.__name__ == pname
37 return parent
38 return None
39
40def find_head_package(parent, name):
41 if '.' in name:
42 i = name.find('.')
43 head = name[:i]
44 tail = name[i+1:]
45 else:
46 head = name
47 tail = ""
48 if parent:
49 qname = "%s.%s" % (parent.__name__, head)
50 else:
51 qname = head
52 q = import_module(head, qname, parent)
53 if q: return q, tail
54 if parent:
55 qname = head
56 parent = None
57 q = import_module(head, qname, parent)
58 if q: return q, tail
59 raise ImportError, "No module named " + qname
60
61def load_tail(q, tail):
62 m = q
63 while tail:
64 i = tail.find('.')
65 if i < 0: i = len(tail)
66 head, tail = tail[:i], tail[i+1:]
67 mname = "%s.%s" % (m.__name__, head)
68 m = import_module(head, mname, m)
69 if not m:
70 raise ImportError, "No module named " + mname
71 return m
72
73def ensure_fromlist(m, fromlist, recursive=0):
74 for sub in fromlist:
75 if sub == "*":
76 if not recursive:
77 try:
78 all = m.__all__
79 except AttributeError:
80 pass
81 else:
82 ensure_fromlist(m, all, 1)
83 continue
84 if sub != "*" and not hasattr(m, sub):
85 subname = "%s.%s" % (m.__name__, sub)
86 submod = import_module(sub, subname, m)
87 if not submod:
88 raise ImportError, "No module named " + subname
89
90def import_module(partname, fqname, parent):
91 try:
92 return sys.modules[fqname]
93 except KeyError:
94 pass
95 try:
96 fp, pathname, stuff = imp.find_module(partname,
97 parent and parent.__path__)
98 except ImportError:
99 return None
100 try:
101 m = imp.load_module(fqname, fp, pathname, stuff)
102 finally:
103 if fp: fp.close()
104 if parent:
105 setattr(parent, partname, m)
106 return m
107
108
109# Replacement for reload()
110def reload_hook(module):
111 name = module.__name__
112 if '.' not in name:
113 return import_module(name, name, None)
114 i = name.rfind('.')
115 pname = name[:i]
116 parent = sys.modules[pname]
117 return import_module(name[i+1:], name, parent)
118
119
120# Save the original hooks
121original_import = __builtin__.__import__
122original_reload = __builtin__.reload
123
124# Now install our hooks
125__builtin__.__import__ = import_hook
126__builtin__.reload = reload_hook
sys/src/cmd/python/Demo/md5test/README+10−0
@@ -0,0 +1,10 @@
1This is the Python version of the MD5 test program from the MD5
2Internet Draft (Rivest and Dusse, The MD5 Message-Digest Algorithm, 10
3July 1991). The file "foo" contains the string "abc" with no trailing
4newline.
5
6When called without arguments, it acts as a filter. When called with
7"-x", it executes a self-test, and the output should literally match
8the output given in the RFC.
9
10Code by Jan-Hein B\"uhrman after the original in C.
sys/src/cmd/python/Demo/md5test/foo+1−0
@@ -0,0 +1 @@
1abc
sys/src/cmd/python/Demo/md5test/md5driver.py+123−0
@@ -0,0 +1,123 @@
1import string
2import md5
3from sys import argv
4
5def MDPrint(str):
6 outstr = ''
7 for i in str:
8 o = ord(i)
9 outstr = (outstr
10 + string.hexdigits[(o >> 4) & 0xF]
11 + string.hexdigits[o & 0xF])
12 print outstr,
13
14
15from time import time
16
17def makestr(start, end):
18 result = ''
19 for i in range(start, end + 1):
20 result = result + chr(i)
21
22 return result
23
24
25def MDTimeTrial():
26 TEST_BLOCK_SIZE = 1000
27 TEST_BLOCKS = 10000
28
29 TEST_BYTES = TEST_BLOCK_SIZE * TEST_BLOCKS
30
31 # initialize test data, need temporary string filler
32
33 filsiz = 1 << 8
34 filler = makestr(0, filsiz-1)
35 data = filler * (TEST_BLOCK_SIZE / filsiz);
36 data = data + filler[:(TEST_BLOCK_SIZE % filsiz)]
37
38 del filsiz, filler
39
40
41 # start timer
42 print 'MD5 time trial. Processing', TEST_BYTES, 'characters...'
43 t1 = time()
44
45 mdContext = md5.new()
46
47 for i in range(TEST_BLOCKS):
48 mdContext.update(data)
49
50 str = mdContext.digest()
51 t2 = time()
52
53 MDPrint(str)
54 print 'is digest of test input.'
55 print 'Seconds to process test input:', t2 - t1
56 print 'Characters processed per second:', TEST_BYTES / (t2 - t1)
57
58
59def MDString(str):
60 MDPrint(md5.new(str).digest())
61 print '"' + str + '"'
62
63
64def MDFile(filename):
65 f = open(filename, 'rb');
66 mdContext = md5.new()
67
68 while 1:
69 data = f.read(1024)
70 if not data:
71 break
72 mdContext.update(data)
73
74 MDPrint(mdContext.digest())
75 print filename
76
77
78import sys
79
80def MDFilter():
81 mdContext = md5.new()
82
83 while 1:
84 data = sys.stdin.read(16)
85 if not data:
86 break
87 mdContext.update(data)
88
89 MDPrint(mdContext.digest())
90 print
91
92
93def MDTestSuite():
94 print 'MD5 test suite results:'
95 MDString('')
96 MDString('a')
97 MDString('abc')
98 MDString('message digest')
99 MDString(makestr(ord('a'), ord('z')))
100 MDString(makestr(ord('A'), ord('Z'))
101 + makestr(ord('a'), ord('z'))
102 + makestr(ord('0'), ord('9')))
103 MDString((makestr(ord('1'), ord('9')) + '0') * 8)
104
105 # Contents of file foo are "abc"
106 MDFile('foo')
107
108
109# I don't wanna use getopt(), since I want to use the same i/f...
110def main():
111 if len(argv) == 1:
112 MDFilter()
113 for arg in argv[1:]:
114 if arg[:2] == '-s':
115 MDString(arg[2:])
116 elif arg == '-t':
117 MDTimeTrial()
118 elif arg == '-x':
119 MDTestSuite()
120 else:
121 MDFile(arg)
122
123main()
sys/src/cmd/python/Demo/metaclasses/Eiffel.py+113−0
@@ -0,0 +1,113 @@
1"""Support Eiffel-style preconditions and postconditions.
2
3For example,
4
5class C:
6 def m1(self, arg):
7 require arg > 0
8 return whatever
9 ensure Result > arg
10
11can be written (clumsily, I agree) as:
12
13class C(Eiffel):
14 def m1(self, arg):
15 return whatever
16 def m1_pre(self, arg):
17 assert arg > 0
18 def m1_post(self, Result, arg):
19 assert Result > arg
20
21Pre- and post-conditions for a method, being implemented as methods
22themselves, are inherited independently from the method. This gives
23much of the same effect of Eiffel, where pre- and post-conditions are
24inherited when a method is overridden by a derived class. However,
25when a derived class in Python needs to extend a pre- or
26post-condition, it must manually merge the base class' pre- or
27post-condition with that defined in the derived class', for example:
28
29class D(C):
30 def m1(self, arg):
31 return arg**2
32 def m1_post(self, Result, arg):
33 C.m1_post(self, Result, arg)
34 assert Result < 100
35
36This gives derived classes more freedom but also more responsibility
37than in Eiffel, where the compiler automatically takes care of this.
38
39In Eiffel, pre-conditions combine using contravariance, meaning a
40derived class can only make a pre-condition weaker; in Python, this is
41up to the derived class. For example, a derived class that takes away
42the requirement that arg > 0 could write:
43
44 def m1_pre(self, arg):
45 pass
46
47but one could equally write a derived class that makes a stronger
48requirement:
49
50 def m1_pre(self, arg):
51 require arg > 50
52
53It would be easy to modify the classes shown here so that pre- and
54post-conditions can be disabled (separately, on a per-class basis).
55
56A different design would have the pre- or post-condition testing
57functions return true for success and false for failure. This would
58make it possible to implement automatic combination of inherited
59and new pre-/post-conditions. All this is left as an exercise to the
60reader.
61
62"""
63
64from Meta import MetaClass, MetaHelper, MetaMethodWrapper
65
66class EiffelMethodWrapper(MetaMethodWrapper):
67
68 def __init__(self, func, inst):
69 MetaMethodWrapper.__init__(self, func, inst)
70 # Note that the following causes recursive wrappers around
71 # the pre-/post-condition testing methods. These are harmless
72 # but inefficient; to avoid them, the lookup must be done
73 # using the class.
74 try:
75 self.pre = getattr(inst, self.__name__ + "_pre")
76 except AttributeError:
77 self.pre = None
78 try:
79 self.post = getattr(inst, self.__name__ + "_post")
80 except AttributeError:
81 self.post = None
82
83 def __call__(self, *args, **kw):
84 if self.pre:
85 apply(self.pre, args, kw)
86 Result = apply(self.func, (self.inst,) + args, kw)
87 if self.post:
88 apply(self.post, (Result,) + args, kw)
89 return Result
90
91class EiffelHelper(MetaHelper):
92 __methodwrapper__ = EiffelMethodWrapper
93
94class EiffelMetaClass(MetaClass):
95 __helper__ = EiffelHelper
96
97Eiffel = EiffelMetaClass('Eiffel', (), {})
98
99
100def _test():
101 class C(Eiffel):
102 def m1(self, arg):
103 return arg+1
104 def m1_pre(self, arg):
105 assert arg > 0, "precondition for m1 failed"
106 def m1_post(self, Result, arg):
107 assert Result > arg
108 x = C()
109 x.m1(12)
110## x.m1(-1)
111
112if __name__ == '__main__':
113 _test()
sys/src/cmd/python/Demo/metaclasses/Enum.py+169−0
@@ -0,0 +1,169 @@
1"""Enumeration metaclass.
2
3XXX This is very much a work in progress.
4
5"""
6
7import string
8
9class EnumMetaClass:
10 """Metaclass for enumeration.
11
12 To define your own enumeration, do something like
13
14 class Color(Enum):
15 red = 1
16 green = 2
17 blue = 3
18
19 Now, Color.red, Color.green and Color.blue behave totally
20 different: they are enumerated values, not integers.
21
22 Enumerations cannot be instantiated; however they can be
23 subclassed.
24
25 """
26
27 def __init__(self, name, bases, dict):
28 """Constructor -- create an enumeration.
29
30 Called at the end of the class statement. The arguments are
31 the name of the new class, a tuple containing the base
32 classes, and a dictionary containing everything that was
33 entered in the class' namespace during execution of the class
34 statement. In the above example, it would be {'red': 1,
35 'green': 2, 'blue': 3}.
36
37 """
38 for base in bases:
39 if base.__class__ is not EnumMetaClass:
40 raise TypeError, "Enumeration base class must be enumeration"
41 bases = filter(lambda x: x is not Enum, bases)
42 self.__name__ = name
43 self.__bases__ = bases
44 self.__dict = {}
45 for key, value in dict.items():
46 self.__dict[key] = EnumInstance(name, key, value)
47
48 def __getattr__(self, name):
49 """Return an enumeration value.
50
51 For example, Color.red returns the value corresponding to red.
52
53 XXX Perhaps the values should be created in the constructor?
54
55 This looks in the class dictionary and if it is not found
56 there asks the base classes.
57
58 The special attribute __members__ returns the list of names
59 defined in this class (it does not merge in the names defined
60 in base classes).
61
62 """
63 if name == '__members__':
64 return self.__dict.keys()
65
66 try:
67 return self.__dict[name]
68 except KeyError:
69 for base in self.__bases__:
70 try:
71 return getattr(base, name)
72 except AttributeError:
73 continue
74
75 raise AttributeError, name
76
77 def __repr__(self):
78 s = self.__name__
79 if self.__bases__:
80 s = s + '(' + string.join(map(lambda x: x.__name__,
81 self.__bases__), ", ") + ')'
82 if self.__dict:
83 list = []
84 for key, value in self.__dict.items():
85 list.append("%s: %s" % (key, int(value)))
86 s = "%s: {%s}" % (s, string.join(list, ", "))
87 return s
88
89
90class EnumInstance:
91 """Class to represent an enumeration value.
92
93 EnumInstance('Color', 'red', 12) prints as 'Color.red' and behaves
94 like the integer 12 when compared, but doesn't support arithmetic.
95
96 XXX Should it record the actual enumeration rather than just its
97 name?
98
99 """
100
101 def __init__(self, classname, enumname, value):
102 self.__classname = classname
103 self.__enumname = enumname
104 self.__value = value
105
106 def __int__(self):
107 return self.__value
108
109 def __repr__(self):
110 return "EnumInstance(%r, %r, %r)" % (self.__classname,
111 self.__enumname,
112 self.__value)
113
114 def __str__(self):
115 return "%s.%s" % (self.__classname, self.__enumname)
116
117 def __cmp__(self, other):
118 return cmp(self.__value, int(other))
119
120
121# Create the base class for enumerations.
122# It is an empty enumeration.
123Enum = EnumMetaClass("Enum", (), {})
124
125
126def _test():
127
128 class Color(Enum):
129 red = 1
130 green = 2
131 blue = 3
132
133 print Color.red
134 print dir(Color)
135
136 print Color.red == Color.red
137 print Color.red == Color.blue
138 print Color.red == 1
139 print Color.red == 2
140
141 class ExtendedColor(Color):
142 white = 0
143 orange = 4
144 yellow = 5
145 purple = 6
146 black = 7
147
148 print ExtendedColor.orange
149 print ExtendedColor.red
150
151 print Color.red == ExtendedColor.red
152
153 class OtherColor(Enum):
154 white = 4
155 blue = 5
156
157 class MergedColor(Color, OtherColor):
158 pass
159
160 print MergedColor.red
161 print MergedColor.white
162
163 print Color
164 print ExtendedColor
165 print OtherColor
166 print MergedColor
167
168if __name__ == '__main__':
169 _test()
sys/src/cmd/python/Demo/metaclasses/Meta.py+118−0
@@ -0,0 +1,118 @@
1"""Generic metaclass.
2
3XXX This is very much a work in progress.
4
5"""
6
7import types
8
9class MetaMethodWrapper:
10
11 def __init__(self, func, inst):
12 self.func = func
13 self.inst = inst
14 self.__name__ = self.func.__name__
15
16 def __call__(self, *args, **kw):
17 return apply(self.func, (self.inst,) + args, kw)
18
19class MetaHelper:
20
21 __methodwrapper__ = MetaMethodWrapper # For derived helpers to override
22
23 def __helperinit__(self, formalclass):
24 self.__formalclass__ = formalclass
25
26 def __getattr__(self, name):
27 # Invoked for any attr not in the instance's __dict__
28 try:
29 raw = self.__formalclass__.__getattr__(name)
30 except AttributeError:
31 try:
32 ga = self.__formalclass__.__getattr__('__usergetattr__')
33 except (KeyError, AttributeError):
34 raise AttributeError, name
35 return ga(self, name)
36 if type(raw) != types.FunctionType:
37 return raw
38 return self.__methodwrapper__(raw, self)
39
40class MetaClass:
41
42 """A generic metaclass.
43
44 This can be subclassed to implement various kinds of meta-behavior.
45
46 """
47
48 __helper__ = MetaHelper # For derived metaclasses to override
49
50 __inited = 0
51
52 def __init__(self, name, bases, dict):
53 try:
54 ga = dict['__getattr__']
55 except KeyError:
56 pass
57 else:
58 dict['__usergetattr__'] = ga
59 del dict['__getattr__']
60 self.__name__ = name
61 self.__bases__ = bases
62 self.__realdict__ = dict
63 self.__inited = 1
64
65 def __getattr__(self, name):
66 try:
67 return self.__realdict__[name]
68 except KeyError:
69 for base in self.__bases__:
70 try:
71 return base.__getattr__(name)
72 except AttributeError:
73 pass
74 raise AttributeError, name
75
76 def __setattr__(self, name, value):
77 if not self.__inited:
78 self.__dict__[name] = value
79 else:
80 self.__realdict__[name] = value
81
82 def __call__(self, *args, **kw):
83 inst = self.__helper__()
84 inst.__helperinit__(self)
85 try:
86 init = inst.__getattr__('__init__')
87 except AttributeError:
88 init = lambda: None
89 apply(init, args, kw)
90 return inst
91
92
93Meta = MetaClass('Meta', (), {})
94
95
96def _test():
97 class C(Meta):
98 def __init__(self, *args):
99 print "__init__, args =", args
100 def m1(self, x):
101 print "m1(x=%r)" % (x,)
102 print C
103 x = C()
104 print x
105 x.m1(12)
106 class D(C):
107 def __getattr__(self, name):
108 if name[:2] == '__': raise AttributeError, name
109 return "getattr:%s" % name
110 x = D()
111 print x.foo
112 print x._foo
113## print x.__foo
114## print x.__foo__
115
116
117if __name__ == '__main__':
118 _test()
sys/src/cmd/python/Demo/metaclasses/Simple.py+45−0
@@ -0,0 +1,45 @@
1import types
2
3class Tracing:
4 def __init__(self, name, bases, namespace):
5 """Create a new class."""
6 self.__name__ = name
7 self.__bases__ = bases
8 self.__namespace__ = namespace
9 def __call__(self):
10 """Create a new instance."""
11 return Instance(self)
12
13class Instance:
14 def __init__(self, klass):
15 self.__klass__ = klass
16 def __getattr__(self, name):
17 try:
18 value = self.__klass__.__namespace__[name]
19 except KeyError:
20 raise AttributeError, name
21 if type(value) is not types.FunctionType:
22 return value
23 return BoundMethod(value, self)
24
25class BoundMethod:
26 def __init__(self, function, instance):
27 self.function = function
28 self.instance = instance
29 def __call__(self, *args):
30 print "calling", self.function, "for", self.instance, "with", args
31 return apply(self.function, (self.instance,) + args)
32
33Trace = Tracing('Trace', (), {})
34
35class MyTracedClass(Trace):
36 def method1(self, a):
37 self.a = a
38 def method2(self):
39 return self.a
40
41aninstance = MyTracedClass()
42
43aninstance.method1(10)
44
45print aninstance.method2()
sys/src/cmd/python/Demo/metaclasses/Synch.py+256−0
@@ -0,0 +1,256 @@
1"""Synchronization metaclass.
2
3This metaclass makes it possible to declare synchronized methods.
4
5"""
6
7import thread
8
9# First we need to define a reentrant lock.
10# This is generally useful and should probably be in a standard Python
11# library module. For now, we in-line it.
12
13class Lock:
14
15 """Reentrant lock.
16
17 This is a mutex-like object which can be acquired by the same
18 thread more than once. It keeps a reference count of the number
19 of times it has been acquired by the same thread. Each acquire()
20 call must be matched by a release() call and only the last
21 release() call actually releases the lock for acquisition by
22 another thread.
23
24 The implementation uses two locks internally:
25
26 __mutex is a short term lock used to protect the instance variables
27 __wait is the lock for which other threads wait
28
29 A thread intending to acquire both locks should acquire __wait
30 first.
31
32 The implementation uses two other instance variables, protected by
33 locking __mutex:
34
35 __tid is the thread ID of the thread that currently has the lock
36 __count is the number of times the current thread has acquired it
37
38 When the lock is released, __tid is None and __count is zero.
39
40 """
41
42 def __init__(self):
43 """Constructor. Initialize all instance variables."""
44 self.__mutex = thread.allocate_lock()
45 self.__wait = thread.allocate_lock()
46 self.__tid = None
47 self.__count = 0
48
49 def acquire(self, flag=1):
50 """Acquire the lock.
51
52 If the optional flag argument is false, returns immediately
53 when it cannot acquire the __wait lock without blocking (it
54 may still block for a little while in order to acquire the
55 __mutex lock).
56
57 The return value is only relevant when the flag argument is
58 false; it is 1 if the lock is acquired, 0 if not.
59
60 """
61 self.__mutex.acquire()
62 try:
63 if self.__tid == thread.get_ident():
64 self.__count = self.__count + 1
65 return 1
66 finally:
67 self.__mutex.release()
68 locked = self.__wait.acquire(flag)
69 if not flag and not locked:
70 return 0
71 try:
72 self.__mutex.acquire()
73 assert self.__tid == None
74 assert self.__count == 0
75 self.__tid = thread.get_ident()
76 self.__count = 1
77 return 1
78 finally:
79 self.__mutex.release()
80
81 def release(self):
82 """Release the lock.
83
84 If this thread doesn't currently have the lock, an assertion
85 error is raised.
86
87 Only allow another thread to acquire the lock when the count
88 reaches zero after decrementing it.
89
90 """
91 self.__mutex.acquire()
92 try:
93 assert self.__tid == thread.get_ident()
94 assert self.__count > 0
95 self.__count = self.__count - 1
96 if self.__count == 0:
97 self.__tid = None
98 self.__wait.release()
99 finally:
100 self.__mutex.release()
101
102
103def _testLock():
104
105 done = []
106
107 def f2(lock, done=done):
108 lock.acquire()
109 print "f2 running in thread %d\n" % thread.get_ident(),
110 lock.release()
111 done.append(1)
112
113 def f1(lock, f2=f2, done=done):
114 lock.acquire()
115 print "f1 running in thread %d\n" % thread.get_ident(),
116 try:
117 f2(lock)
118 finally:
119 lock.release()
120 done.append(1)
121
122 lock = Lock()
123 lock.acquire()
124 f1(lock) # Adds 2 to done
125 lock.release()
126
127 lock.acquire()
128
129 thread.start_new_thread(f1, (lock,)) # Adds 2
130 thread.start_new_thread(f1, (lock, f1)) # Adds 3
131 thread.start_new_thread(f2, (lock,)) # Adds 1
132 thread.start_new_thread(f2, (lock,)) # Adds 1
133
134 lock.release()
135 import time
136 while len(done) < 9:
137 print len(done)
138 time.sleep(0.001)
139 print len(done)
140
141
142# Now, the Locking metaclass is a piece of cake.
143# As an example feature, methods whose name begins with exactly one
144# underscore are not synchronized.
145
146from Meta import MetaClass, MetaHelper, MetaMethodWrapper
147
148class LockingMethodWrapper(MetaMethodWrapper):
149 def __call__(self, *args, **kw):
150 if self.__name__[:1] == '_' and self.__name__[1:] != '_':
151 return apply(self.func, (self.inst,) + args, kw)
152 self.inst.__lock__.acquire()
153 try:
154 return apply(self.func, (self.inst,) + args, kw)
155 finally:
156 self.inst.__lock__.release()
157
158class LockingHelper(MetaHelper):
159 __methodwrapper__ = LockingMethodWrapper
160 def __helperinit__(self, formalclass):
161 MetaHelper.__helperinit__(self, formalclass)
162 self.__lock__ = Lock()
163
164class LockingMetaClass(MetaClass):
165 __helper__ = LockingHelper
166
167Locking = LockingMetaClass('Locking', (), {})
168
169def _test():
170 # For kicks, take away the Locking base class and see it die
171 class Buffer(Locking):
172 def __init__(self, initialsize):
173 assert initialsize > 0
174 self.size = initialsize
175 self.buffer = [None]*self.size
176 self.first = self.last = 0
177 def put(self, item):
178 # Do we need to grow the buffer?
179 if (self.last+1) % self.size != self.first:
180 # Insert the new item
181 self.buffer[self.last] = item
182 self.last = (self.last+1) % self.size
183 return
184 # Double the buffer size
185 # First normalize it so that first==0 and last==size-1
186 print "buffer =", self.buffer
187 print "first = %d, last = %d, size = %d" % (
188 self.first, self.last, self.size)
189 if self.first <= self.last:
190 temp = self.buffer[self.first:self.last]
191 else:
192 temp = self.buffer[self.first:] + self.buffer[:self.last]
193 print "temp =", temp
194 self.buffer = temp + [None]*(self.size+1)
195 self.first = 0
196 self.last = self.size-1
197 self.size = self.size*2
198 print "Buffer size doubled to", self.size
199 print "new buffer =", self.buffer
200 print "first = %d, last = %d, size = %d" % (
201 self.first, self.last, self.size)
202 self.put(item) # Recursive call to test the locking
203 def get(self):
204 # Is the buffer empty?
205 if self.first == self.last:
206 raise EOFError # Avoid defining a new exception
207 item = self.buffer[self.first]
208 self.first = (self.first+1) % self.size
209 return item
210
211 def producer(buffer, wait, n=1000):
212 import time
213 i = 0
214 while i < n:
215 print "put", i
216 buffer.put(i)
217 i = i+1
218 print "Producer: done producing", n, "items"
219 wait.release()
220
221 def consumer(buffer, wait, n=1000):
222 import time
223 i = 0
224 tout = 0.001
225 while i < n:
226 try:
227 x = buffer.get()
228 if x != i:
229 raise AssertionError, \
230 "get() returned %s, expected %s" % (x, i)
231 print "got", i
232 i = i+1
233 tout = 0.001
234 except EOFError:
235 time.sleep(tout)
236 tout = tout*2
237 print "Consumer: done consuming", n, "items"
238 wait.release()
239
240 pwait = thread.allocate_lock()
241 pwait.acquire()
242 cwait = thread.allocate_lock()
243 cwait.acquire()
244 buffer = Buffer(1)
245 n = 1000
246 thread.start_new_thread(consumer, (buffer, cwait, n))
247 thread.start_new_thread(producer, (buffer, pwait, n))
248 pwait.acquire()
249 print "Producer done"
250 cwait.acquire()
251 print "All done"
252 print "buffer size ==", len(buffer.buffer)
253
254if __name__ == '__main__':
255 _testLock()
256 _test()
sys/src/cmd/python/Demo/metaclasses/Trace.py+144−0
@@ -0,0 +1,144 @@
1"""Tracing metaclass.
2
3XXX This is very much a work in progress.
4
5"""
6
7import types, sys
8
9class TraceMetaClass:
10 """Metaclass for tracing.
11
12 Classes defined using this metaclass have an automatic tracing
13 feature -- by setting the __trace_output__ instance (or class)
14 variable to a file object, trace messages about all calls are
15 written to the file. The trace formatting can be changed by
16 defining a suitable __trace_call__ method.
17
18 """
19
20 __inited = 0
21
22 def __init__(self, name, bases, dict):
23 self.__name__ = name
24 self.__bases__ = bases
25 self.__dict = dict
26 # XXX Can't define __dict__, alas
27 self.__inited = 1
28
29 def __getattr__(self, name):
30 try:
31 return self.__dict[name]
32 except KeyError:
33 for base in self.__bases__:
34 try:
35 return base.__getattr__(name)
36 except AttributeError:
37 pass
38 raise AttributeError, name
39
40 def __setattr__(self, name, value):
41 if not self.__inited:
42 self.__dict__[name] = value
43 else:
44 self.__dict[name] = value
45
46 def __call__(self, *args, **kw):
47 inst = TracingInstance()
48 inst.__meta_init__(self)
49 try:
50 init = inst.__getattr__('__init__')
51 except AttributeError:
52 init = lambda: None
53 apply(init, args, kw)
54 return inst
55
56 __trace_output__ = None
57
58class TracingInstance:
59 """Helper class to represent an instance of a tracing class."""
60
61 def __trace_call__(self, fp, fmt, *args):
62 fp.write((fmt+'\n') % args)
63
64 def __meta_init__(self, klass):
65 self.__class = klass
66
67 def __getattr__(self, name):
68 # Invoked for any attr not in the instance's __dict__
69 try:
70 raw = self.__class.__getattr__(name)
71 except AttributeError:
72 raise AttributeError, name
73 if type(raw) != types.FunctionType:
74 return raw
75 # It's a function
76 fullname = self.__class.__name__ + "." + name
77 if not self.__trace_output__ or name == '__trace_call__':
78 return NotTracingWrapper(fullname, raw, self)
79 else:
80 return TracingWrapper(fullname, raw, self)
81
82class NotTracingWrapper:
83 def __init__(self, name, func, inst):
84 self.__name__ = name
85 self.func = func
86 self.inst = inst
87 def __call__(self, *args, **kw):
88 return apply(self.func, (self.inst,) + args, kw)
89
90class TracingWrapper(NotTracingWrapper):
91 def __call__(self, *args, **kw):
92 self.inst.__trace_call__(self.inst.__trace_output__,
93 "calling %s, inst=%s, args=%s, kw=%s",
94 self.__name__, self.inst, args, kw)
95 try:
96 rv = apply(self.func, (self.inst,) + args, kw)
97 except:
98 t, v, tb = sys.exc_info()
99 self.inst.__trace_call__(self.inst.__trace_output__,
100 "returning from %s with exception %s: %s",
101 self.__name__, t, v)
102 raise t, v, tb
103 else:
104 self.inst.__trace_call__(self.inst.__trace_output__,
105 "returning from %s with value %s",
106 self.__name__, rv)
107 return rv
108
109Traced = TraceMetaClass('Traced', (), {'__trace_output__': None})
110
111
112def _test():
113 global C, D
114 class C(Traced):
115 def __init__(self, x=0): self.x = x
116 def m1(self, x): self.x = x
117 def m2(self, y): return self.x + y
118 __trace_output__ = sys.stdout
119 class D(C):
120 def m2(self, y): print "D.m2(%r)" % (y,); return C.m2(self, y)
121 __trace_output__ = None
122 x = C(4321)
123 print x
124 print x.x
125 print x.m1(100)
126 print x.m1(10)
127 print x.m2(33)
128 print x.m1(5)
129 print x.m2(4000)
130 print x.x
131
132 print C.__init__
133 print C.m2
134 print D.__init__
135 print D.m2
136
137 y = D()
138 print y
139 print y.m1(10)
140 print y.m2(100)
141 print y.x
142
143if __name__ == '__main__':
144 _test()
sys/src/cmd/python/Demo/metaclasses/index.html+605−0
@@ -0,0 +1,605 @@
1<HTML>
2
3<HEAD>
4<TITLE>Metaclasses in Python 1.5</TITLE>
5</HEAD>
6
7<BODY BGCOLOR="FFFFFF">
8
9<H1>Metaclasses in Python 1.5</H1>
10<H2>(A.k.a. The Killer Joke :-)</H2>
11
12<HR>
13
14(<i>Postscript:</i> reading this essay is probably not the best way to
15understand the metaclass hook described here. See a <A
16HREF="meta-vladimir.txt">message posted by Vladimir Marangozov</A>
17which may give a gentler introduction to the matter. You may also
18want to search Deja News for messages with "metaclass" in the subject
19posted to comp.lang.python in July and August 1998.)
20
21<HR>
22
23<P>In previous Python releases (and still in 1.5), there is something
24called the ``Don Beaudry hook'', after its inventor and champion.
25This allows C extensions to provide alternate class behavior, thereby
26allowing the Python class syntax to be used to define other class-like
27entities. Don Beaudry has used this in his infamous <A
28HREF="http://maigret.cog.brown.edu/pyutil/">MESS</A> package; Jim
29Fulton has used it in his <A
30HREF="http://www.digicool.com/releases/ExtensionClass/">Extension
31Classes</A> package. (It has also been referred to as the ``Don
32Beaudry <i>hack</i>,'' but that's a misnomer. There's nothing hackish
33about it -- in fact, it is rather elegant and deep, even though
34there's something dark to it.)
35
36<P>(On first reading, you may want to skip directly to the examples in
37the section "Writing Metaclasses in Python" below, unless you want
38your head to explode.)
39
40<P>
41
42<HR>
43
44<P>Documentation of the Don Beaudry hook has purposefully been kept
45minimal, since it is a feature of incredible power, and is easily
46abused. Basically, it checks whether the <b>type of the base
47class</b> is callable, and if so, it is called to create the new
48class.
49
50<P>Note the two indirection levels. Take a simple example:
51
52<PRE>
53class B:
54 pass
55
56class C(B):
57 pass
58</PRE>
59
60Take a look at the second class definition, and try to fathom ``the
61type of the base class is callable.''
62
63<P>(Types are not classes, by the way. See questions 4.2, 4.19 and in
64particular 6.22 in the <A
65HREF="http://www.python.org/cgi-bin/faqw.py" >Python FAQ</A>
66for more on this topic.)
67
68<P>
69
70<UL>
71
72<LI>The <b>base class</b> is B; this one's easy.<P>
73
74<LI>Since B is a class, its type is ``class''; so the <b>type of the
75base class</b> is the type ``class''. This is also known as
76types.ClassType, assuming the standard module <code>types</code> has
77been imported.<P>
78
79<LI>Now is the type ``class'' <b>callable</b>? No, because types (in
80core Python) are never callable. Classes are callable (calling a
81class creates a new instance) but types aren't.<P>
82
83</UL>
84
85<P>So our conclusion is that in our example, the type of the base
86class (of C) is not callable. So the Don Beaudry hook does not apply,
87and the default class creation mechanism is used (which is also used
88when there is no base class). In fact, the Don Beaudry hook never
89applies when using only core Python, since the type of a core object
90is never callable.
91
92<P>So what do Don and Jim do in order to use Don's hook? Write an
93extension that defines at least two new Python object types. The
94first would be the type for ``class-like'' objects usable as a base
95class, to trigger Don's hook. This type must be made callable.
96That's why we need a second type. Whether an object is callable
97depends on its type. So whether a type object is callable depends on
98<i>its</i> type, which is a <i>meta-type</i>. (In core Python there
99is only one meta-type, the type ``type'' (types.TypeType), which is
100the type of all type objects, even itself.) A new meta-type must
101be defined that makes the type of the class-like objects callable.
102(Normally, a third type would also be needed, the new ``instance''
103type, but this is not an absolute requirement -- the new class type
104could return an object of some existing type when invoked to create an
105instance.)
106
107<P>Still confused? Here's a simple device due to Don himself to
108explain metaclasses. Take a simple class definition; assume B is a
109special class that triggers Don's hook:
110
111<PRE>
112class C(B):
113 a = 1
114 b = 2
115</PRE>
116
117This can be though of as equivalent to:
118
119<PRE>
120C = type(B)('C', (B,), {'a': 1, 'b': 2})
121</PRE>
122
123If that's too dense for you, here's the same thing written out using
124temporary variables:
125
126<PRE>
127creator = type(B) # The type of the base class
128name = 'C' # The name of the new class
129bases = (B,) # A tuple containing the base class(es)
130namespace = {'a': 1, 'b': 2} # The namespace of the class statement
131C = creator(name, bases, namespace)
132</PRE>
133
134This is analogous to what happens without the Don Beaudry hook, except
135that in that case the creator function is set to the default class
136creator.
137
138<P>In either case, the creator is called with three arguments. The
139first one, <i>name</i>, is the name of the new class (as given at the
140top of the class statement). The <i>bases</i> argument is a tuple of
141base classes (a singleton tuple if there's only one base class, like
142the example). Finally, <i>namespace</i> is a dictionary containing
143the local variables collected during execution of the class statement.
144
145<P>Note that the contents of the namespace dictionary is simply
146whatever names were defined in the class statement. A little-known
147fact is that when Python executes a class statement, it enters a new
148local namespace, and all assignments and function definitions take
149place in this namespace. Thus, after executing the following class
150statement:
151
152<PRE>
153class C:
154 a = 1
155 def f(s): pass
156</PRE>
157
158the class namespace's contents would be {'a': 1, 'f': &lt;function f
159...&gt;}.
160
161<P>But enough already about writing Python metaclasses in C; read the
162documentation of <A
163HREF="http://maigret.cog.brown.edu/pyutil/">MESS</A> or <A
164HREF="http://www.digicool.com/papers/ExtensionClass.html" >Extension
165Classes</A> for more information.
166
167<P>
168
169<HR>
170
171<H2>Writing Metaclasses in Python</H2>
172
173<P>In Python 1.5, the requirement to write a C extension in order to
174write metaclasses has been dropped (though you can still do
175it, of course). In addition to the check ``is the type of the base
176class callable,'' there's a check ``does the base class have a
177__class__ attribute.'' If so, it is assumed that the __class__
178attribute refers to a class.
179
180<P>Let's repeat our simple example from above:
181
182<PRE>
183class C(B):
184 a = 1
185 b = 2
186</PRE>
187
188Assuming B has a __class__ attribute, this translates into:
189
190<PRE>
191C = B.__class__('C', (B,), {'a': 1, 'b': 2})
192</PRE>
193
194This is exactly the same as before except that instead of type(B),
195B.__class__ is invoked. If you have read <A HREF=
196"http://www.python.org/cgi-bin/faqw.py?req=show&file=faq06.022.htp"
197>FAQ question 6.22</A> you will understand that while there is a big
198technical difference between type(B) and B.__class__, they play the
199same role at different abstraction levels. And perhaps at some point
200in the future they will really be the same thing (at which point you
201would be able to derive subclasses from built-in types).
202
203<P>At this point it may be worth mentioning that C.__class__ is the
204same object as B.__class__, i.e., C's metaclass is the same as B's
205metaclass. In other words, subclassing an existing class creates a
206new (meta)inststance of the base class's metaclass.
207
208<P>Going back to the example, the class B.__class__ is instantiated,
209passing its constructor the same three arguments that are passed to
210the default class constructor or to an extension's metaclass:
211<i>name</i>, <i>bases</i>, and <i>namespace</i>.
212
213<P>It is easy to be confused by what exactly happens when using a
214metaclass, because we lose the absolute distinction between classes
215and instances: a class is an instance of a metaclass (a
216``metainstance''), but technically (i.e. in the eyes of the python
217runtime system), the metaclass is just a class, and the metainstance
218is just an instance. At the end of the class statement, the metaclass
219whose metainstance is used as a base class is instantiated, yielding a
220second metainstance (of the same metaclass). This metainstance is
221then used as a (normal, non-meta) class; instantiation of the class
222means calling the metainstance, and this will return a real instance.
223And what class is that an instance of? Conceptually, it is of course
224an instance of our metainstance; but in most cases the Python runtime
225system will see it as an instance of a a helper class used by the
226metaclass to implement its (non-meta) instances...
227
228<P>Hopefully an example will make things clearer. Let's presume we
229have a metaclass MetaClass1. It's helper class (for non-meta
230instances) is callled HelperClass1. We now (manually) instantiate
231MetaClass1 once to get an empty special base class:
232
233<PRE>
234BaseClass1 = MetaClass1("BaseClass1", (), {})
235</PRE>
236
237We can now use BaseClass1 as a base class in a class statement:
238
239<PRE>
240class MySpecialClass(BaseClass1):
241 i = 1
242 def f(s): pass
243</PRE>
244
245At this point, MySpecialClass is defined; it is a metainstance of
246MetaClass1 just like BaseClass1, and in fact the expression
247``BaseClass1.__class__ == MySpecialClass.__class__ == MetaClass1''
248yields true.
249
250<P>We are now ready to create instances of MySpecialClass. Let's
251assume that no constructor arguments are required:
252
253<PRE>
254x = MySpecialClass()
255y = MySpecialClass()
256print x.__class__, y.__class__
257</PRE>
258
259The print statement shows that x and y are instances of HelperClass1.
260How did this happen? MySpecialClass is an instance of MetaClass1
261(``meta'' is irrelevant here); when an instance is called, its
262__call__ method is invoked, and presumably the __call__ method defined
263by MetaClass1 returns an instance of HelperClass1.
264
265<P>Now let's see how we could use metaclasses -- what can we do
266with metaclasses that we can't easily do without them? Here's one
267idea: a metaclass could automatically insert trace calls for all
268method calls. Let's first develop a simplified example, without
269support for inheritance or other ``advanced'' Python features (we'll
270add those later).
271
272<PRE>
273import types
274
275class Tracing:
276 def __init__(self, name, bases, namespace):
277 """Create a new class."""
278 self.__name__ = name
279 self.__bases__ = bases
280 self.__namespace__ = namespace
281 def __call__(self):
282 """Create a new instance."""
283 return Instance(self)
284
285class Instance:
286 def __init__(self, klass):
287 self.__klass__ = klass
288 def __getattr__(self, name):
289 try:
290 value = self.__klass__.__namespace__[name]
291 except KeyError:
292 raise AttributeError, name
293 if type(value) is not types.FunctionType:
294 return value
295 return BoundMethod(value, self)
296
297class BoundMethod:
298 def __init__(self, function, instance):
299 self.function = function
300 self.instance = instance
301 def __call__(self, *args):
302 print "calling", self.function, "for", self.instance, "with", args
303 return apply(self.function, (self.instance,) + args)
304
305Trace = Tracing('Trace', (), {})
306
307class MyTracedClass(Trace):
308 def method1(self, a):
309 self.a = a
310 def method2(self):
311 return self.a
312
313aninstance = MyTracedClass()
314
315aninstance.method1(10)
316
317print "the answer is %d" % aninstance.method2()
318</PRE>
319
320Confused already? The intention is to read this from top down. The
321Tracing class is the metaclass we're defining. Its structure is
322really simple.
323
324<P>
325
326<UL>
327
328<LI>The __init__ method is invoked when a new Tracing instance is
329created, e.g. the definition of class MyTracedClass later in the
330example. It simply saves the class name, base classes and namespace
331as instance variables.<P>
332
333<LI>The __call__ method is invoked when a Tracing instance is called,
334e.g. the creation of aninstance later in the example. It returns an
335instance of the class Instance, which is defined next.<P>
336
337</UL>
338
339<P>The class Instance is the class used for all instances of classes
340built using the Tracing metaclass, e.g. aninstance. It has two
341methods:
342
343<P>
344
345<UL>
346
347<LI>The __init__ method is invoked from the Tracing.__call__ method
348above to initialize a new instance. It saves the class reference as
349an instance variable. It uses a funny name because the user's
350instance variables (e.g. self.a later in the example) live in the same
351namespace.<P>
352
353<LI>The __getattr__ method is invoked whenever the user code
354references an attribute of the instance that is not an instance
355variable (nor a class variable; but except for __init__ and
356__getattr__ there are no class variables). It will be called, for
357example, when aninstance.method1 is referenced in the example, with
358self set to aninstance and name set to the string "method1".<P>
359
360</UL>
361
362<P>The __getattr__ method looks the name up in the __namespace__
363dictionary. If it isn't found, it raises an AttributeError exception.
364(In a more realistic example, it would first have to look through the
365base classes as well.) If it is found, there are two possibilities:
366it's either a function or it isn't. If it's not a function, it is
367assumed to be a class variable, and its value is returned. If it's a
368function, we have to ``wrap'' it in instance of yet another helper
369class, BoundMethod.
370
371<P>The BoundMethod class is needed to implement a familiar feature:
372when a method is defined, it has an initial argument, self, which is
373automatically bound to the relevant instance when it is called. For
374example, aninstance.method1(10) is equivalent to method1(aninstance,
37510). In the example if this call, first a temporary BoundMethod
376instance is created with the following constructor call: temp =
377BoundMethod(method1, aninstance); then this instance is called as
378temp(10). After the call, the temporary instance is discarded.
379
380<P>
381
382<UL>
383
384<LI>The __init__ method is invoked for the constructor call
385BoundMethod(method1, aninstance). It simply saves away its
386arguments.<P>
387
388<LI>The __call__ method is invoked when the bound method instance is
389called, as in temp(10). It needs to call method1(aninstance, 10).
390However, even though self.function is now method1 and self.instance is
391aninstance, it can't call self.function(self.instance, args) directly,
392because it should work regardless of the number of arguments passed.
393(For simplicity, support for keyword arguments has been omitted.)<P>
394
395</UL>
396
397<P>In order to be able to support arbitrary argument lists, the
398__call__ method first constructs a new argument tuple. Conveniently,
399because of the notation *args in __call__'s own argument list, the
400arguments to __call__ (except for self) are placed in the tuple args.
401To construct the desired argument list, we concatenate a singleton
402tuple containing the instance with the args tuple: (self.instance,) +
403args. (Note the trailing comma used to construct the singleton
404tuple.) In our example, the resulting argument tuple is (aninstance,
40510).
406
407<P>The intrinsic function apply() takes a function and an argument
408tuple and calls the function for it. In our example, we are calling
409apply(method1, (aninstance, 10)) which is equivalent to calling
410method(aninstance, 10).
411
412<P>From here on, things should come together quite easily. The output
413of the example code is something like this:
414
415<PRE>
416calling &lt;function method1 at ae8d8&gt; for &lt;Instance instance at 95ab0&gt; with (10,)
417calling &lt;function method2 at ae900&gt; for &lt;Instance instance at 95ab0&gt; with ()
418the answer is 10
419</PRE>
420
421<P>That was about the shortest meaningful example that I could come up
422with. A real tracing metaclass (for example, <A
423HREF="#Trace">Trace.py</A> discussed below) needs to be more
424complicated in two dimensions.
425
426<P>First, it needs to support more advanced Python features such as
427class variables, inheritance, __init__ methods, and keyword arguments.
428
429<P>Second, it needs to provide a more flexible way to handle the
430actual tracing information; perhaps it should be possible to write
431your own tracing function that gets called, perhaps it should be
432possible to enable and disable tracing on a per-class or per-instance
433basis, and perhaps a filter so that only interesting calls are traced;
434it should also be able to trace the return value of the call (or the
435exception it raised if an error occurs). Even the Trace.py example
436doesn't support all these features yet.
437
438<P>
439
440<HR>
441
442<H1>Real-life Examples</H1>
443
444<P>Have a look at some very preliminary examples that I coded up to
445teach myself how to write metaclasses:
446
447<DL>
448
449<DT><A HREF="Enum.py">Enum.py</A>
450
451<DD>This (ab)uses the class syntax as an elegant way to define
452enumerated types. The resulting classes are never instantiated --
453rather, their class attributes are the enumerated values. For
454example:
455
456<PRE>
457class Color(Enum):
458 red = 1
459 green = 2
460 blue = 3
461print Color.red
462</PRE>
463
464will print the string ``Color.red'', while ``Color.red==1'' is true,
465and ``Color.red + 1'' raise a TypeError exception.
466
467<P>
468
469<DT><A NAME=Trace></A><A HREF="Trace.py">Trace.py</A>
470
471<DD>The resulting classes work much like standard
472classes, but by setting a special class or instance attribute
473__trace_output__ to point to a file, all calls to the class's methods
474are traced. It was a bit of a struggle to get this right. This
475should probably redone using the generic metaclass below.
476
477<P>
478
479<DT><A HREF="Meta.py">Meta.py</A>
480
481<DD>A generic metaclass. This is an attempt at finding out how much
482standard class behavior can be mimicked by a metaclass. The
483preliminary answer appears to be that everything's fine as long as the
484class (or its clients) don't look at the instance's __class__
485attribute, nor at the class's __dict__ attribute. The use of
486__getattr__ internally makes the classic implementation of __getattr__
487hooks tough; we provide a similar hook _getattr_ instead.
488(__setattr__ and __delattr__ are not affected.)
489(XXX Hm. Could detect presence of __getattr__ and rename it.)
490
491<P>
492
493<DT><A HREF="Eiffel.py">Eiffel.py</A>
494
495<DD>Uses the above generic metaclass to implement Eiffel style
496pre-conditions and post-conditions.
497
498<P>
499
500<DT><A HREF="Synch.py">Synch.py</A>
501
502<DD>Uses the above generic metaclass to implement synchronized
503methods.
504
505<P>
506
507<DT><A HREF="Simple.py">Simple.py</A>
508
509<DD>The example module used above.
510
511<P>
512
513</DL>
514
515<P>A pattern seems to be emerging: almost all these uses of
516metaclasses (except for Enum, which is probably more cute than useful)
517mostly work by placing wrappers around method calls. An obvious
518problem with that is that it's not easy to combine the features of
519different metaclasses, while this would actually be quite useful: for
520example, I wouldn't mind getting a trace from the test run of the
521Synch module, and it would be interesting to add preconditions to it
522as well. This needs more research. Perhaps a metaclass could be
523provided that allows stackable wrappers...
524
525<P>
526
527<HR>
528
529<H2>Things You Could Do With Metaclasses</H2>
530
531<P>There are lots of things you could do with metaclasses. Most of
532these can also be done with creative use of __getattr__, but
533metaclasses make it easier to modify the attribute lookup behavior of
534classes. Here's a partial list.
535
536<P>
537
538<UL>
539
540<LI>Enforce different inheritance semantics, e.g. automatically call
541base class methods when a derived class overrides<P>
542
543<LI>Implement class methods (e.g. if the first argument is not named
544'self')<P>
545
546<LI>Implement that each instance is initialized with <b>copies</b> of
547all class variables<P>
548
549<LI>Implement a different way to store instance variables (e.g. in a
550list kept outside the instance but indexed by the instance's id())<P>
551
552<LI>Automatically wrap or trap all or certain methods
553
554<UL>
555
556<LI>for tracing
557
558<LI>for precondition and postcondition checking
559
560<LI>for synchronized methods
561
562<LI>for automatic value caching
563
564</UL>
565<P>
566
567<LI>When an attribute is a parameterless function, call it on
568reference (to mimic it being an instance variable); same on assignment<P>
569
570<LI>Instrumentation: see how many times various attributes are used<P>
571
572<LI>Different semantics for __setattr__ and __getattr__ (e.g. disable
573them when they are being used recursively)<P>
574
575<LI>Abuse class syntax for other things<P>
576
577<LI>Experiment with automatic type checking<P>
578
579<LI>Delegation (or acquisition)<P>
580
581<LI>Dynamic inheritance patterns<P>
582
583<LI>Automatic caching of methods<P>
584
585</UL>
586
587<P>
588
589<HR>
590
591<H4>Credits</H4>
592
593<P>Many thanks to David Ascher and Donald Beaudry for their comments
594on earlier draft of this paper. Also thanks to Matt Conway and Tommy
595Burnette for putting a seed for the idea of metaclasses in my
596mind, nearly three years ago, even though at the time my response was
597``you can do that with __getattr__ hooks...'' :-)
598
599<P>
600
601<HR>
602
603</BODY>
604
605</HTML>
sys/src/cmd/python/Demo/metaclasses/meta-vladimir.txt+256−0
@@ -0,0 +1,256 @@
1Subject: Re: The metaclass saga using Python
2From: Vladimir Marangozov <Vladimir.Marangozov@imag.fr>
3To: tim_one@email.msn.com (Tim Peters)
4Cc: python-list@cwi.nl
5Date: Wed, 5 Aug 1998 15:59:06 +0200 (DFT)
6
7[Tim]
8>
9> building-on-examples-tends-to-prevent-abstract-thrashing-ly y'rs - tim
10>
11
12OK, I stand corrected. I understand that anybody's interpretation of
13the meta-class concept is likely to be difficult to digest by others.
14
15Here's another try, expressing the same thing, but using the Python
16programming model, examples and, perhaps, more popular terms.
17
181. Classes.
19
20 This is pure Python of today. Sorry about the tutorial, but it is
21 meant to illustrate the second part, which is the one we're
22 interested in and which will follow the same development scenario.
23 Besides, newbies are likely to understand that the discussion is
24 affordable even for them :-)
25
26 a) Class definition
27
28 A class is meant to define the common properties of a set of objects.
29 A class is a "package" of properties. The assembly of properties
30 in a class package is sometimes called a class structure (which isn't
31 always appropriate).
32
33 >>> class A:
34 attr1 = "Hello" # an attribute of A
35 def method1(self, *args): pass # method1 of A
36 def method2(self, *args): pass # method2 of A
37 >>>
38
39 So far, we defined the structure of the class A. The class A is
40 of type <class>. We can check this by asking Python: "what is A?"
41
42 >>> A # What is A?
43 <class __main__.A at 2023e360>
44
45 b) Class instantiation
46
47 Creating an object with the properties defined in the class A is
48 called instantiation of the class A. After an instantiation of A, we
49 obtain a new object, called an instance, which has the properties
50 packaged in the class A.
51
52 >>> a = A() # 'a' is the 1st instance of A
53 >>> a # What is 'a'?
54 <__main__.A instance at 2022b9d0>
55
56 >>> b = A() # 'b' is another instance of A
57 >>> b # What is 'b'?
58 <__main__.A instance at 2022b9c0>
59
60 The objects, 'a' and 'b', are of type <instance> and they both have
61 the same properties. Note, that 'a' and 'b' are different objects.
62 (their adresses differ). This is a bit hard to see, so let's ask Python:
63
64 >>> a == b # Is 'a' the same object as 'b'?
65 0 # No.
66
67 Instance objects have one more special property, indicating the class
68 they are an instance of. This property is named __class__.
69
70 >>> a.__class__ # What is the class of 'a'?
71 <class __main__.A at 2023e360> # 'a' is an instance of A
72 >>> b.__class__ # What is the class of 'b'?
73 <class __main__.A at 2023e360> # 'b' is an instance of A
74 >>> a.__class__ == b.__class__ # Is it really the same class A?
75 1 # Yes.
76
77 c) Class inheritance (class composition and specialization)
78
79 Classes can be defined in terms of other existing classes (and only
80 classes! -- don't bug me on this now). Thus, we can compose property
81 packages and create new ones. We reuse the property set defined
82 in a class by defining a new class, which "inherits" from the former.
83 In other words, a class B which inherits from the class A, inherits
84 the properties defined in A, or, B inherits the structure of A.
85
86 In the same time, at the definition of the new class B, we can enrich
87 the inherited set of properties by adding new ones and/or modify some
88 of the inherited properties.
89
90 >>> class B(A): # B inherits A's properties
91 attr2 = "World" # additional attr2
92 def method2(self, arg1): pass # method2 is redefined
93 def method3(self, *args): pass # additional method3
94
95 >>> B # What is B?
96 <class __main__.B at 2023e500>
97 >>> B == A # Is B the same class as A?
98 0 # No.
99
100 Classes define one special property, indicating whether a class
101 inherits the properties of another class. This property is called
102 __bases__ and it contains a list (a tuple) of the classes the new
103 class inherits from. The classes from which a class is inheriting the
104 properties are called superclasses (in Python, we call them also --
105 base classes).
106
107 >>> A.__bases__ # Does A have any superclasses?
108 () # No.
109 >>> B.__bases__ # Does B have any superclasses?
110 (<class __main__.A at 2023e360>,) # Yes. It has one superclass.
111 >>> B.__bases__[0] == A # Is it really the class A?
112 1 # Yes, it is.
113
114--------
115
116 Congratulations on getting this far! This was the hard part.
117 Now, let's continue with the easy one.
118
119--------
120
1212. Meta-classes
122
123 You have to admit, that an anonymous group of Python wizards are
124 not satisfied with the property packaging facilities presented above.
125 They say, that the Real-World bugs them with problems that cannot be
126 modelled successfully with classes. Or, that the way classes are
127 implemented in Python and the way classes and instances behave at
128 runtime isn't always appropriate for reproducing the Real-World's
129 behavior in a way that satisfies them.
130
131 Hence, what they want is the following:
132
133 a) leave objects as they are (instances of classes)
134 b) leave classes as they are (property packages and object creators)
135
136 BUT, at the same time:
137
138 c) consider classes as being instances of mysterious objects.
139 d) label mysterious objects "meta-classes".
140
141 Easy, eh?
142
143 You may ask: "Why on earth do they want to do that?".
144 They answer: "Poor soul... Go and see how cruel the Real-World is!".
145 You - fuzzy: "OK, will do!"
146
147 And here we go for another round of what I said in section 1 -- Classes.
148
149 However, be warned! The features we're going to talk about aren't fully
150 implemented yet, because the Real-World don't let wizards to evaluate
151 precisely how cruel it is, so the features are still highly-experimental.
152
153 a) Meta-class definition
154
155 A meta-class is meant to define the common properties of a set of
156 classes. A meta-class is a "package" of properties. The assembly
157 of properties in a meta-class package is sometimes called a meta-class
158 structure (which isn't always appropriate).
159
160 In Python, a meta-class definition would have looked like this:
161
162 >>> metaclass M:
163 attr1 = "Hello" # an attribute of M
164 def method1(self, *args): pass # method1 of M
165 def method2(self, *args): pass # method2 of M
166 >>>
167
168 So far, we defined the structure of the meta-class M. The meta-class
169 M is of type <metaclass>. We cannot check this by asking Python, but
170 if we could, it would have answered:
171
172 >>> M # What is M?
173 <metaclass __main__.M at 2023e4e0>
174
175 b) Meta-class instantiation
176
177 Creating an object with the properties defined in the meta-class M is
178 called instantiation of the meta-class M. After an instantiation of M,
179 we obtain a new object, called an class, but now it is called also
180 a meta-instance, which has the properties packaged in the meta-class M.
181
182 In Python, instantiating a meta-class would have looked like this:
183
184 >>> A = M() # 'A' is the 1st instance of M
185 >>> A # What is 'A'?
186 <class __main__.A at 2022b9d0>
187
188 >>> B = M() # 'B' is another instance of M
189 >>> B # What is 'B'?
190 <class __main__.B at 2022b9c0>
191
192 The metaclass-instances, A and B, are of type <class> and they both
193 have the same properties. Note, that A and B are different objects.
194 (their adresses differ). This is a bit hard to see, but if it was
195 possible to ask Python, it would have answered:
196
197 >>> A == B # Is A the same class as B?
198 0 # No.
199
200 Class objects have one more special property, indicating the meta-class
201 they are an instance of. This property is named __metaclass__.
202
203 >>> A.__metaclass__ # What is the meta-class of A?
204 <metaclass __main__.M at 2023e4e0> # A is an instance of M
205 >>> A.__metaclass__ # What is the meta-class of B?
206 <metaclass __main__.M at 2023e4e0> # B is an instance of M
207 >>> A.__metaclass__ == B.__metaclass__ # Is it the same meta-class M?
208 1 # Yes.
209
210 c) Meta-class inheritance (meta-class composition and specialization)
211
212 Meta-classes can be defined in terms of other existing meta-classes
213 (and only meta-classes!). Thus, we can compose property packages and
214 create new ones. We reuse the property set defined in a meta-class by
215 defining a new meta-class, which "inherits" from the former.
216 In other words, a meta-class N which inherits from the meta-class M,
217 inherits the properties defined in M, or, N inherits the structure of M.
218
219 In the same time, at the definition of the new meta-class N, we can
220 enrich the inherited set of properties by adding new ones and/or modify
221 some of the inherited properties.
222
223 >>> metaclass N(M): # N inherits M's properties
224 attr2 = "World" # additional attr2
225 def method2(self, arg1): pass # method2 is redefined
226 def method3(self, *args): pass # additional method3
227
228 >>> N # What is N?
229 <metaclass __main__.N at 2023e500>
230 >>> N == M # Is N the same meta-class as M?
231 0 # No.
232
233 Meta-classes define one special property, indicating whether a
234 meta-class inherits the properties of another meta-class. This property
235 is called __metabases__ and it contains a list (a tuple) of the
236 meta-classes the new meta-class inherits from. The meta-classes from
237 which a meta-class is inheriting the properties are called
238 super-meta-classes (in Python, we call them also -- super meta-bases).
239
240 >>> M.__metabases__ # Does M have any supermetaclasses?
241 () # No.
242 >>> N.__metabases__ # Does N have any supermetaclasses?
243 (<metaclass __main__.M at 2023e360>,) # Yes. It has a supermetaclass.
244 >>> N.__metabases__[0] == M # Is it really the meta-class M?
245 1 # Yes, it is.
246
247--------
248
249 Triple congratulations on getting this far!
250 Now you know everything about meta-classes and the Real-World!
251
252<unless-wizards-want-meta-classes-be-instances-of-mysterious-objects!>
253
254--
255 Vladimir MARANGOZOV | Vladimir.Marangozov@inrialpes.fr
256http://sirac.inrialpes.fr/~marangoz | tel:(+33-4)76615277 fax:76615252
sys/src/cmd/python/Demo/newmetaclasses/Eiffel.py+141−0
@@ -0,0 +1,141 @@
1"""Support Eiffel-style preconditions and postconditions."""
2
3from new import function
4
5class EiffelBaseMetaClass(type):
6
7 def __new__(meta, name, bases, dict):
8 meta.convert_methods(dict)
9 return super(EiffelBaseMetaClass, meta).__new__(meta, name, bases,
10 dict)
11
12 @classmethod
13 def convert_methods(cls, dict):
14 """Replace functions in dict with EiffelMethod wrappers.
15
16 The dict is modified in place.
17
18 If a method ends in _pre or _post, it is removed from the dict
19 regardless of whether there is a corresponding method.
20 """
21 # find methods with pre or post conditions
22 methods = []
23 for k, v in dict.iteritems():
24 if k.endswith('_pre') or k.endswith('_post'):
25 assert isinstance(v, function)
26 elif isinstance(v, function):
27 methods.append(k)
28 for m in methods:
29 pre = dict.get("%s_pre" % m)
30 post = dict.get("%s_post" % m)
31 if pre or post:
32 dict[k] = cls.make_eiffel_method(dict[m], pre, post)
33
34class EiffelMetaClass1(EiffelBaseMetaClass):
35 # an implementation of the "eiffel" meta class that uses nested functions
36
37 @staticmethod
38 def make_eiffel_method(func, pre, post):
39 def method(self, *args, **kwargs):
40 if pre:
41 pre(self, *args, **kwargs)
42 x = func(self, *args, **kwargs)
43 if post:
44 post(self, x, *args, **kwargs)
45 return x
46
47 if func.__doc__:
48 method.__doc__ = func.__doc__
49
50 return method
51
52class EiffelMethodWrapper:
53
54 def __init__(self, inst, descr):
55 self._inst = inst
56 self._descr = descr
57
58 def __call__(self, *args, **kwargs):
59 return self._descr.callmethod(self._inst, args, kwargs)
60
61class EiffelDescriptor(object):
62
63 def __init__(self, func, pre, post):
64 self._func = func
65 self._pre = pre
66 self._post = post
67
68 self.__name__ = func.__name__
69 self.__doc__ = func.__doc__
70
71 def __get__(self, obj, cls):
72 return EiffelMethodWrapper(obj, self)
73
74 def callmethod(self, inst, args, kwargs):
75 if self._pre:
76 self._pre(inst, *args, **kwargs)
77 x = self._func(inst, *args, **kwargs)
78 if self._post:
79 self._post(inst, x, *args, **kwargs)
80 return x
81
82class EiffelMetaClass2(EiffelBaseMetaClass):
83 # an implementation of the "eiffel" meta class that uses descriptors
84
85 make_eiffel_method = EiffelDescriptor
86
87def _test(metaclass):
88 class Eiffel:
89 __metaclass__ = metaclass
90
91 class Test(Eiffel):
92
93 def m(self, arg):
94 """Make it a little larger"""
95 return arg + 1
96
97 def m2(self, arg):
98 """Make it a little larger"""
99 return arg + 1
100
101 def m2_pre(self, arg):
102 assert arg > 0
103
104 def m2_post(self, result, arg):
105 assert result > arg
106
107 class Sub(Test):
108 def m2(self, arg):
109 return arg**2
110 def m2_post(self, Result, arg):
111 super(Sub, self).m2_post(Result, arg)
112 assert Result < 100
113
114 t = Test()
115 t.m(1)
116 t.m2(1)
117 try:
118 t.m2(0)
119 except AssertionError:
120 pass
121 else:
122 assert False
123
124 s = Sub()
125 try:
126 s.m2(1)
127 except AssertionError:
128 pass # result == arg
129 else:
130 assert False
131 try:
132 s.m2(10)
133 except AssertionError:
134 pass # result == 100
135 else:
136 assert False
137 s.m2(5)
138
139if __name__ == "__main__":
140 _test(EiffelMetaClass1)
141 _test(EiffelMetaClass2)
sys/src/cmd/python/Demo/newmetaclasses/Enum.py+177−0
@@ -0,0 +1,177 @@
1"""Enumeration metaclass."""
2
3class EnumMetaclass(type):
4 """Metaclass for enumeration.
5
6 To define your own enumeration, do something like
7
8 class Color(Enum):
9 red = 1
10 green = 2
11 blue = 3
12
13 Now, Color.red, Color.green and Color.blue behave totally
14 different: they are enumerated values, not integers.
15
16 Enumerations cannot be instantiated; however they can be
17 subclassed.
18 """
19
20 def __init__(cls, name, bases, dict):
21 super(EnumMetaclass, cls).__init__(name, bases, dict)
22 cls._members = []
23 for attr in dict.keys():
24 if not (attr.startswith('__') and attr.endswith('__')):
25 enumval = EnumInstance(name, attr, dict[attr])
26 setattr(cls, attr, enumval)
27 cls._members.append(attr)
28
29 def __getattr__(cls, name):
30 if name == "__members__":
31 return cls._members
32 raise AttributeError, name
33
34 def __repr__(cls):
35 s1 = s2 = ""
36 enumbases = [base.__name__ for base in cls.__bases__
37 if isinstance(base, EnumMetaclass) and not base is Enum]
38 if enumbases:
39 s1 = "(%s)" % ", ".join(enumbases)
40 enumvalues = ["%s: %d" % (val, getattr(cls, val))
41 for val in cls._members]
42 if enumvalues:
43 s2 = ": {%s}" % ", ".join(enumvalues)
44 return "%s%s%s" % (cls.__name__, s1, s2)
45
46class FullEnumMetaclass(EnumMetaclass):
47 """Metaclass for full enumerations.
48
49 A full enumeration displays all the values defined in base classes.
50 """
51
52 def __init__(cls, name, bases, dict):
53 super(FullEnumMetaclass, cls).__init__(name, bases, dict)
54 for obj in cls.__mro__:
55 if isinstance(obj, EnumMetaclass):
56 for attr in obj._members:
57 # XXX inefficient
58 if not attr in cls._members:
59 cls._members.append(attr)
60
61class EnumInstance(int):
62 """Class to represent an enumeration value.
63
64 EnumInstance('Color', 'red', 12) prints as 'Color.red' and behaves
65 like the integer 12 when compared, but doesn't support arithmetic.
66
67 XXX Should it record the actual enumeration rather than just its
68 name?
69 """
70
71 def __new__(cls, classname, enumname, value):
72 return int.__new__(cls, value)
73
74 def __init__(self, classname, enumname, value):
75 self.__classname = classname
76 self.__enumname = enumname
77
78 def __repr__(self):
79 return "EnumInstance(%s, %s, %d)" % (self.__classname, self.__enumname,
80 self)
81
82 def __str__(self):
83 return "%s.%s" % (self.__classname, self.__enumname)
84
85class Enum:
86 __metaclass__ = EnumMetaclass
87
88class FullEnum:
89 __metaclass__ = FullEnumMetaclass
90
91def _test():
92
93 class Color(Enum):
94 red = 1
95 green = 2
96 blue = 3
97
98 print Color.red
99
100 print repr(Color.red)
101 print Color.red == Color.red
102 print Color.red == Color.blue
103 print Color.red == 1
104 print Color.red == 2
105
106 class ExtendedColor(Color):
107 white = 0
108 orange = 4
109 yellow = 5
110 purple = 6
111 black = 7
112
113 print ExtendedColor.orange
114 print ExtendedColor.red
115
116 print Color.red == ExtendedColor.red
117
118 class OtherColor(Enum):
119 white = 4
120 blue = 5
121
122 class MergedColor(Color, OtherColor):
123 pass
124
125 print MergedColor.red
126 print MergedColor.white
127
128 print Color
129 print ExtendedColor
130 print OtherColor
131 print MergedColor
132
133def _test2():
134
135 class Color(FullEnum):
136 red = 1
137 green = 2
138 blue = 3
139
140 print Color.red
141
142 print repr(Color.red)
143 print Color.red == Color.red
144 print Color.red == Color.blue
145 print Color.red == 1
146 print Color.red == 2
147
148 class ExtendedColor(Color):
149 white = 0
150 orange = 4
151 yellow = 5
152 purple = 6
153 black = 7
154
155 print ExtendedColor.orange
156 print ExtendedColor.red
157
158 print Color.red == ExtendedColor.red
159
160 class OtherColor(FullEnum):
161 white = 4
162 blue = 5
163
164 class MergedColor(Color, OtherColor):
165 pass
166
167 print MergedColor.red
168 print MergedColor.white
169
170 print Color
171 print ExtendedColor
172 print OtherColor
173 print MergedColor
174
175if __name__ == '__main__':
176 _test()
177 _test2()
sys/src/cmd/python/Demo/parser/FILES+6−0
@@ -0,0 +1,6 @@
1Demo/parser
2Doc/libparser.tex
3Lib/AST.py
4Lib/symbol.py
5Lib/token.py
6Modules/parsermodule.c
sys/src/cmd/python/Demo/parser/README+31−0
@@ -0,0 +1,31 @@
1These files are from the large example of using the `parser' module. Refer
2to the Python Library Reference for more information.
3
4It also contains examples for the AST parser.
5
6Files:
7------
8
9 FILES -- list of files associated with the parser module.
10
11 README -- this file.
12
13 example.py -- module that uses the `parser' module to extract
14 information from the parse tree of Python source
15 code.
16
17 docstring.py -- sample source file containing only a module docstring.
18
19 simple.py -- sample source containing a "short form" definition.
20
21 source.py -- sample source code used to demonstrate ability to
22 handle nested constructs easily using the functions
23 and classes in example.py.
24
25 test_parser.py program to put the parser module through its paces.
26
27 unparse.py AST (2.5) based example to recreate source code
28 from an AST. This is incomplete; contributions
29 are welcome.
30
31Enjoy!
sys/src/cmd/python/Demo/parser/docstring.py+2−0
@@ -0,0 +1,2 @@
1"""Some documentation.
2"""
sys/src/cmd/python/Demo/parser/example.py+190−0
@@ -0,0 +1,190 @@
1"""Simple code to extract class & function docstrings from a module.
2
3This code is used as an example in the library reference manual in the
4section on using the parser module. Refer to the manual for a thorough
5discussion of the operation of this code.
6"""
7
8import os
9import parser
10import symbol
11import token
12import types
13
14from types import ListType, TupleType
15
16
17def get_docs(fileName):
18 """Retrieve information from the parse tree of a source file.
19
20 fileName
21 Name of the file to read Python source code from.
22 """
23 source = open(fileName).read()
24 basename = os.path.basename(os.path.splitext(fileName)[0])
25 ast = parser.suite(source)
26 return ModuleInfo(ast.totuple(), basename)
27
28
29class SuiteInfoBase:
30 _docstring = ''
31 _name = ''
32
33 def __init__(self, tree = None):
34 self._class_info = {}
35 self._function_info = {}
36 if tree:
37 self._extract_info(tree)
38
39 def _extract_info(self, tree):
40 # extract docstring
41 if len(tree) == 2:
42 found, vars = match(DOCSTRING_STMT_PATTERN[1], tree[1])
43 else:
44 found, vars = match(DOCSTRING_STMT_PATTERN, tree[3])
45 if found:
46 self._docstring = eval(vars['docstring'])
47 # discover inner definitions
48 for node in tree[1:]:
49 found, vars = match(COMPOUND_STMT_PATTERN, node)
50 if found:
51 cstmt = vars['compound']
52 if cstmt[0] == symbol.funcdef:
53 name = cstmt[2][1]
54 self._function_info[name] = FunctionInfo(cstmt)
55 elif cstmt[0] == symbol.classdef:
56 name = cstmt[2][1]
57 self._class_info[name] = ClassInfo(cstmt)
58
59 def get_docstring(self):
60 return self._docstring
61
62 def get_name(self):
63 return self._name
64
65 def get_class_names(self):
66 return self._class_info.keys()
67
68 def get_class_info(self, name):
69 return self._class_info[name]
70
71 def __getitem__(self, name):
72 try:
73 return self._class_info[name]
74 except KeyError:
75 return self._function_info[name]
76
77
78class SuiteFuncInfo:
79 # Mixin class providing access to function names and info.
80
81 def get_function_names(self):
82 return self._function_info.keys()
83
84 def get_function_info(self, name):
85 return self._function_info[name]
86
87
88class FunctionInfo(SuiteInfoBase, SuiteFuncInfo):
89 def __init__(self, tree = None):
90 self._name = tree[2][1]
91 SuiteInfoBase.__init__(self, tree and tree[-1] or None)
92
93
94class ClassInfo(SuiteInfoBase):
95 def __init__(self, tree = None):
96 self._name = tree[2][1]
97 SuiteInfoBase.__init__(self, tree and tree[-1] or None)
98
99 def get_method_names(self):
100 return self._function_info.keys()
101
102 def get_method_info(self, name):
103 return self._function_info[name]
104
105
106class ModuleInfo(SuiteInfoBase, SuiteFuncInfo):
107 def __init__(self, tree = None, name = "<string>"):
108 self._name = name
109 SuiteInfoBase.__init__(self, tree)
110 if tree:
111 found, vars = match(DOCSTRING_STMT_PATTERN, tree[1])
112 if found:
113 self._docstring = vars["docstring"]
114
115
116def match(pattern, data, vars=None):
117 """Match `data' to `pattern', with variable extraction.
118
119 pattern
120 Pattern to match against, possibly containing variables.
121
122 data
123 Data to be checked and against which variables are extracted.
124
125 vars
126 Dictionary of variables which have already been found. If not
127 provided, an empty dictionary is created.
128
129 The `pattern' value may contain variables of the form ['varname'] which
130 are allowed to match anything. The value that is matched is returned as
131 part of a dictionary which maps 'varname' to the matched value. 'varname'
132 is not required to be a string object, but using strings makes patterns
133 and the code which uses them more readable.
134
135 This function returns two values: a boolean indicating whether a match
136 was found and a dictionary mapping variable names to their associated
137 values.
138 """
139 if vars is None:
140 vars = {}
141 if type(pattern) is ListType: # 'variables' are ['varname']
142 vars[pattern[0]] = data
143 return 1, vars
144 if type(pattern) is not TupleType:
145 return (pattern == data), vars
146 if len(data) != len(pattern):
147 return 0, vars
148 for pattern, data in map(None, pattern, data):
149 same, vars = match(pattern, data, vars)
150 if not same:
151 break
152 return same, vars
153
154
155# This pattern identifies compound statements, allowing them to be readily
156# differentiated from simple statements.
157#
158COMPOUND_STMT_PATTERN = (
159 symbol.stmt,
160 (symbol.compound_stmt, ['compound'])
161 )
162
163
164# This pattern will match a 'stmt' node which *might* represent a docstring;
165# docstrings require that the statement which provides the docstring be the
166# first statement in the class or function, which this pattern does not check.
167#
168DOCSTRING_STMT_PATTERN = (
169 symbol.stmt,
170 (symbol.simple_stmt,
171 (symbol.small_stmt,
172 (symbol.expr_stmt,
173 (symbol.testlist,
174 (symbol.test,
175 (symbol.and_test,
176 (symbol.not_test,
177 (symbol.comparison,
178 (symbol.expr,
179 (symbol.xor_expr,
180 (symbol.and_expr,
181 (symbol.shift_expr,
182 (symbol.arith_expr,
183 (symbol.term,
184 (symbol.factor,
185 (symbol.power,
186 (symbol.atom,
187 (token.STRING, ['docstring'])
188 )))))))))))))))),
189 (token.NEWLINE, '')
190 ))
sys/src/cmd/python/Demo/parser/simple.py+1−0
@@ -0,0 +1 @@
1def f(): "maybe a docstring"
sys/src/cmd/python/Demo/parser/source.py+27−0
@@ -0,0 +1,27 @@
1"""Exmaple file to be parsed for the parsermodule example.
2
3The classes and functions in this module exist only to exhibit the ability
4of the handling information extraction from nested definitions using parse
5trees. They shouldn't interest you otherwise!
6"""
7
8class Simple:
9 "This class does very little."
10
11 def method(self):
12 "This method does almost nothing."
13 return 1
14
15 class Nested:
16 "This is a nested class."
17
18 def nested_method(self):
19 "Method of Nested class."
20 def nested_function():
21 "Function in method of Nested class."
22 pass
23 return nested_function
24
25def function():
26 "This function lives at the module level."
27 return 0
sys/src/cmd/python/Demo/parser/test_parser.py+48−0
@@ -0,0 +1,48 @@
1#! /usr/bin/env python
2# (Force the script to use the latest build.)
3#
4# test_parser.py
5
6import parser, traceback
7
8_numFailed = 0
9
10def testChunk(t, fileName):
11 global _numFailed
12 print '----', fileName,
13 try:
14 ast = parser.suite(t)
15 tup = parser.ast2tuple(ast)
16 # this discards the first AST; a huge memory savings when running
17 # against a large source file like Tkinter.py.
18 ast = None
19 new = parser.tuple2ast(tup)
20 except parser.ParserError, err:
21 print
22 print 'parser module raised exception on input file', fileName + ':'
23 traceback.print_exc()
24 _numFailed = _numFailed + 1
25 else:
26 if tup != parser.ast2tuple(new):
27 print
28 print 'parser module failed on input file', fileName
29 _numFailed = _numFailed + 1
30 else:
31 print 'o.k.'
32
33def testFile(fileName):
34 t = open(fileName).read()
35 testChunk(t, fileName)
36
37def test():
38 import sys
39 args = sys.argv[1:]
40 if not args:
41 import glob
42 args = glob.glob("*.py")
43 args.sort()
44 map(testFile, args)
45 sys.exit(_numFailed != 0)
46
47if __name__ == '__main__':
48 test()
sys/src/cmd/python/Demo/parser/texipre.dat+100−0
@@ -0,0 +1,100 @@
1\input texinfo @c -*-texinfo-*-
2@c %**start of header
3@setfilename parser.info
4@settitle Python Parser Module Reference
5@setchapternewpage odd
6@footnotestyle end
7@c %**end of header
8
9@ifinfo
10This file describes the interfaces
11published by the optional @code{parser} module and gives examples of
12how they may be used. It contains the same text as the chapter on the
13@code{parser} module in the @cite{Python Library Reference}, but is
14presented as a separate document.
15
16Copyright 1995-1996 by Fred L. Drake, Jr., Reston, Virginia, USA, and
17Virginia Polytechnic Institute and State University, Blacksburg,
18Virginia, USA. Portions of the software copyright 1991-1995 by
19Stichting Mathematisch Centrum, Amsterdam, The Netherlands. Copying is
20permitted under the terms associated with the main Python distribution,
21with the additional restriction that this additional notice be included
22and maintained on all distributed copies.
23
24 All Rights Reserved
25
26Permission to use, copy, modify, and distribute this software and its
27documentation for any purpose and without fee is hereby granted,
28provided that the above copyright notice appear in all copies and that
29both that copyright notice and this permission notice appear in
30supporting documentation, and that the names of Fred L. Drake, Jr. and
31Virginia Polytechnic Institute and State University not be used in
32advertising or publicity pertaining to distribution of the software
33without specific, written prior permission.
34
35FRED L. DRAKE, JR. AND VIRGINIA POLYTECHNIC INSTITUTE AND STATE
36UNIVERSITY DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
37INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
38EVENT SHALL FRED L. DRAKE, JR. OR VIRGINIA POLYTECHNIC INSTITUTE AND
39STATE UNIVERSITY BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
40DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
41PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
42TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
43PERFORMANCE OF THIS SOFTWARE.
44@end ifinfo
45
46@titlepage
47@title Python Parser Module Reference
48@author Fred L. Drake, Jr.
49
50@c The following two commands start the copyright page.
51@page
52@vskip 0pt plus 1filll
53Copyright 1995-1996 by Fred L. Drake, Jr., Reston, Virginia, USA, and
54Virginia Polytechnic Institute and State University, Blacksburg,
55Virginia, USA. Portions of the software copyright 1991-1995 by
56Stichting Mathematisch Centrum, Amsterdam, The Netherlands. Copying is
57permitted under the terms associated with the main Python distribution,
58with the additional restriction that this additional notice be included
59and maintained on all distributed copies.
60
61@center All Rights Reserved
62
63Permission to use, copy, modify, and distribute this software and its
64documentation for any purpose and without fee is hereby granted,
65provided that the above copyright notice appear in all copies and that
66both that copyright notice and this permission notice appear in
67supporting documentation, and that the names of Fred L. Drake, Jr. and
68Virginia Polytechnic Institute and State University not be used in
69advertising or publicity pertaining to distribution of the software
70without specific, written prior permission.
71
72FRED L. DRAKE, JR. AND VIRGINIA POLYTECHNIC INSTITUTE AND STATE
73UNIVERSITY DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
74INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
75EVENT SHALL FRED L. DRAKE, JR. OR VIRGINIA POLYTECHNIC INSTITUTE AND
76STATE UNIVERSITY BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
77DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
78PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
79TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
80PERFORMANCE OF THIS SOFTWARE.
81@end titlepage
82
83
84@node Top, Overview, (dir), (dir)
85@top The Python Parser Module
86
87@ifinfo
88This file describes the interfaces
89published by the optional @code{parser} module and gives examples of
90how they may be used. It contains the same text as the chapter on the
91@code{parser} module in the @cite{Python Library Reference}, but is
92presented as a separate document.
93
94This version corresponds to Python version 1.4 (1 Sept. 1996).
95
96@end ifinfo
97
98@c placeholder for the master menu -- patched by texinfo-all-menus-update
99@menu
100@end menu
sys/src/cmd/python/Demo/parser/unparse.py+519−0
@@ -0,0 +1,519 @@
1"Usage: unparse.py <path to source file>"
2import sys
3import _ast
4import cStringIO
5import os
6
7class Unparser:
8 """Methods in this class recursively traverse an AST and
9 output source code for the abstract syntax; original formatting
10 is disregarged. """
11
12 def __init__(self, tree, file = sys.stdout):
13 """Unparser(tree, file=sys.stdout) -> None.
14 Print the source for tree to file."""
15 self.f = file
16 self._indent = 0
17 self.dispatch(tree)
18 print >>self.f,""
19 self.f.flush()
20
21 def fill(self, text = ""):
22 "Indent a piece of text, according to the current indentation level"
23 self.f.write("\n"+" "*self._indent + text)
24
25 def write(self, text):
26 "Append a piece of text to the current line."
27 self.f.write(text)
28
29 def enter(self):
30 "Print ':', and increase the indentation."
31 self.write(":")
32 self._indent += 1
33
34 def leave(self):
35 "Decrease the indentation level."
36 self._indent -= 1
37
38 def dispatch(self, tree):
39 "Dispatcher function, dispatching tree type T to method _T."
40 if isinstance(tree, list):
41 for t in tree:
42 self.dispatch(t)
43 return
44 meth = getattr(self, "_"+tree.__class__.__name__)
45 meth(tree)
46
47
48 ############### Unparsing methods ######################
49 # There should be one method per concrete grammar type #
50 # Constructors should be grouped by sum type. Ideally, #
51 # this would follow the order in the grammar, but #
52 # currently doesn't. #
53 ########################################################
54
55 def _Module(self, tree):
56 for stmt in tree.body:
57 self.dispatch(stmt)
58
59 # stmt
60 def _Expr(self, tree):
61 self.fill()
62 self.dispatch(tree.value)
63
64 def _Import(self, t):
65 self.fill("import ")
66 first = True
67 for a in t.names:
68 if first:
69 first = False
70 else:
71 self.write(", ")
72 self.write(a.name)
73 if a.asname:
74 self.write(" as "+a.asname)
75
76 def _ImportFrom(self, t):
77 self.fill("from ")
78 self.write(t.module)
79 self.write(" import ")
80 for i, a in enumerate(t.names):
81 if i == 0:
82 self.write(", ")
83 self.write(a.name)
84 if a.asname:
85 self.write(" as "+a.asname)
86 # XXX(jpe) what is level for?
87
88 def _Assign(self, t):
89 self.fill()
90 for target in t.targets:
91 self.dispatch(target)
92 self.write(" = ")
93 self.dispatch(t.value)
94
95 def _AugAssign(self, t):
96 self.fill()
97 self.dispatch(t.target)
98 self.write(" "+self.binop[t.op.__class__.__name__]+"= ")
99 self.dispatch(t.value)
100
101 def _Return(self, t):
102 self.fill("return ")
103 if t.value:
104 self.dispatch(t.value)
105
106 def _Pass(self, t):
107 self.fill("pass")
108
109 def _Break(self, t):
110 self.fill("break")
111
112 def _Continue(self, t):
113 self.fill("continue")
114
115 def _Delete(self, t):
116 self.fill("del ")
117 self.dispatch(t.targets)
118
119 def _Assert(self, t):
120 self.fill("assert ")
121 self.dispatch(t.test)
122 if t.msg:
123 self.write(", ")
124 self.dispatch(t.msg)
125
126 def _Exec(self, t):
127 self.fill("exec ")
128 self.dispatch(t.body)
129 if t.globals:
130 self.write(" in ")
131 self.dispatch(t.globals)
132 if t.locals:
133 self.write(", ")
134 self.dispatch(t.locals)
135
136 def _Print(self, t):
137 self.fill("print ")
138 do_comma = False
139 if t.dest:
140 self.write(">>")
141 self.dispatch(t.dest)
142 do_comma = True
143 for e in t.values:
144 if do_comma:self.write(", ")
145 else:do_comma=True
146 self.dispatch(e)
147 if not t.nl:
148 self.write(",")
149
150 def _Global(self, t):
151 self.fill("global")
152 for i, n in enumerate(t.names):
153 if i != 0:
154 self.write(",")
155 self.write(" " + n)
156
157 def _Yield(self, t):
158 self.fill("yield")
159 if t.value:
160 self.write(" (")
161 self.dispatch(t.value)
162 self.write(")")
163
164 def _Raise(self, t):
165 self.fill('raise ')
166 if t.type:
167 self.dispatch(t.type)
168 if t.inst:
169 self.write(", ")
170 self.dispatch(t.inst)
171 if t.tback:
172 self.write(", ")
173 self.dispatch(t.tback)
174
175 def _TryExcept(self, t):
176 self.fill("try")
177 self.enter()
178 self.dispatch(t.body)
179 self.leave()
180
181 for ex in t.handlers:
182 self.dispatch(ex)
183 if t.orelse:
184 self.fill("else")
185 self.enter()
186 self.dispatch(t.orelse)
187 self.leave()
188
189 def _TryFinally(self, t):
190 self.fill("try")
191 self.enter()
192 self.dispatch(t.body)
193 self.leave()
194
195 self.fill("finally")
196 self.enter()
197 self.dispatch(t.finalbody)
198 self.leave()
199
200 def _excepthandler(self, t):
201 self.fill("except ")
202 if t.type:
203 self.dispatch(t.type)
204 if t.name:
205 self.write(", ")
206 self.dispatch(t.name)
207 self.enter()
208 self.dispatch(t.body)
209 self.leave()
210
211 def _ClassDef(self, t):
212 self.write("\n")
213 self.fill("class "+t.name)
214 if t.bases:
215 self.write("(")
216 for a in t.bases:
217 self.dispatch(a)
218 self.write(", ")
219 self.write(")")
220 self.enter()
221 self.dispatch(t.body)
222 self.leave()
223
224 def _FunctionDef(self, t):
225 self.write("\n")
226 for deco in t.decorators:
227 self.fill("@")
228 self.dispatch(deco)
229 self.fill("def "+t.name + "(")
230 self.dispatch(t.args)
231 self.write(")")
232 self.enter()
233 self.dispatch(t.body)
234 self.leave()
235
236 def _For(self, t):
237 self.fill("for ")
238 self.dispatch(t.target)
239 self.write(" in ")
240 self.dispatch(t.iter)
241 self.enter()
242 self.dispatch(t.body)
243 self.leave()
244 if t.orelse:
245 self.fill("else")
246 self.enter()
247 self.dispatch(t.orelse)
248 self.leave
249
250 def _If(self, t):
251 self.fill("if ")
252 self.dispatch(t.test)
253 self.enter()
254 # XXX elif?
255 self.dispatch(t.body)
256 self.leave()
257 if t.orelse:
258 self.fill("else")
259 self.enter()
260 self.dispatch(t.orelse)
261 self.leave()
262
263 def _While(self, t):
264 self.fill("while ")
265 self.dispatch(t.test)
266 self.enter()
267 self.dispatch(t.body)
268 self.leave()
269 if t.orelse:
270 self.fill("else")
271 self.enter()
272 self.dispatch(t.orelse)
273 self.leave
274
275 def _With(self, t):
276 self.fill("with ")
277 self.dispatch(t.context_expr)
278 if t.optional_vars:
279 self.write(" as ")
280 self.dispatch(t.optional_vars)
281 self.enter()
282 self.dispatch(t.body)
283 self.leave()
284
285 # expr
286 def _Str(self, tree):
287 self.write(repr(tree.s))
288
289 def _Name(self, t):
290 self.write(t.id)
291
292 def _Repr(self, t):
293 self.write("`")
294 self.dispatch(t.value)
295 self.write("`")
296
297 def _Num(self, t):
298 self.write(repr(t.n))
299
300 def _List(self, t):
301 self.write("[")
302 for e in t.elts:
303 self.dispatch(e)
304 self.write(", ")
305 self.write("]")
306
307 def _ListComp(self, t):
308 self.write("[")
309 self.dispatch(t.elt)
310 for gen in t.generators:
311 self.dispatch(gen)
312 self.write("]")
313
314 def _GeneratorExp(self, t):
315 self.write("(")
316 self.dispatch(t.elt)
317 for gen in t.generators:
318 self.dispatch(gen)
319 self.write(")")
320
321 def _comprehension(self, t):
322 self.write(" for ")
323 self.dispatch(t.target)
324 self.write(" in ")
325 self.dispatch(t.iter)
326 for if_clause in t.ifs:
327 self.write(" if ")
328 self.dispatch(if_clause)
329
330 def _IfExp(self, t):
331 self.dispatch(t.body)
332 self.write(" if ")
333 self.dispatch(t.test)
334 if t.orelse:
335 self.write(" else ")
336 self.dispatch(t.orelse)
337
338 def _Dict(self, t):
339 self.write("{")
340 for k,v in zip(t.keys, t.values):
341 self.dispatch(k)
342 self.write(" : ")
343 self.dispatch(v)
344 self.write(", ")
345 self.write("}")
346
347 def _Tuple(self, t):
348 if not t.elts:
349 self.write("()")
350 return
351 self.write("(")
352 for e in t.elts:
353 self.dispatch(e)
354 self.write(", ")
355 self.write(")")
356
357 unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"}
358 def _UnaryOp(self, t):
359 self.write(self.unop[t.op.__class__.__name__])
360 self.write("(")
361 self.dispatch(t.operand)
362 self.write(")")
363
364 binop = { "Add":"+", "Sub":"-", "Mult":"*", "Div":"/", "Mod":"%",
365 "LShift":">>", "RShift":"<<", "BitOr":"|", "BitXor":"^", "BitAnd":"&",
366 "FloorDiv":"//", "Pow": "**"}
367 def _BinOp(self, t):
368 self.write("(")
369 self.dispatch(t.left)
370 self.write(")" + self.binop[t.op.__class__.__name__] + "(")
371 self.dispatch(t.right)
372 self.write(")")
373
374 cmpops = {"Eq":"==", "NotEq":"!=", "Lt":"<", "LtE":"<=", "Gt":">", "GtE":">=",
375 "Is":"is", "IsNot":"is not", "In":"in", "NotIn":"not in"}
376 def _Compare(self, t):
377 self.write("(")
378 self.dispatch(t.left)
379 for o, e in zip(t.ops, t.comparators):
380 self.write(") " +self.cmpops[o.__class__.__name__] + " (")
381 self.dispatch(e)
382 self.write(")")
383
384 boolops = {_ast.And: 'and', _ast.Or: 'or'}
385 def _BoolOp(self, t):
386 self.write("(")
387 self.dispatch(t.values[0])
388 for v in t.values[1:]:
389 self.write(" %s " % self.boolops[t.op.__class__])
390 self.dispatch(v)
391 self.write(")")
392
393 def _Attribute(self,t):
394 self.dispatch(t.value)
395 self.write(".")
396 self.write(t.attr)
397
398 def _Call(self, t):
399 self.dispatch(t.func)
400 self.write("(")
401 comma = False
402 for e in t.args:
403 if comma: self.write(", ")
404 else: comma = True
405 self.dispatch(e)
406 for e in t.keywords:
407 if comma: self.write(", ")
408 else: comma = True
409 self.dispatch(e)
410 if t.starargs:
411 if comma: self.write(", ")
412 else: comma = True
413 self.write("*")
414 self.dispatch(t.starargs)
415 if t.kwargs:
416 if comma: self.write(", ")
417 else: comma = True
418 self.write("**")
419 self.dispatch(t.kwargs)
420 self.write(")")
421
422 def _Subscript(self, t):
423 self.dispatch(t.value)
424 self.write("[")
425 self.dispatch(t.slice)
426 self.write("]")
427
428 # slice
429 def _Ellipsis(self, t):
430 self.write("...")
431
432 def _Index(self, t):
433 self.dispatch(t.value)
434
435 def _Slice(self, t):
436 if t.lower:
437 self.dispatch(t.lower)
438 self.write(":")
439 if t.upper:
440 self.dispatch(t.upper)
441 if t.step:
442 self.write(":")
443 self.dispatch(t.step)
444
445 def _ExtSlice(self, t):
446 for i, d in enumerate(t.dims):
447 if i != 0:
448 self.write(': ')
449 self.dispatch(d)
450
451 # others
452 def _arguments(self, t):
453 first = True
454 nonDef = len(t.args)-len(t.defaults)
455 for a in t.args[0:nonDef]:
456 if first:first = False
457 else: self.write(", ")
458 self.dispatch(a)
459 for a,d in zip(t.args[nonDef:], t.defaults):
460 if first:first = False
461 else: self.write(", ")
462 self.dispatch(a),
463 self.write("=")
464 self.dispatch(d)
465 if t.vararg:
466 if first:first = False
467 else: self.write(", ")
468 self.write("*"+t.vararg)
469 if t.kwarg:
470 if first:first = False
471 else: self.write(", ")
472 self.write("**"+t.kwarg)
473
474 def _keyword(self, t):
475 self.write(t.arg)
476 self.write("=")
477 self.dispatch(t.value)
478
479 def _Lambda(self, t):
480 self.write("lambda ")
481 self.dispatch(t.args)
482 self.write(": ")
483 self.dispatch(t.body)
484
485def roundtrip(filename, output=sys.stdout):
486 source = open(filename).read()
487 tree = compile(source, filename, "exec", 0x400)
488 Unparser(tree, output)
489
490
491
492def testdir(a):
493 try:
494 names = [n for n in os.listdir(a) if n.endswith('.py')]
495 except OSError:
496 print >> sys.stderr, "Directory not readable: %s" % a
497 else:
498 for n in names:
499 fullname = os.path.join(a, n)
500 if os.path.isfile(fullname):
501 output = cStringIO.StringIO()
502 print 'Testing %s' % fullname
503 try:
504 roundtrip(fullname, output)
505 except Exception, e:
506 print ' Failed to compile, exception is %s' % repr(e)
507 elif os.path.isdir(fullname):
508 testdir(fullname)
509
510def main(args):
511 if args[0] == '--testdir':
512 for a in args[1:]:
513 testdir(a)
514 else:
515 for a in args:
516 roundtrip(a)
517
518if __name__=='__main__':
519 main(sys.argv[1:])
sys/src/cmd/python/Demo/pdist/FSProxy.py+322−0
@@ -0,0 +1,322 @@
1"""File System Proxy.
2
3Provide an OS-neutral view on a file system, locally or remotely.
4The functionality is geared towards implementing some sort of
5rdist-like utility between a Mac and a UNIX system.
6
7The module defines three classes:
8
9FSProxyLocal -- used for local access
10FSProxyServer -- used on the server side of remote access
11FSProxyClient -- used on the client side of remote access
12
13The remote classes are instantiated with an IP address and an optional
14verbosity flag.
15"""
16
17import server
18import client
19import md5
20import os
21import fnmatch
22from stat import *
23import time
24import fnmatch
25
26if os.name == 'mac':
27 import macfs
28 maxnamelen = 31
29else:
30 macfs = None
31 maxnamelen = 255
32
33skipnames = (os.curdir, os.pardir)
34
35
36class FSProxyLocal:
37
38 def __init__(self):
39 self._dirstack = []
40 self._ignore = ['*.pyc'] + self._readignore()
41
42 def _close(self):
43 while self._dirstack:
44 self.back()
45
46 def _readignore(self):
47 file = self._hide('ignore')
48 try:
49 f = open(file)
50 except IOError:
51 file = self._hide('synctree.ignorefiles')
52 try:
53 f = open(file)
54 except IOError:
55 return []
56 ignore = []
57 while 1:
58 line = f.readline()
59 if not line: break
60 if line[-1] == '\n': line = line[:-1]
61 ignore.append(line)
62 f.close()
63 return ignore
64
65 def _hidden(self, name):
66 if os.name == 'mac':
67 return name[0] == '(' and name[-1] == ')'
68 else:
69 return name[0] == '.'
70
71 def _hide(self, name):
72 if os.name == 'mac':
73 return '(%s)' % name
74 else:
75 return '.%s' % name
76
77 def visible(self, name):
78 if len(name) > maxnamelen: return 0
79 if name[-1] == '~': return 0
80 if name in skipnames: return 0
81 if self._hidden(name): return 0
82 head, tail = os.path.split(name)
83 if head or not tail: return 0
84 if macfs:
85 if os.path.exists(name) and not os.path.isdir(name):
86 try:
87 fs = macfs.FSSpec(name)
88 c, t = fs.GetCreatorType()
89 if t != 'TEXT': return 0
90 except macfs.error, msg:
91 print "***", name, msg
92 return 0
93 else:
94 if os.path.islink(name): return 0
95 if '\0' in open(name, 'rb').read(512): return 0
96 for ign in self._ignore:
97 if fnmatch.fnmatch(name, ign): return 0
98 return 1
99
100 def check(self, name):
101 if not self.visible(name):
102 raise os.error, "protected name %s" % repr(name)
103
104 def checkfile(self, name):
105 self.check(name)
106 if not os.path.isfile(name):
107 raise os.error, "not a plain file %s" % repr(name)
108
109 def pwd(self):
110 return os.getcwd()
111
112 def cd(self, name):
113 self.check(name)
114 save = os.getcwd(), self._ignore
115 os.chdir(name)
116 self._dirstack.append(save)
117 self._ignore = self._ignore + self._readignore()
118
119 def back(self):
120 if not self._dirstack:
121 raise os.error, "empty directory stack"
122 dir, ignore = self._dirstack[-1]
123 os.chdir(dir)
124 del self._dirstack[-1]
125 self._ignore = ignore
126
127 def _filter(self, files, pat = None):
128 if pat:
129 def keep(name, pat = pat):
130 return fnmatch.fnmatch(name, pat)
131 files = filter(keep, files)
132 files = filter(self.visible, files)
133 files.sort()
134 return files
135
136 def list(self, pat = None):
137 files = os.listdir(os.curdir)
138 return self._filter(files, pat)
139
140 def listfiles(self, pat = None):
141 files = os.listdir(os.curdir)
142 files = filter(os.path.isfile, files)
143 return self._filter(files, pat)
144
145 def listsubdirs(self, pat = None):
146 files = os.listdir(os.curdir)
147 files = filter(os.path.isdir, files)
148 return self._filter(files, pat)
149
150 def exists(self, name):
151 return self.visible(name) and os.path.exists(name)
152
153 def isdir(self, name):
154 return self.visible(name) and os.path.isdir(name)
155
156 def islink(self, name):
157 return self.visible(name) and os.path.islink(name)
158
159 def isfile(self, name):
160 return self.visible(name) and os.path.isfile(name)
161
162 def sum(self, name):
163 self.checkfile(name)
164 BUFFERSIZE = 1024*8
165 f = open(name)
166 sum = md5.new()
167 while 1:
168 buffer = f.read(BUFFERSIZE)
169 if not buffer:
170 break
171 sum.update(buffer)
172 return sum.digest()
173
174 def size(self, name):
175 self.checkfile(name)
176 return os.stat(name)[ST_SIZE]
177
178 def mtime(self, name):
179 self.checkfile(name)
180 return time.localtime(os.stat(name)[ST_MTIME])
181
182 def stat(self, name):
183 self.checkfile(name)
184 size = os.stat(name)[ST_SIZE]
185 mtime = time.localtime(os.stat(name)[ST_MTIME])
186 return size, mtime
187
188 def info(self, name):
189 sum = self.sum(name)
190 size = os.stat(name)[ST_SIZE]
191 mtime = time.localtime(os.stat(name)[ST_MTIME])
192 return sum, size, mtime
193
194 def _list(self, function, list):
195 if list is None:
196 list = self.listfiles()
197 res = []
198 for name in list:
199 try:
200 res.append((name, function(name)))
201 except (os.error, IOError):
202 res.append((name, None))
203 return res
204
205 def sumlist(self, list = None):
206 return self._list(self.sum, list)
207
208 def statlist(self, list = None):
209 return self._list(self.stat, list)
210
211 def mtimelist(self, list = None):
212 return self._list(self.mtime, list)
213
214 def sizelist(self, list = None):
215 return self._list(self.size, list)
216
217 def infolist(self, list = None):
218 return self._list(self.info, list)
219
220 def _dict(self, function, list):
221 if list is None:
222 list = self.listfiles()
223 dict = {}
224 for name in list:
225 try:
226 dict[name] = function(name)
227 except (os.error, IOError):
228 pass
229 return dict
230
231 def sumdict(self, list = None):
232 return self.dict(self.sum, list)
233
234 def sizedict(self, list = None):
235 return self.dict(self.size, list)
236
237 def mtimedict(self, list = None):
238 return self.dict(self.mtime, list)
239
240 def statdict(self, list = None):
241 return self.dict(self.stat, list)
242
243 def infodict(self, list = None):
244 return self._dict(self.info, list)
245
246 def read(self, name, offset = 0, length = -1):
247 self.checkfile(name)
248 f = open(name)
249 f.seek(offset)
250 if length == 0:
251 data = ''
252 elif length < 0:
253 data = f.read()
254 else:
255 data = f.read(length)
256 f.close()
257 return data
258
259 def create(self, name):
260 self.check(name)
261 if os.path.exists(name):
262 self.checkfile(name)
263 bname = name + '~'
264 try:
265 os.unlink(bname)
266 except os.error:
267 pass
268 os.rename(name, bname)
269 f = open(name, 'w')
270 f.close()
271
272 def write(self, name, data, offset = 0):
273 self.checkfile(name)
274 f = open(name, 'r+')
275 f.seek(offset)
276 f.write(data)
277 f.close()
278
279 def mkdir(self, name):
280 self.check(name)
281 os.mkdir(name, 0777)
282
283 def rmdir(self, name):
284 self.check(name)
285 os.rmdir(name)
286
287
288class FSProxyServer(FSProxyLocal, server.Server):
289
290 def __init__(self, address, verbose = server.VERBOSE):
291 FSProxyLocal.__init__(self)
292 server.Server.__init__(self, address, verbose)
293
294 def _close(self):
295 server.Server._close(self)
296 FSProxyLocal._close(self)
297
298 def _serve(self):
299 server.Server._serve(self)
300 # Retreat into start directory
301 while self._dirstack: self.back()
302
303
304class FSProxyClient(client.Client):
305
306 def __init__(self, address, verbose = client.VERBOSE):
307 client.Client.__init__(self, address, verbose)
308
309
310def test():
311 import string
312 import sys
313 if sys.argv[1:]:
314 port = string.atoi(sys.argv[1])
315 else:
316 port = 4127
317 proxy = FSProxyServer(('', port))
318 proxy._serverloop()
319
320
321if __name__ == '__main__':
322 test()
sys/src/cmd/python/Demo/pdist/RCSProxy.py+198−0
@@ -0,0 +1,198 @@
1#! /usr/bin/env python
2
3"""RCS Proxy.
4
5Provide a simplified interface on RCS files, locally or remotely.
6The functionality is geared towards implementing some sort of
7remote CVS like utility. It is modeled after the similar module
8FSProxy.
9
10The module defines two classes:
11
12RCSProxyLocal -- used for local access
13RCSProxyServer -- used on the server side of remote access
14
15The corresponding client class, RCSProxyClient, is defined in module
16rcsclient.
17
18The remote classes are instantiated with an IP address and an optional
19verbosity flag.
20"""
21
22import server
23import md5
24import os
25import fnmatch
26import string
27import tempfile
28import rcslib
29
30
31class DirSupport:
32
33 def __init__(self):
34 self._dirstack = []
35
36 def __del__(self):
37 self._close()
38
39 def _close(self):
40 while self._dirstack:
41 self.back()
42
43 def pwd(self):
44 return os.getcwd()
45
46 def cd(self, name):
47 save = os.getcwd()
48 os.chdir(name)
49 self._dirstack.append(save)
50
51 def back(self):
52 if not self._dirstack:
53 raise os.error, "empty directory stack"
54 dir = self._dirstack[-1]
55 os.chdir(dir)
56 del self._dirstack[-1]
57
58 def listsubdirs(self, pat = None):
59 files = os.listdir(os.curdir)
60 files = filter(os.path.isdir, files)
61 return self._filter(files, pat)
62
63 def isdir(self, name):
64 return os.path.isdir(name)
65
66 def mkdir(self, name):
67 os.mkdir(name, 0777)
68
69 def rmdir(self, name):
70 os.rmdir(name)
71
72
73class RCSProxyLocal(rcslib.RCS, DirSupport):
74
75 def __init__(self):
76 rcslib.RCS.__init__(self)
77 DirSupport.__init__(self)
78
79 def __del__(self):
80 DirSupport.__del__(self)
81 rcslib.RCS.__del__(self)
82
83 def sumlist(self, list = None):
84 return self._list(self.sum, list)
85
86 def sumdict(self, list = None):
87 return self._dict(self.sum, list)
88
89 def sum(self, name_rev):
90 f = self._open(name_rev)
91 BUFFERSIZE = 1024*8
92 sum = md5.new()
93 while 1:
94 buffer = f.read(BUFFERSIZE)
95 if not buffer:
96 break
97 sum.update(buffer)
98 self._closepipe(f)
99 return sum.digest()
100
101 def get(self, name_rev):
102 f = self._open(name_rev)
103 data = f.read()
104 self._closepipe(f)
105 return data
106
107 def put(self, name_rev, data, message=None):
108 name, rev = self._unmangle(name_rev)
109 f = open(name, 'w')
110 f.write(data)
111 f.close()
112 self.checkin(name_rev, message)
113 self._remove(name)
114
115 def _list(self, function, list = None):
116 """INTERNAL: apply FUNCTION to all files in LIST.
117
118 Return a list of the results.
119
120 The list defaults to all files in the directory if None.
121
122 """
123 if list is None:
124 list = self.listfiles()
125 res = []
126 for name in list:
127 try:
128 res.append((name, function(name)))
129 except (os.error, IOError):
130 res.append((name, None))
131 return res
132
133 def _dict(self, function, list = None):
134 """INTERNAL: apply FUNCTION to all files in LIST.
135
136 Return a dictionary mapping files to results.
137
138 The list defaults to all files in the directory if None.
139
140 """
141 if list is None:
142 list = self.listfiles()
143 dict = {}
144 for name in list:
145 try:
146 dict[name] = function(name)
147 except (os.error, IOError):
148 pass
149 return dict
150
151
152class RCSProxyServer(RCSProxyLocal, server.SecureServer):
153
154 def __init__(self, address, verbose = server.VERBOSE):
155 RCSProxyLocal.__init__(self)
156 server.SecureServer.__init__(self, address, verbose)
157
158 def _close(self):
159 server.SecureServer._close(self)
160 RCSProxyLocal._close(self)
161
162 def _serve(self):
163 server.SecureServer._serve(self)
164 # Retreat into start directory
165 while self._dirstack: self.back()
166
167
168def test_server():
169 import string
170 import sys
171 if sys.argv[1:]:
172 port = string.atoi(sys.argv[1])
173 else:
174 port = 4127
175 proxy = RCSProxyServer(('', port))
176 proxy._serverloop()
177
178
179def test():
180 import sys
181 if not sys.argv[1:] or sys.argv[1] and sys.argv[1][0] in '0123456789':
182 test_server()
183 sys.exit(0)
184 proxy = RCSProxyLocal()
185 what = sys.argv[1]
186 if hasattr(proxy, what):
187 attr = getattr(proxy, what)
188 if callable(attr):
189 print apply(attr, tuple(sys.argv[2:]))
190 else:
191 print repr(attr)
192 else:
193 print "%s: no such attribute" % what
194 sys.exit(2)
195
196
197if __name__ == '__main__':
198 test()
sys/src/cmd/python/Demo/pdist/README+121−0
@@ -0,0 +1,121 @@
1Filesystem, RCS and CVS client and server classes
2=================================================
3
4*** See the security warning at the end of this file! ***
5
6This directory contains various modules and classes that support
7remote file system operations.
8
9CVS stuff
10---------
11
12rcvs Script to put in your bin directory
13rcvs.py Remote CVS client command line interface
14
15cvslib.py CVS admin files classes (used by rrcs)
16cvslock.py CVS locking algorithms
17
18RCS stuff
19---------
20
21rrcs Script to put in your bin directory
22rrcs.py Remote RCS client command line interface
23
24rcsclient.py Return an RCSProxyClient instance
25 (has reasonable default server/port/directory)
26
27RCSProxy.py RCS proxy and server classes (on top of rcslib.py)
28
29rcslib.py Local-only RCS base class (affects stdout &
30 local work files)
31
32FSProxy stuff
33-------------
34
35sumtree.py Old demo for FSProxy
36cmptree.py First FSProxy client (used to sync from the Mac)
37FSProxy.py Filesystem interface classes
38
39Generic client/server stuff
40---------------------------
41
42client.py Client class
43server.py Server class
44
45security.py Security mix-in class (not very secure I think)
46
47Other generic stuff
48-------------------
49
50cmdfw.py CommandFrameWork class
51 (used by rcvs, should be used by rrcs as well)
52
53
54Client/Server operation
55-----------------------
56
57The Client and Server classes implement a simple-minded RPC protocol,
58using Python's pickle module to transfer arguments, return values and
59exceptions with the most generality. The Server class is instantiated
60with a port number on which it should listen for requests; the Client
61class is instantiated with a host name and a port number where it
62should connect to. Once a client is connected, a TCP connection is
63maintained between client and server.
64
65The Server class currently handles only one connection at a time;
66however it could be rewritten to allow various modes of operations,
67using multiple threads or processes or the select() system call as
68desired to serve multiple clients simultaneously (when using select(),
69still handling one request at a time). This would not require
70rewriting of the Client class. It may also be possible to adapt the
71code to use UDP instead of TCP, but then both classes will have to be
72rewritten (and unless extensive acknowlegements and request serial
73numbers are used, the server should handle duplicate requests, so its
74semantics should be idempotent -- shrudder).
75
76Even though the FSProxy and RCSProxy modules define client classes,
77the client class is fully generic -- what methods it supports is
78determined entirely by the server. The server class, however, must be
79derived from. This is generally done as follows:
80
81 from server import Server
82 from client import Client
83
84 # Define a class that performs the operations locally
85 class MyClassLocal:
86 def __init__(self): ...
87 def _close(self): ...
88
89 # Derive a server class using multiple inheritance
90 class MyClassServer(MyClassLocal, Server):
91 def __init__(self, address):
92 # Must initialize MyClassLocal as well as Server
93 MyClassLocal.__init__(self)
94 Server.__init__(self, address)
95 def _close(self):
96 Server._close()
97 MyClassLocal._close()
98
99 # A dummy client class
100 class MyClassClient(Client): pass
101
102Note that because MyClassLocal isn't used in the definition of
103MyClassClient, it would actually be better to place it in a separate
104module so the definition of MyClassLocal isn't executed when we only
105instantiate a client.
106
107The modules client and server should probably be renamed to Client and
108Server in order to match the class names.
109
110
111*** Security warning: this version requires that you have a file
112$HOME/.python_keyfile at the server and client side containing two
113comma- separated numbers. The security system at the moment makes no
114guarantees of actuallng being secure -- however it requires that the
115key file exists and contains the same numbers at both ends for this to
116work. (You can specify an alternative keyfile in $PYTHON_KEYFILE).
117Have a look at the Security class in security.py for details;
118basically, if the key file contains (x, y), then the security server
119class chooses a random number z (the challenge) in the range
12010..100000 and the client must be able to produce pow(z, x, y)
121(i.e. z**x mod y).
sys/src/cmd/python/Demo/pdist/client.py+157−0
@@ -0,0 +1,157 @@
1"""RPC Client module."""
2
3import sys
4import socket
5import pickle
6import __builtin__
7import os
8
9
10# Default verbosity (0 = silent, 1 = print connections, 2 = print requests too)
11VERBOSE = 1
12
13
14class Client:
15
16 """RPC Client class. No need to derive a class -- it's fully generic."""
17
18 def __init__(self, address, verbose = VERBOSE):
19 self._pre_init(address, verbose)
20 self._post_init()
21
22 def _pre_init(self, address, verbose = VERBOSE):
23 if type(address) == type(0):
24 address = ('', address)
25 self._address = address
26 self._verbose = verbose
27 if self._verbose: print "Connecting to %s ..." % repr(address)
28 self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
29 self._socket.connect(address)
30 if self._verbose: print "Connected."
31 self._lastid = 0 # Last id for which a reply has been received
32 self._nextid = 1 # Id of next request
33 self._replies = {} # Unprocessed replies
34 self._rf = self._socket.makefile('r')
35 self._wf = self._socket.makefile('w')
36
37 def _post_init(self):
38 self._methods = self._call('.methods')
39
40 def __del__(self):
41 self._close()
42
43 def _close(self):
44 if self._rf: self._rf.close()
45 self._rf = None
46 if self._wf: self._wf.close()
47 self._wf = None
48 if self._socket: self._socket.close()
49 self._socket = None
50
51 def __getattr__(self, name):
52 if name in self._methods:
53 method = _stub(self, name)
54 setattr(self, name, method) # XXX circular reference
55 return method
56 raise AttributeError, name
57
58 def _setverbose(self, verbose):
59 self._verbose = verbose
60
61 def _call(self, name, *args):
62 return self._vcall(name, args)
63
64 def _vcall(self, name, args):
65 return self._recv(self._vsend(name, args))
66
67 def _send(self, name, *args):
68 return self._vsend(name, args)
69
70 def _send_noreply(self, name, *args):
71 return self._vsend(name, args, 0)
72
73 def _vsend_noreply(self, name, args):
74 return self._vsend(name, args, 0)
75
76 def _vsend(self, name, args, wantreply = 1):
77 id = self._nextid
78 self._nextid = id+1
79 if not wantreply: id = -id
80 request = (name, args, id)
81 if self._verbose > 1: print "sending request: %s" % repr(request)
82 wp = pickle.Pickler(self._wf)
83 wp.dump(request)
84 return id
85
86 def _recv(self, id):
87 exception, value, rid = self._vrecv(id)
88 if rid != id:
89 raise RuntimeError, "request/reply id mismatch: %d/%d" % (id, rid)
90 if exception is None:
91 return value
92 x = exception
93 if hasattr(__builtin__, exception):
94 x = getattr(__builtin__, exception)
95 elif exception in ('posix.error', 'mac.error'):
96 x = os.error
97 if x == exception:
98 exception = x
99 raise exception, value
100
101 def _vrecv(self, id):
102 self._flush()
103 if self._replies.has_key(id):
104 if self._verbose > 1: print "retrieving previous reply, id = %d" % id
105 reply = self._replies[id]
106 del self._replies[id]
107 return reply
108 aid = abs(id)
109 while 1:
110 if self._verbose > 1: print "waiting for reply, id = %d" % id
111 rp = pickle.Unpickler(self._rf)
112 reply = rp.load()
113 del rp
114 if self._verbose > 1: print "got reply: %s" % repr(reply)
115 rid = reply[2]
116 arid = abs(rid)
117 if arid == aid:
118 if self._verbose > 1: print "got it"
119 return reply
120 self._replies[rid] = reply
121 if arid > aid:
122 if self._verbose > 1: print "got higher id, assume all ok"
123 return (None, None, id)
124
125 def _flush(self):
126 self._wf.flush()
127
128
129from security import Security
130
131
132class SecureClient(Client, Security):
133
134 def __init__(self, *args):
135 import string
136 apply(self._pre_init, args)
137 Security.__init__(self)
138 self._wf.flush()
139 line = self._rf.readline()
140 challenge = string.atoi(string.strip(line))
141 response = self._encode_challenge(challenge)
142 line = repr(long(response))
143 if line[-1] in 'Ll': line = line[:-1]
144 self._wf.write(line + '\n')
145 self._wf.flush()
146 self._post_init()
147
148class _stub:
149
150 """Helper class for Client -- each instance serves as a method of the client."""
151
152 def __init__(self, client, name):
153 self._client = client
154 self._name = name
155
156 def __call__(self, *args):
157 return self._client._vcall(self._name, args)
sys/src/cmd/python/Demo/pdist/cmdfw.py+144−0
@@ -0,0 +1,144 @@
1"Framework for command line interfaces like CVS. See class CmdFrameWork."
2
3
4class CommandFrameWork:
5
6 """Framework class for command line interfaces like CVS.
7
8 The general command line structure is
9
10 command [flags] subcommand [subflags] [argument] ...
11
12 There's a class variable GlobalFlags which specifies the
13 global flags options. Subcommands are defined by defining
14 methods named do_<subcommand>. Flags for the subcommand are
15 defined by defining class or instance variables named
16 flags_<subcommand>. If there's no command, method default()
17 is called. The __doc__ strings for the do_ methods are used
18 for the usage message, printed after the general usage message
19 which is the class variable UsageMessage. The class variable
20 PostUsageMessage is printed after all the do_ methods' __doc__
21 strings. The method's return value can be a suggested exit
22 status. [XXX Need to rewrite this to clarify it.]
23
24 Common usage is to derive a class, instantiate it, and then call its
25 run() method; by default this takes its arguments from sys.argv[1:].
26 """
27
28 UsageMessage = \
29 "usage: (name)s [flags] subcommand [subflags] [argument] ..."
30
31 PostUsageMessage = None
32
33 GlobalFlags = ''
34
35 def __init__(self):
36 """Constructor, present for completeness."""
37 pass
38
39 def run(self, args = None):
40 """Process flags, subcommand and options, then run it."""
41 import getopt, sys
42 if args is None: args = sys.argv[1:]
43 try:
44 opts, args = getopt.getopt(args, self.GlobalFlags)
45 except getopt.error, msg:
46 return self.usage(msg)
47 self.options(opts)
48 if not args:
49 self.ready()
50 return self.default()
51 else:
52 cmd = args[0]
53 mname = 'do_' + cmd
54 fname = 'flags_' + cmd
55 try:
56 method = getattr(self, mname)
57 except AttributeError:
58 return self.usage("command %r unknown" % (cmd,))
59 try:
60 flags = getattr(self, fname)
61 except AttributeError:
62 flags = ''
63 try:
64 opts, args = getopt.getopt(args[1:], flags)
65 except getopt.error, msg:
66 return self.usage(
67 "subcommand %s: " % cmd + str(msg))
68 self.ready()
69 return method(opts, args)
70
71 def options(self, opts):
72 """Process the options retrieved by getopt.
73 Override this if you have any options."""
74 if opts:
75 print "-"*40
76 print "Options:"
77 for o, a in opts:
78 print 'option', o, 'value', repr(a)
79 print "-"*40
80
81 def ready(self):
82 """Called just before calling the subcommand."""
83 pass
84
85 def usage(self, msg = None):
86 """Print usage message. Return suitable exit code (2)."""
87 if msg: print msg
88 print self.UsageMessage % {'name': self.__class__.__name__}
89 docstrings = {}
90 c = self.__class__
91 while 1:
92 for name in dir(c):
93 if name[:3] == 'do_':
94 if docstrings.has_key(name):
95 continue
96 try:
97 doc = getattr(c, name).__doc__
98 except:
99 doc = None
100 if doc:
101 docstrings[name] = doc
102 if not c.__bases__:
103 break
104 c = c.__bases__[0]
105 if docstrings:
106 print "where subcommand can be:"
107 names = docstrings.keys()
108 names.sort()
109 for name in names:
110 print docstrings[name]
111 if self.PostUsageMessage:
112 print self.PostUsageMessage
113 return 2
114
115 def default(self):
116 """Default method, called when no subcommand is given.
117 You should always override this."""
118 print "Nobody expects the Spanish Inquisition!"
119
120
121def test():
122 """Test script -- called when this module is run as a script."""
123 import sys
124 class Hello(CommandFrameWork):
125 def do_hello(self, opts, args):
126 "hello -- print 'hello world', needs no arguments"
127 print "Hello, world"
128 x = Hello()
129 tests = [
130 [],
131 ['hello'],
132 ['spam'],
133 ['-x'],
134 ['hello', '-x'],
135 None,
136 ]
137 for t in tests:
138 print '-'*10, t, '-'*10
139 sts = x.run(t)
140 print "Exit status:", repr(sts)
141
142
143if __name__ == '__main__':
144 test()
sys/src/cmd/python/Demo/pdist/cmptree.py+208−0
@@ -0,0 +1,208 @@
1"""Compare local and remote dictionaries and transfer differing files -- like rdist."""
2
3import sys
4from repr import repr
5import FSProxy
6import time
7import os
8
9def main():
10 pwd = os.getcwd()
11 s = raw_input("chdir [%s] " % pwd)
12 if s:
13 os.chdir(s)
14 pwd = os.getcwd()
15 host = ask("host", 'voorn.cwi.nl')
16 port = 4127
17 verbose = 1
18 mode = ''
19 print """\
20Mode should be a string of characters, indicating what to do with differences.
21r - read different files to local file system
22w - write different files to remote file system
23c - create new files, either remote or local
24d - delete disappearing files, either remote or local
25"""
26 s = raw_input("mode [%s] " % mode)
27 if s: mode = s
28 address = (host, port)
29 t1 = time.time()
30 local = FSProxy.FSProxyLocal()
31 remote = FSProxy.FSProxyClient(address, verbose)
32 compare(local, remote, mode)
33 remote._close()
34 local._close()
35 t2 = time.time()
36 dt = t2-t1
37 mins, secs = divmod(dt, 60)
38 print mins, "minutes and", round(secs), "seconds"
39 raw_input("[Return to exit] ")
40
41def ask(prompt, default):
42 s = raw_input("%s [%s] " % (prompt, default))
43 return s or default
44
45def askint(prompt, default):
46 s = raw_input("%s [%s] " % (prompt, str(default)))
47 if s: return string.atoi(s)
48 return default
49
50def compare(local, remote, mode):
51 print
52 print "PWD =", repr(os.getcwd())
53 sums_id = remote._send('sumlist')
54 subdirs_id = remote._send('listsubdirs')
55 remote._flush()
56 print "calculating local sums ..."
57 lsumdict = {}
58 for name, info in local.sumlist():
59 lsumdict[name] = info
60 print "getting remote sums ..."
61 sums = remote._recv(sums_id)
62 print "got", len(sums)
63 rsumdict = {}
64 for name, rsum in sums:
65 rsumdict[name] = rsum
66 if not lsumdict.has_key(name):
67 print repr(name), "only remote"
68 if 'r' in mode and 'c' in mode:
69 recvfile(local, remote, name)
70 else:
71 lsum = lsumdict[name]
72 if lsum != rsum:
73 print repr(name),
74 rmtime = remote.mtime(name)
75 lmtime = local.mtime(name)
76 if rmtime > lmtime:
77 print "remote newer",
78 if 'r' in mode:
79 recvfile(local, remote, name)
80 elif lmtime > rmtime:
81 print "local newer",
82 if 'w' in mode:
83 sendfile(local, remote, name)
84 else:
85 print "same mtime but different sum?!?!",
86 print
87 for name in lsumdict.keys():
88 if not rsumdict.keys():
89 print repr(name), "only locally",
90 fl()
91 if 'w' in mode and 'c' in mode:
92 sendfile(local, remote, name)
93 elif 'r' in mode and 'd' in mode:
94 os.unlink(name)
95 print "removed."
96 print
97 print "gettin subdirs ..."
98 subdirs = remote._recv(subdirs_id)
99 common = []
100 for name in subdirs:
101 if local.isdir(name):
102 print "Common subdirectory", repr(name)
103 common.append(name)
104 else:
105 print "Remote subdirectory", repr(name), "not found locally"
106 if 'r' in mode and 'c' in mode:
107 pr = "Create local subdirectory %s? [y] " % \
108 repr(name)
109 if 'y' in mode:
110 ok = 'y'
111 else:
112 ok = ask(pr, "y")
113 if ok[:1] in ('y', 'Y'):
114 local.mkdir(name)
115 print "Subdirectory %s made" % \
116 repr(name)
117 common.append(name)
118 lsubdirs = local.listsubdirs()
119 for name in lsubdirs:
120 if name not in subdirs:
121 print "Local subdirectory", repr(name), "not found remotely"
122 for name in common:
123 print "Entering subdirectory", repr(name)
124 local.cd(name)
125 remote.cd(name)
126 compare(local, remote, mode)
127 remote.back()
128 local.back()
129
130def sendfile(local, remote, name):
131 try:
132 remote.create(name)
133 except (IOError, os.error), msg:
134 print "cannot create:", msg
135 return
136
137 print "sending ...",
138 fl()
139
140 data = open(name).read()
141
142 t1 = time.time()
143
144 remote._send_noreply('write', name, data)
145 remote._flush()
146
147 t2 = time.time()
148
149 dt = t2-t1
150 print len(data), "bytes in", round(dt), "seconds",
151 if dt:
152 print "i.e.", round(len(data)/dt), "bytes/sec",
153 print
154
155def recvfile(local, remote, name):
156 ok = 0
157 try:
158 rv = recvfile_real(local, remote, name)
159 ok = 1
160 return rv
161 finally:
162 if not ok:
163 print "*** recvfile of %r failed, deleting" % (name,)
164 local.delete(name)
165
166def recvfile_real(local, remote, name):
167 try:
168 local.create(name)
169 except (IOError, os.error), msg:
170 print "cannot create:", msg
171 return
172
173 print "receiving ...",
174 fl()
175
176 f = open(name, 'w')
177 t1 = time.time()
178
179 length = 4*1024
180 offset = 0
181 id = remote._send('read', name, offset, length)
182 remote._flush()
183 while 1:
184 newoffset = offset + length
185 newid = remote._send('read', name, newoffset, length)
186 data = remote._recv(id)
187 id = newid
188 if not data: break
189 f.seek(offset)
190 f.write(data)
191 offset = newoffset
192 size = f.tell()
193
194 t2 = time.time()
195 f.close()
196
197 dt = t2-t1
198 print size, "bytes in", round(dt), "seconds",
199 if dt:
200 print "i.e.", int(size/dt), "bytes/sec",
201 print
202 remote._recv(id) # ignored
203
204def fl():
205 sys.stdout.flush()
206
207if __name__ == '__main__':
208 main()
sys/src/cmd/python/Demo/pdist/cvslib.py+364−0
@@ -0,0 +1,364 @@
1"""Utilities for CVS administration."""
2
3import string
4import os
5import time
6import md5
7import fnmatch
8
9if not hasattr(time, 'timezone'):
10 time.timezone = 0
11
12class File:
13
14 """Represent a file's status.
15
16 Instance variables:
17
18 file -- the filename (no slashes), None if uninitialized
19 lseen -- true if the data for the local file is up to date
20 eseen -- true if the data from the CVS/Entries entry is up to date
21 (this implies that the entry must be written back)
22 rseen -- true if the data for the remote file is up to date
23 proxy -- RCSProxy instance used to contact the server, or None
24
25 Note that lseen and rseen don't necessary mean that a local
26 or remote file *exists* -- they indicate that we've checked it.
27 However, eseen means that this instance corresponds to an
28 entry in the CVS/Entries file.
29
30 If lseen is true:
31
32 lsum -- checksum of the local file, None if no local file
33 lctime -- ctime of the local file, None if no local file
34 lmtime -- mtime of the local file, None if no local file
35
36 If eseen is true:
37
38 erev -- revision, None if this is a no revision (not '0')
39 enew -- true if this is an uncommitted added file
40 edeleted -- true if this is an uncommitted removed file
41 ectime -- ctime of last local file corresponding to erev
42 emtime -- mtime of last local file corresponding to erev
43 extra -- 5th string from CVS/Entries file
44
45 If rseen is true:
46
47 rrev -- revision of head, None if non-existent
48 rsum -- checksum of that revision, Non if non-existent
49
50 If eseen and rseen are both true:
51
52 esum -- checksum of revision erev, None if no revision
53
54 Note
55 """
56
57 def __init__(self, file = None):
58 if file and '/' in file:
59 raise ValueError, "no slash allowed in file"
60 self.file = file
61 self.lseen = self.eseen = self.rseen = 0
62 self.proxy = None
63
64 def __cmp__(self, other):
65 return cmp(self.file, other.file)
66
67 def getlocal(self):
68 try:
69 self.lmtime, self.lctime = os.stat(self.file)[-2:]
70 except os.error:
71 self.lmtime = self.lctime = self.lsum = None
72 else:
73 self.lsum = md5.new(open(self.file).read()).digest()
74 self.lseen = 1
75
76 def getentry(self, line):
77 words = string.splitfields(line, '/')
78 if self.file and words[1] != self.file:
79 raise ValueError, "file name mismatch"
80 self.file = words[1]
81 self.erev = words[2]
82 self.edeleted = 0
83 self.enew = 0
84 self.ectime = self.emtime = None
85 if self.erev[:1] == '-':
86 self.edeleted = 1
87 self.erev = self.erev[1:]
88 if self.erev == '0':
89 self.erev = None
90 self.enew = 1
91 else:
92 dates = words[3]
93 self.ectime = unctime(dates[:24])
94 self.emtime = unctime(dates[25:])
95 self.extra = words[4]
96 if self.rseen:
97 self.getesum()
98 self.eseen = 1
99
100 def getremote(self, proxy = None):
101 if proxy:
102 self.proxy = proxy
103 try:
104 self.rrev = self.proxy.head(self.file)
105 except (os.error, IOError):
106 self.rrev = None
107 if self.rrev:
108 self.rsum = self.proxy.sum(self.file)
109 else:
110 self.rsum = None
111 if self.eseen:
112 self.getesum()
113 self.rseen = 1
114
115 def getesum(self):
116 if self.erev == self.rrev:
117 self.esum = self.rsum
118 elif self.erev:
119 name = (self.file, self.erev)
120 self.esum = self.proxy.sum(name)
121 else:
122 self.esum = None
123
124 def putentry(self):
125 """Return a line suitable for inclusion in CVS/Entries.
126
127 The returned line is terminated by a newline.
128 If no entry should be written for this file,
129 return "".
130 """
131 if not self.eseen:
132 return ""
133
134 rev = self.erev or '0'
135 if self.edeleted:
136 rev = '-' + rev
137 if self.enew:
138 dates = 'Initial ' + self.file
139 else:
140 dates = gmctime(self.ectime) + ' ' + \
141 gmctime(self.emtime)
142 return "/%s/%s/%s/%s/\n" % (
143 self.file,
144 rev,
145 dates,
146 self.extra)
147
148 def report(self):
149 print '-'*50
150 def r(key, repr=repr, self=self):
151 try:
152 value = repr(getattr(self, key))
153 except AttributeError:
154 value = "?"
155 print "%-15s:" % key, value
156 r("file")
157 if self.lseen:
158 r("lsum", hexify)
159 r("lctime", gmctime)
160 r("lmtime", gmctime)
161 if self.eseen:
162 r("erev")
163 r("enew")
164 r("edeleted")
165 r("ectime", gmctime)
166 r("emtime", gmctime)
167 if self.rseen:
168 r("rrev")
169 r("rsum", hexify)
170 if self.eseen:
171 r("esum", hexify)
172
173
174class CVS:
175
176 """Represent the contents of a CVS admin file (and more).
177
178 Class variables:
179
180 FileClass -- the class to be instantiated for entries
181 (this should be derived from class File above)
182 IgnoreList -- shell patterns for local files to be ignored
183
184 Instance variables:
185
186 entries -- a dictionary containing File instances keyed by
187 their file name
188 proxy -- an RCSProxy instance, or None
189 """
190
191 FileClass = File
192
193 IgnoreList = ['.*', '@*', ',*', '*~', '*.o', '*.a', '*.so', '*.pyc']
194
195 def __init__(self):
196 self.entries = {}
197 self.proxy = None
198
199 def setproxy(self, proxy):
200 if proxy is self.proxy:
201 return
202 self.proxy = proxy
203 for e in self.entries.values():
204 e.rseen = 0
205
206 def getentries(self):
207 """Read the contents of CVS/Entries"""
208 self.entries = {}
209 f = self.cvsopen("Entries")
210 while 1:
211 line = f.readline()
212 if not line: break
213 e = self.FileClass()
214 e.getentry(line)
215 self.entries[e.file] = e
216 f.close()
217
218 def putentries(self):
219 """Write CVS/Entries back"""
220 f = self.cvsopen("Entries", 'w')
221 for e in self.values():
222 f.write(e.putentry())
223 f.close()
224
225 def getlocalfiles(self):
226 list = self.entries.keys()
227 addlist = os.listdir(os.curdir)
228 for name in addlist:
229 if name in list:
230 continue
231 if not self.ignored(name):
232 list.append(name)
233 list.sort()
234 for file in list:
235 try:
236 e = self.entries[file]
237 except KeyError:
238 e = self.entries[file] = self.FileClass(file)
239 e.getlocal()
240
241 def getremotefiles(self, proxy = None):
242 if proxy:
243 self.proxy = proxy
244 if not self.proxy:
245 raise RuntimeError, "no RCS proxy"
246 addlist = self.proxy.listfiles()
247 for file in addlist:
248 try:
249 e = self.entries[file]
250 except KeyError:
251 e = self.entries[file] = self.FileClass(file)
252 e.getremote(self.proxy)
253
254 def report(self):
255 for e in self.values():
256 e.report()
257 print '-'*50
258
259 def keys(self):
260 keys = self.entries.keys()
261 keys.sort()
262 return keys
263
264 def values(self):
265 def value(key, self=self):
266 return self.entries[key]
267 return map(value, self.keys())
268
269 def items(self):
270 def item(key, self=self):
271 return (key, self.entries[key])
272 return map(item, self.keys())
273
274 def cvsexists(self, file):
275 file = os.path.join("CVS", file)
276 return os.path.exists(file)
277
278 def cvsopen(self, file, mode = 'r'):
279 file = os.path.join("CVS", file)
280 if 'r' not in mode:
281 self.backup(file)
282 return open(file, mode)
283
284 def backup(self, file):
285 if os.path.isfile(file):
286 bfile = file + '~'
287 try: os.unlink(bfile)
288 except os.error: pass
289 os.rename(file, bfile)
290
291 def ignored(self, file):
292 if os.path.isdir(file): return True
293 for pat in self.IgnoreList:
294 if fnmatch.fnmatch(file, pat): return True
295 return False
296
297
298# hexify and unhexify are useful to print MD5 checksums in hex format
299
300hexify_format = '%02x' * 16
301def hexify(sum):
302 "Return a hex representation of a 16-byte string (e.g. an MD5 digest)"
303 if sum is None:
304 return "None"
305 return hexify_format % tuple(map(ord, sum))
306
307def unhexify(hexsum):
308 "Return the original from a hexified string"
309 if hexsum == "None":
310 return None
311 sum = ''
312 for i in range(0, len(hexsum), 2):
313 sum = sum + chr(string.atoi(hexsum[i:i+2], 16))
314 return sum
315
316
317unctime_monthmap = {}
318def unctime(date):
319 if date == "None": return None
320 if not unctime_monthmap:
321 months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
322 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
323 i = 0
324 for m in months:
325 i = i+1
326 unctime_monthmap[m] = i
327 words = string.split(date) # Day Mon DD HH:MM:SS YEAR
328 year = string.atoi(words[4])
329 month = unctime_monthmap[words[1]]
330 day = string.atoi(words[2])
331 [hh, mm, ss] = map(string.atoi, string.splitfields(words[3], ':'))
332 ss = ss - time.timezone
333 return time.mktime((year, month, day, hh, mm, ss, 0, 0, 0))
334
335def gmctime(t):
336 if t is None: return "None"
337 return time.asctime(time.gmtime(t))
338
339def test_unctime():
340 now = int(time.time())
341 t = time.gmtime(now)
342 at = time.asctime(t)
343 print 'GMT', now, at
344 print 'timezone', time.timezone
345 print 'local', time.ctime(now)
346 u = unctime(at)
347 print 'unctime()', u
348 gu = time.gmtime(u)
349 print '->', gu
350 print time.asctime(gu)
351
352def test():
353 x = CVS()
354 x.getentries()
355 x.getlocalfiles()
356## x.report()
357 import rcsclient
358 proxy = rcsclient.openrcsclient()
359 x.getremotefiles(proxy)
360 x.report()
361
362
363if __name__ == "__main__":
364 test()
sys/src/cmd/python/Demo/pdist/cvslock.py+280−0
@@ -0,0 +1,280 @@
1"""CVS locking algorithm.
2
3CVS locking strategy
4====================
5
6As reverse engineered from the CVS 1.3 sources (file lock.c):
7
8- Locking is done on a per repository basis (but a process can hold
9write locks for multiple directories); all lock files are placed in
10the repository and have names beginning with "#cvs.".
11
12- Before even attempting to lock, a file "#cvs.tfl.<pid>" is created
13(and removed again), to test that we can write the repository. [The
14algorithm can still be fooled (1) if the repository's mode is changed
15while attempting to lock; (2) if this file exists and is writable but
16the directory is not.]
17
18- While creating the actual read/write lock files (which may exist for
19a long time), a "meta-lock" is held. The meta-lock is a directory
20named "#cvs.lock" in the repository. The meta-lock is also held while
21a write lock is held.
22
23- To set a read lock:
24
25 - acquire the meta-lock
26 - create the file "#cvs.rfl.<pid>"
27 - release the meta-lock
28
29- To set a write lock:
30
31 - acquire the meta-lock
32 - check that there are no files called "#cvs.rfl.*"
33 - if there are, release the meta-lock, sleep, try again
34 - create the file "#cvs.wfl.<pid>"
35
36- To release a write lock:
37
38 - remove the file "#cvs.wfl.<pid>"
39 - rmdir the meta-lock
40
41- To release a read lock:
42
43 - remove the file "#cvs.rfl.<pid>"
44
45
46Additional notes
47----------------
48
49- A process should read-lock at most one repository at a time.
50
51- A process may write-lock as many repositories as it wishes (to avoid
52deadlocks, I presume it should always lock them top-down in the
53directory hierarchy).
54
55- A process should make sure it removes all its lock files and
56directories when it crashes.
57
58- Limitation: one user id should not be committing files into the same
59repository at the same time.
60
61
62Turn this into Python code
63--------------------------
64
65rl = ReadLock(repository, waittime)
66
67wl = WriteLock(repository, waittime)
68
69list = MultipleWriteLock([repository1, repository2, ...], waittime)
70
71"""
72
73
74import os
75import time
76import stat
77import pwd
78
79
80# Default wait time
81DELAY = 10
82
83
84# XXX This should be the same on all Unix versions
85EEXIST = 17
86
87
88# Files used for locking (must match cvs.h in the CVS sources)
89CVSLCK = "#cvs.lck"
90CVSRFL = "#cvs.rfl."
91CVSWFL = "#cvs.wfl."
92
93
94class Error:
95
96 def __init__(self, msg):
97 self.msg = msg
98
99 def __repr__(self):
100 return repr(self.msg)
101
102 def __str__(self):
103 return str(self.msg)
104
105
106class Locked(Error):
107 pass
108
109
110class Lock:
111
112 def __init__(self, repository = ".", delay = DELAY):
113 self.repository = repository
114 self.delay = delay
115 self.lockdir = None
116 self.lockfile = None
117 pid = repr(os.getpid())
118 self.cvslck = self.join(CVSLCK)
119 self.cvsrfl = self.join(CVSRFL + pid)
120 self.cvswfl = self.join(CVSWFL + pid)
121
122 def __del__(self):
123 print "__del__"
124 self.unlock()
125
126 def setlockdir(self):
127 while 1:
128 try:
129 self.lockdir = self.cvslck
130 os.mkdir(self.cvslck, 0777)
131 return
132 except os.error, msg:
133 self.lockdir = None
134 if msg[0] == EEXIST:
135 try:
136 st = os.stat(self.cvslck)
137 except os.error:
138 continue
139 self.sleep(st)
140 continue
141 raise Error("failed to lock %s: %s" % (
142 self.repository, msg))
143
144 def unlock(self):
145 self.unlockfile()
146 self.unlockdir()
147
148 def unlockfile(self):
149 if self.lockfile:
150 print "unlink", self.lockfile
151 try:
152 os.unlink(self.lockfile)
153 except os.error:
154 pass
155 self.lockfile = None
156
157 def unlockdir(self):
158 if self.lockdir:
159 print "rmdir", self.lockdir
160 try:
161 os.rmdir(self.lockdir)
162 except os.error:
163 pass
164 self.lockdir = None
165
166 def sleep(self, st):
167 sleep(st, self.repository, self.delay)
168
169 def join(self, name):
170 return os.path.join(self.repository, name)
171
172
173def sleep(st, repository, delay):
174 if delay <= 0:
175 raise Locked(st)
176 uid = st[stat.ST_UID]
177 try:
178 pwent = pwd.getpwuid(uid)
179 user = pwent[0]
180 except KeyError:
181 user = "uid %d" % uid
182 print "[%s]" % time.ctime(time.time())[11:19],
183 print "Waiting for %s's lock in" % user, repository
184 time.sleep(delay)
185
186
187class ReadLock(Lock):
188
189 def __init__(self, repository, delay = DELAY):
190 Lock.__init__(self, repository, delay)
191 ok = 0
192 try:
193 self.setlockdir()
194 self.lockfile = self.cvsrfl
195 fp = open(self.lockfile, 'w')
196 fp.close()
197 ok = 1
198 finally:
199 if not ok:
200 self.unlockfile()
201 self.unlockdir()
202
203
204class WriteLock(Lock):
205
206 def __init__(self, repository, delay = DELAY):
207 Lock.__init__(self, repository, delay)
208 self.setlockdir()
209 while 1:
210 uid = self.readers_exist()
211 if not uid:
212 break
213 self.unlockdir()
214 self.sleep(uid)
215 self.lockfile = self.cvswfl
216 fp = open(self.lockfile, 'w')
217 fp.close()
218
219 def readers_exist(self):
220 n = len(CVSRFL)
221 for name in os.listdir(self.repository):
222 if name[:n] == CVSRFL:
223 try:
224 st = os.stat(self.join(name))
225 except os.error:
226 continue
227 return st
228 return None
229
230
231def MultipleWriteLock(repositories, delay = DELAY):
232 while 1:
233 locks = []
234 for r in repositories:
235 try:
236 locks.append(WriteLock(r, 0))
237 except Locked, instance:
238 del locks
239 break
240 else:
241 break
242 sleep(instance.msg, r, delay)
243 return list
244
245
246def test():
247 import sys
248 if sys.argv[1:]:
249 repository = sys.argv[1]
250 else:
251 repository = "."
252 rl = None
253 wl = None
254 try:
255 print "attempting write lock ..."
256 wl = WriteLock(repository)
257 print "got it."
258 wl.unlock()
259 print "attempting read lock ..."
260 rl = ReadLock(repository)
261 print "got it."
262 rl.unlock()
263 finally:
264 print [1]
265 sys.exc_traceback = None
266 print [2]
267 if rl:
268 rl.unlock()
269 print [3]
270 if wl:
271 wl.unlock()
272 print [4]
273 rl = None
274 print [5]
275 wl = None
276 print [6]
277
278
279if __name__ == '__main__':
280 test()
sys/src/cmd/python/Demo/pdist/mac.py+19−0
@@ -0,0 +1,19 @@
1import sys
2import string
3import rcvs
4
5def main():
6 while 1:
7 try:
8 line = raw_input('$ ')
9 except EOFError:
10 break
11 words = string.split(line)
12 if not words:
13 continue
14 if words[0] != 'rcvs':
15 words.insert(0, 'rcvs')
16 sys.argv = words
17 rcvs.main()
18
19main()
sys/src/cmd/python/Demo/pdist/makechangelog.py+109−0
@@ -0,0 +1,109 @@
1#! /usr/bin/env python
2
3"""Turn a pile of RCS log output into ChangeLog file entries.
4
5"""
6
7import sys
8import string
9import re
10import getopt
11import time
12
13def main():
14 args = sys.argv[1:]
15 opts, args = getopt.getopt(args, 'p:')
16 prefix = ''
17 for o, a in opts:
18 if p == '-p': prefix = a
19
20 f = sys.stdin
21 allrevs = []
22 while 1:
23 file = getnextfile(f)
24 if not file: break
25 revs = []
26 while 1:
27 rev = getnextrev(f, file)
28 if not rev:
29 break
30 revs.append(rev)
31 if revs:
32 allrevs[len(allrevs):] = revs
33 allrevs.sort()
34 allrevs.reverse()
35 for rev in allrevs:
36 formatrev(rev, prefix)
37
38parsedateprog = re.compile(
39 '^date: ([0-9]+)/([0-9]+)/([0-9]+) ' +
40 '([0-9]+):([0-9]+):([0-9]+); author: ([^ ;]+)')
41
42authormap = {
43 'guido': 'Guido van Rossum <guido@cnri.reston.va.us>',
44 'jack': 'Jack Jansen <jack@cwi.nl>',
45 'sjoerd': 'Sjoerd Mullender <sjoerd@cwi.nl>',
46 }
47
48def formatrev(rev, prefix):
49 dateline, file, revline, log = rev
50 if parsedateprog.match(dateline) >= 0:
51 fields = parsedateprog.group(1, 2, 3, 4, 5, 6)
52 author = parsedateprog.group(7)
53 if authormap.has_key(author): author = authormap[author]
54 tfields = map(string.atoi, fields) + [0, 0, 0]
55 tfields[5] = tfields[5] - time.timezone
56 t = time.mktime(tuple(tfields))
57 print time.ctime(t), '', author
58 words = string.split(log)
59 words[:0] = ['*', prefix + file + ':']
60 maxcol = 72-8
61 col = maxcol
62 for word in words:
63 if col > 0 and col + len(word) >= maxcol:
64 print
65 print '\t' + word,
66 col = -1
67 else:
68 print word,
69 col = col + 1 + len(word)
70 print
71 print
72
73startprog = re.compile("^Working file: (.*)$")
74
75def getnextfile(f):
76 while 1:
77 line = f.readline()
78 if not line: return None
79 if startprog.match(line) >= 0:
80 file = startprog.group(1)
81 # Skip until first revision
82 while 1:
83 line = f.readline()
84 if not line: return None
85 if line[:10] == '='*10: return None
86 if line[:10] == '-'*10: break
87## print "Skipped", line,
88 return file
89## else:
90## print "Ignored", line,
91
92def getnextrev(f, file):
93 # This is called when we are positioned just after a '---' separator
94 revline = f.readline()
95 dateline = f.readline()
96 log = ''
97 while 1:
98 line = f.readline()
99 if not line: break
100 if line[:10] == '='*10:
101 # Ignore the *last* log entry for each file since it
102 # is the revision since which we are logging.
103 return None
104 if line[:10] == '-'*10: break
105 log = log + line
106 return dateline, file, revline, log
107
108if __name__ == '__main__':
109 main()
sys/src/cmd/python/Demo/pdist/rcsbump+33−0
@@ -0,0 +1,33 @@
1#!/usr/bin/env python
2# -*- python -*-
3#
4# guido's version, from rcsbump,v 1.2 1995/06/22 21:27:27 bwarsaw Exp
5#
6# Python script for bumping up an RCS major revision number.
7
8import sys
9import re
10import rcslib
11import string
12
13WITHLOCK = 1
14majorrev_re = re.compile('^[0-9]+')
15
16dir = rcslib.RCS()
17
18if sys.argv[1:]:
19 files = sys.argv[1:]
20else:
21 files = dir.listfiles()
22
23for file in files:
24 # get the major revnumber of the file
25 headbranch = dir.info(file)['head']
26 majorrev_re.match(headbranch)
27 majorrev = string.atoi(majorrev_re.group(0)) + 1
28
29 if not dir.islocked(file):
30 dir.checkout(file, WITHLOCK)
31
32 msg = "Bumping major revision number (to %d)" % majorrev
33 dir.checkin((file, "%s.0" % majorrev), msg, "-f")
sys/src/cmd/python/Demo/pdist/rcsclient.py+71−0
@@ -0,0 +1,71 @@
1"""Customize this file to change the default client etc.
2
3(In general, it is probably be better to make local operation the
4default and to require something like an RCSSERVER environment
5variable to enable remote operation.)
6
7"""
8
9import string
10import os
11
12# These defaults don't belong here -- they should be taken from the
13# environment or from a hidden file in the current directory
14
15HOST = 'voorn.cwi.nl'
16PORT = 4127
17VERBOSE = 1
18LOCAL = 0
19
20import client
21
22
23class RCSProxyClient(client.SecureClient):
24
25 def __init__(self, address, verbose = client.VERBOSE):
26 client.SecureClient.__init__(self, address, verbose)
27
28
29def openrcsclient(opts = []):
30 "open an RCSProxy client based on a list of options returned by getopt"
31 import RCSProxy
32 host = HOST
33 port = PORT
34 verbose = VERBOSE
35 local = LOCAL
36 directory = None
37 for o, a in opts:
38 if o == '-h':
39 host = a
40 if ':' in host:
41 i = string.find(host, ':')
42 host, p = host[:i], host[i+1:]
43 if p:
44 port = string.atoi(p)
45 if o == '-p':
46 port = string.atoi(a)
47 if o == '-d':
48 directory = a
49 if o == '-v':
50 verbose = verbose + 1
51 if o == '-q':
52 verbose = 0
53 if o == '-L':
54 local = 1
55 if local:
56 import RCSProxy
57 x = RCSProxy.RCSProxyLocal()
58 else:
59 address = (host, port)
60 x = RCSProxyClient(address, verbose)
61 if not directory:
62 try:
63 directory = open(os.path.join("CVS", "Repository")).readline()
64 except IOError:
65 pass
66 else:
67 if directory[-1] == '\n':
68 directory = directory[:-1]
69 if directory:
70 x.cd(directory)
71 return x
sys/src/cmd/python/Demo/pdist/rcslib.py+334−0
@@ -0,0 +1,334 @@
1"""RCS interface module.
2
3Defines the class RCS, which represents a directory with rcs version
4files and (possibly) corresponding work files.
5
6"""
7
8
9import fnmatch
10import os
11import re
12import string
13import tempfile
14
15
16class RCS:
17
18 """RCS interface class (local filesystem version).
19
20 An instance of this class represents a directory with rcs version
21 files and (possible) corresponding work files.
22
23 Methods provide access to most rcs operations such as
24 checkin/checkout, access to the rcs metadata (revisions, logs,
25 branches etc.) as well as some filesystem operations such as
26 listing all rcs version files.
27
28 XXX BUGS / PROBLEMS
29
30 - The instance always represents the current directory so it's not
31 very useful to have more than one instance around simultaneously
32
33 """
34
35 # Characters allowed in work file names
36 okchars = string.ascii_letters + string.digits + '-_=+'
37
38 def __init__(self):
39 """Constructor."""
40 pass
41
42 def __del__(self):
43 """Destructor."""
44 pass
45
46 # --- Informational methods about a single file/revision ---
47
48 def log(self, name_rev, otherflags = ''):
49 """Return the full log text for NAME_REV as a string.
50
51 Optional OTHERFLAGS are passed to rlog.
52
53 """
54 f = self._open(name_rev, 'rlog ' + otherflags)
55 data = f.read()
56 status = self._closepipe(f)
57 if status:
58 data = data + "%s: %s" % status
59 elif data[-1] == '\n':
60 data = data[:-1]
61 return data
62
63 def head(self, name_rev):
64 """Return the head revision for NAME_REV"""
65 dict = self.info(name_rev)
66 return dict['head']
67
68 def info(self, name_rev):
69 """Return a dictionary of info (from rlog -h) for NAME_REV
70
71 The dictionary's keys are the keywords that rlog prints
72 (e.g. 'head' and its values are the corresponding data
73 (e.g. '1.3').
74
75 XXX symbolic names and locks are not returned
76
77 """
78 f = self._open(name_rev, 'rlog -h')
79 dict = {}
80 while 1:
81 line = f.readline()
82 if not line: break
83 if line[0] == '\t':
84 # XXX could be a lock or symbolic name
85 # Anything else?
86 continue
87 i = string.find(line, ':')
88 if i > 0:
89 key, value = line[:i], string.strip(line[i+1:])
90 dict[key] = value
91 status = self._closepipe(f)
92 if status:
93 raise IOError, status
94 return dict
95
96 # --- Methods that change files ---
97
98 def lock(self, name_rev):
99 """Set an rcs lock on NAME_REV."""
100 name, rev = self.checkfile(name_rev)
101 cmd = "rcs -l%s %s" % (rev, name)
102 return self._system(cmd)
103
104 def unlock(self, name_rev):
105 """Clear an rcs lock on NAME_REV."""
106 name, rev = self.checkfile(name_rev)
107 cmd = "rcs -u%s %s" % (rev, name)
108 return self._system(cmd)
109
110 def checkout(self, name_rev, withlock=0, otherflags=""):
111 """Check out NAME_REV to its work file.
112
113 If optional WITHLOCK is set, check out locked, else unlocked.
114
115 The optional OTHERFLAGS is passed to co without
116 interpretation.
117
118 Any output from co goes to directly to stdout.
119
120 """
121 name, rev = self.checkfile(name_rev)
122 if withlock: lockflag = "-l"
123 else: lockflag = "-u"
124 cmd = 'co %s%s %s %s' % (lockflag, rev, otherflags, name)
125 return self._system(cmd)
126
127 def checkin(self, name_rev, message=None, otherflags=""):
128 """Check in NAME_REV from its work file.
129
130 The optional MESSAGE argument becomes the checkin message
131 (default "<none>" if None); or the file description if this is
132 a new file.
133
134 The optional OTHERFLAGS argument is passed to ci without
135 interpretation.
136
137 Any output from ci goes to directly to stdout.
138
139 """
140 name, rev = self._unmangle(name_rev)
141 new = not self.isvalid(name)
142 if not message: message = "<none>"
143 if message and message[-1] != '\n':
144 message = message + '\n'
145 lockflag = "-u"
146 if new:
147 f = tempfile.NamedTemporaryFile()
148 f.write(message)
149 f.flush()
150 cmd = 'ci %s%s -t%s %s %s' % \
151 (lockflag, rev, f.name, otherflags, name)
152 else:
153 message = re.sub(r'([\"$`])', r'\\\1', message)
154 cmd = 'ci %s%s -m"%s" %s %s' % \
155 (lockflag, rev, message, otherflags, name)
156 return self._system(cmd)
157
158 # --- Exported support methods ---
159
160 def listfiles(self, pat = None):
161 """Return a list of all version files matching optional PATTERN."""
162 files = os.listdir(os.curdir)
163 files = filter(self._isrcs, files)
164 if os.path.isdir('RCS'):
165 files2 = os.listdir('RCS')
166 files2 = filter(self._isrcs, files2)
167 files = files + files2
168 files = map(self.realname, files)
169 return self._filter(files, pat)
170
171 def isvalid(self, name):
172 """Test whether NAME has a version file associated."""
173 namev = self.rcsname(name)
174 return (os.path.isfile(namev) or
175 os.path.isfile(os.path.join('RCS', namev)))
176
177 def rcsname(self, name):
178 """Return the pathname of the version file for NAME.
179
180 The argument can be a work file name or a version file name.
181 If the version file does not exist, the name of the version
182 file that would be created by "ci" is returned.
183
184 """
185 if self._isrcs(name): namev = name
186 else: namev = name + ',v'
187 if os.path.isfile(namev): return namev
188 namev = os.path.join('RCS', os.path.basename(namev))
189 if os.path.isfile(namev): return namev
190 if os.path.isdir('RCS'):
191 return os.path.join('RCS', namev)
192 else:
193 return namev
194
195 def realname(self, namev):
196 """Return the pathname of the work file for NAME.
197
198 The argument can be a work file name or a version file name.
199 If the work file does not exist, the name of the work file
200 that would be created by "co" is returned.
201
202 """
203 if self._isrcs(namev): name = namev[:-2]
204 else: name = namev
205 if os.path.isfile(name): return name
206 name = os.path.basename(name)
207 return name
208
209 def islocked(self, name_rev):
210 """Test whether FILE (which must have a version file) is locked.
211
212 XXX This does not tell you which revision number is locked and
213 ignores any revision you may pass in (by virtue of using rlog
214 -L -R).
215
216 """
217 f = self._open(name_rev, 'rlog -L -R')
218 line = f.readline()
219 status = self._closepipe(f)
220 if status:
221 raise IOError, status
222 if not line: return None
223 if line[-1] == '\n':
224 line = line[:-1]
225 return self.realname(name_rev) == self.realname(line)
226
227 def checkfile(self, name_rev):
228 """Normalize NAME_REV into a (NAME, REV) tuple.
229
230 Raise an exception if there is no corresponding version file.
231
232 """
233 name, rev = self._unmangle(name_rev)
234 if not self.isvalid(name):
235 raise os.error, 'not an rcs file %r' % (name,)
236 return name, rev
237
238 # --- Internal methods ---
239
240 def _open(self, name_rev, cmd = 'co -p', rflag = '-r'):
241 """INTERNAL: open a read pipe to NAME_REV using optional COMMAND.
242
243 Optional FLAG is used to indicate the revision (default -r).
244
245 Default COMMAND is "co -p".
246
247 Return a file object connected by a pipe to the command's
248 output.
249
250 """
251 name, rev = self.checkfile(name_rev)
252 namev = self.rcsname(name)
253 if rev:
254 cmd = cmd + ' ' + rflag + rev
255 return os.popen("%s %r" % (cmd, namev))
256
257 def _unmangle(self, name_rev):
258 """INTERNAL: Normalize NAME_REV argument to (NAME, REV) tuple.
259
260 Raise an exception if NAME contains invalid characters.
261
262 A NAME_REV argument is either NAME string (implying REV='') or
263 a tuple of the form (NAME, REV).
264
265 """
266 if type(name_rev) == type(''):
267 name_rev = name, rev = name_rev, ''
268 else:
269 name, rev = name_rev
270 for c in rev:
271 if c not in self.okchars:
272 raise ValueError, "bad char in rev"
273 return name_rev
274
275 def _closepipe(self, f):
276 """INTERNAL: Close PIPE and print its exit status if nonzero."""
277 sts = f.close()
278 if not sts: return None
279 detail, reason = divmod(sts, 256)
280 if reason == 0: return 'exit', detail # Exit status
281 signal = reason&0x7F
282 if signal == 0x7F:
283 code = 'stopped'
284 signal = detail
285 else:
286 code = 'killed'
287 if reason&0x80:
288 code = code + '(coredump)'
289 return code, signal
290
291 def _system(self, cmd):
292 """INTERNAL: run COMMAND in a subshell.
293
294 Standard input for the command is taken from /dev/null.
295
296 Raise IOError when the exit status is not zero.
297
298 Return whatever the calling method should return; normally
299 None.
300
301 A derived class may override this method and redefine it to
302 capture stdout/stderr of the command and return it.
303
304 """
305 cmd = cmd + " </dev/null"
306 sts = os.system(cmd)
307 if sts: raise IOError, "command exit status %d" % sts
308
309 def _filter(self, files, pat = None):
310 """INTERNAL: Return a sorted copy of the given list of FILES.
311
312 If a second PATTERN argument is given, only files matching it
313 are kept. No check for valid filenames is made.
314
315 """
316 if pat:
317 def keep(name, pat = pat):
318 return fnmatch.fnmatch(name, pat)
319 files = filter(keep, files)
320 else:
321 files = files[:]
322 files.sort()
323 return files
324
325 def _remove(self, fn):
326 """INTERNAL: remove FILE without complaints."""
327 try:
328 os.unlink(fn)
329 except os.error:
330 pass
331
332 def _isrcs(self, name):
333 """INTERNAL: Test whether NAME ends in ',v'."""
334 return name[-2:] == ',v'
sys/src/cmd/python/Demo/pdist/rcvs+8−0
@@ -0,0 +1,8 @@
1#!/usr/bin/env python
2
3import addpack
4addpack.addpack('/home/guido/src/python/Demo/pdist')
5
6import rcvs
7
8rcvs.main()
sys/src/cmd/python/Demo/pdist/rcvs.py+477−0
@@ -0,0 +1,477 @@
1#! /usr/bin/env python
2
3"""Remote CVS -- command line interface"""
4
5# XXX To do:
6#
7# Bugs:
8# - if the remote file is deleted, "rcvs update" will fail
9#
10# Functionality:
11# - cvs rm
12# - descend into directories (alraedy done for update)
13# - conflict resolution
14# - other relevant commands?
15# - branches
16#
17# - Finesses:
18# - retain file mode's x bits
19# - complain when "nothing known about filename"
20# - edit log message the way CVS lets you edit it
21# - cvs diff -rREVA -rREVB
22# - send mail the way CVS sends it
23#
24# Performance:
25# - cache remote checksums (for every revision ever seen!)
26# - translate symbolic revisions to numeric revisions
27#
28# Reliability:
29# - remote locking
30#
31# Security:
32# - Authenticated RPC?
33
34
35from cvslib import CVS, File
36import md5
37import os
38import string
39import sys
40from cmdfw import CommandFrameWork
41
42
43DEF_LOCAL = 1 # Default -l
44
45
46class MyFile(File):
47
48 def action(self):
49 """Return a code indicating the update status of this file.
50
51 The possible return values are:
52
53 '=' -- everything's fine
54 '0' -- file doesn't exist anywhere
55 '?' -- exists locally only
56 'A' -- new locally
57 'R' -- deleted locally
58 'U' -- changed remotely, no changes locally
59 (includes new remotely or deleted remotely)
60 'M' -- changed locally, no changes remotely
61 'C' -- conflict: changed locally as well as remotely
62 (includes cases where the file has been added
63 or removed locally and remotely)
64 'D' -- deleted remotely
65 'N' -- new remotely
66 'r' -- get rid of entry
67 'c' -- create entry
68 'u' -- update entry
69
70 (and probably others :-)
71 """
72 if not self.lseen:
73 self.getlocal()
74 if not self.rseen:
75 self.getremote()
76 if not self.eseen:
77 if not self.lsum:
78 if not self.rsum: return '0' # Never heard of
79 else:
80 return 'N' # New remotely
81 else: # self.lsum
82 if not self.rsum: return '?' # Local only
83 # Local and remote, but no entry
84 if self.lsum == self.rsum:
85 return 'c' # Restore entry only
86 else: return 'C' # Real conflict
87 else: # self.eseen
88 if not self.lsum:
89 if self.edeleted:
90 if self.rsum: return 'R' # Removed
91 else: return 'r' # Get rid of entry
92 else: # not self.edeleted
93 if self.rsum:
94 print "warning:",
95 print self.file,
96 print "was lost"
97 return 'U'
98 else: return 'r' # Get rid of entry
99 else: # self.lsum
100 if not self.rsum:
101 if self.enew: return 'A' # New locally
102 else: return 'D' # Deleted remotely
103 else: # self.rsum
104 if self.enew:
105 if self.lsum == self.rsum:
106 return 'u'
107 else:
108 return 'C'
109 if self.lsum == self.esum:
110 if self.esum == self.rsum:
111 return '='
112 else:
113 return 'U'
114 elif self.esum == self.rsum:
115 return 'M'
116 elif self.lsum == self.rsum:
117 return 'u'
118 else:
119 return 'C'
120
121 def update(self):
122 code = self.action()
123 if code == '=': return
124 print code, self.file
125 if code in ('U', 'N'):
126 self.get()
127 elif code == 'C':
128 print "%s: conflict resolution not yet implemented" % \
129 self.file
130 elif code == 'D':
131 remove(self.file)
132 self.eseen = 0
133 elif code == 'r':
134 self.eseen = 0
135 elif code in ('c', 'u'):
136 self.eseen = 1
137 self.erev = self.rrev
138 self.enew = 0
139 self.edeleted = 0
140 self.esum = self.rsum
141 self.emtime, self.ectime = os.stat(self.file)[-2:]
142 self.extra = ''
143
144 def commit(self, message = ""):
145 code = self.action()
146 if code in ('A', 'M'):
147 self.put(message)
148 return 1
149 elif code == 'R':
150 print "%s: committing removes not yet implemented" % \
151 self.file
152 elif code == 'C':
153 print "%s: conflict resolution not yet implemented" % \
154 self.file
155
156 def diff(self, opts = []):
157 self.action() # To update lseen, rseen
158 flags = ''
159 rev = self.rrev
160 # XXX should support two rev options too!
161 for o, a in opts:
162 if o == '-r':
163 rev = a
164 else:
165 flags = flags + ' ' + o + a
166 if rev == self.rrev and self.lsum == self.rsum:
167 return
168 flags = flags[1:]
169 fn = self.file
170 data = self.proxy.get((fn, rev))
171 sum = md5.new(data).digest()
172 if self.lsum == sum:
173 return
174 import tempfile
175 tf = tempfile.NamedTemporaryFile()
176 tf.write(data)
177 tf.flush()
178 print 'diff %s -r%s %s' % (flags, rev, fn)
179 sts = os.system('diff %s %s %s' % (flags, tf.name, fn))
180 if sts:
181 print '='*70
182
183 def commitcheck(self):
184 return self.action() != 'C'
185
186 def put(self, message = ""):
187 print "Checking in", self.file, "..."
188 data = open(self.file).read()
189 if not self.enew:
190 self.proxy.lock(self.file)
191 messages = self.proxy.put(self.file, data, message)
192 if messages:
193 print messages
194 self.setentry(self.proxy.head(self.file), self.lsum)
195
196 def get(self):
197 data = self.proxy.get(self.file)
198 f = open(self.file, 'w')
199 f.write(data)
200 f.close()
201 self.setentry(self.rrev, self.rsum)
202
203 def log(self, otherflags):
204 print self.proxy.log(self.file, otherflags)
205
206 def add(self):
207 self.eseen = 0 # While we're hacking...
208 self.esum = self.lsum
209 self.emtime, self.ectime = 0, 0
210 self.erev = ''
211 self.enew = 1
212 self.edeleted = 0
213 self.eseen = 1 # Done
214 self.extra = ''
215
216 def setentry(self, erev, esum):
217 self.eseen = 0 # While we're hacking...
218 self.esum = esum
219 self.emtime, self.ectime = os.stat(self.file)[-2:]
220 self.erev = erev
221 self.enew = 0
222 self.edeleted = 0
223 self.eseen = 1 # Done
224 self.extra = ''
225
226
227SENDMAIL = "/usr/lib/sendmail -t"
228MAILFORM = """To: %s
229Subject: CVS changes: %s
230
231...Message from rcvs...
232
233Committed files:
234 %s
235
236Log message:
237 %s
238"""
239
240
241class RCVS(CVS):
242
243 FileClass = MyFile
244
245 def __init__(self):
246 CVS.__init__(self)
247
248 def update(self, files):
249 for e in self.whichentries(files, 1):
250 e.update()
251
252 def commit(self, files, message = ""):
253 list = self.whichentries(files)
254 if not list: return
255 ok = 1
256 for e in list:
257 if not e.commitcheck():
258 ok = 0
259 if not ok:
260 print "correct above errors first"
261 return
262 if not message:
263 message = raw_input("One-liner: ")
264 committed = []
265 for e in list:
266 if e.commit(message):
267 committed.append(e.file)
268 self.mailinfo(committed, message)
269
270 def mailinfo(self, files, message = ""):
271 towhom = "sjoerd@cwi.nl, jack@cwi.nl" # XXX
272 mailtext = MAILFORM % (towhom, string.join(files),
273 string.join(files), message)
274 print '-'*70
275 print mailtext
276 print '-'*70
277 ok = raw_input("OK to mail to %s? " % towhom)
278 if string.lower(string.strip(ok)) in ('y', 'ye', 'yes'):
279 p = os.popen(SENDMAIL, "w")
280 p.write(mailtext)
281 sts = p.close()
282 if sts:
283 print "Sendmail exit status %s" % str(sts)
284 else:
285 print "Mail sent."
286 else:
287 print "No mail sent."
288
289 def report(self, files):
290 for e in self.whichentries(files):
291 e.report()
292
293 def diff(self, files, opts):
294 for e in self.whichentries(files):
295 e.diff(opts)
296
297 def add(self, files):
298 if not files:
299 raise RuntimeError, "'cvs add' needs at least one file"
300 list = []
301 for e in self.whichentries(files, 1):
302 e.add()
303
304 def rm(self, files):
305 if not files:
306 raise RuntimeError, "'cvs rm' needs at least one file"
307 raise RuntimeError, "'cvs rm' not yet imlemented"
308
309 def log(self, files, opts):
310 flags = ''
311 for o, a in opts:
312 flags = flags + ' ' + o + a
313 for e in self.whichentries(files):
314 e.log(flags)
315
316 def whichentries(self, files, localfilestoo = 0):
317 if files:
318 list = []
319 for file in files:
320 if self.entries.has_key(file):
321 e = self.entries[file]
322 else:
323 e = self.FileClass(file)
324 self.entries[file] = e
325 list.append(e)
326 else:
327 list = self.entries.values()
328 for file in self.proxy.listfiles():
329 if self.entries.has_key(file):
330 continue
331 e = self.FileClass(file)
332 self.entries[file] = e
333 list.append(e)
334 if localfilestoo:
335 for file in os.listdir(os.curdir):
336 if not self.entries.has_key(file) \
337 and not self.ignored(file):
338 e = self.FileClass(file)
339 self.entries[file] = e
340 list.append(e)
341 list.sort()
342 if self.proxy:
343 for e in list:
344 if e.proxy is None:
345 e.proxy = self.proxy
346 return list
347
348
349class rcvs(CommandFrameWork):
350
351 GlobalFlags = 'd:h:p:qvL'
352 UsageMessage = \
353"usage: rcvs [-d directory] [-h host] [-p port] [-q] [-v] [subcommand arg ...]"
354 PostUsageMessage = \
355 "If no subcommand is given, the status of all files is listed"
356
357 def __init__(self):
358 """Constructor."""
359 CommandFrameWork.__init__(self)
360 self.proxy = None
361 self.cvs = RCVS()
362
363 def close(self):
364 if self.proxy:
365 self.proxy._close()
366 self.proxy = None
367
368 def recurse(self):
369 self.close()
370 names = os.listdir(os.curdir)
371 for name in names:
372 if name == os.curdir or name == os.pardir:
373 continue
374 if name == "CVS":
375 continue
376 if not os.path.isdir(name):
377 continue
378 if os.path.islink(name):
379 continue
380 print "--- entering subdirectory", name, "---"
381 os.chdir(name)
382 try:
383 if os.path.isdir("CVS"):
384 self.__class__().run()
385 else:
386 self.recurse()
387 finally:
388 os.chdir(os.pardir)
389 print "--- left subdirectory", name, "---"
390
391 def options(self, opts):
392 self.opts = opts
393
394 def ready(self):
395 import rcsclient
396 self.proxy = rcsclient.openrcsclient(self.opts)
397 self.cvs.setproxy(self.proxy)
398 self.cvs.getentries()
399
400 def default(self):
401 self.cvs.report([])
402
403 def do_report(self, opts, files):
404 self.cvs.report(files)
405
406 def do_update(self, opts, files):
407 """update [-l] [-R] [file] ..."""
408 local = DEF_LOCAL
409 for o, a in opts:
410 if o == '-l': local = 1
411 if o == '-R': local = 0
412 self.cvs.update(files)
413 self.cvs.putentries()
414 if not local and not files:
415 self.recurse()
416 flags_update = '-lR'
417 do_up = do_update
418 flags_up = flags_update
419
420 def do_commit(self, opts, files):
421 """commit [-m message] [file] ..."""
422 message = ""
423 for o, a in opts:
424 if o == '-m': message = a
425 self.cvs.commit(files, message)
426 self.cvs.putentries()
427 flags_commit = 'm:'
428 do_com = do_commit
429 flags_com = flags_commit
430
431 def do_diff(self, opts, files):
432 """diff [difflags] [file] ..."""
433 self.cvs.diff(files, opts)
434 flags_diff = 'cbitwcefhnlr:sD:S:'
435 do_dif = do_diff
436 flags_dif = flags_diff
437
438 def do_add(self, opts, files):
439 """add file ..."""
440 if not files:
441 print "'rcvs add' requires at least one file"
442 return
443 self.cvs.add(files)
444 self.cvs.putentries()
445
446 def do_remove(self, opts, files):
447 """remove file ..."""
448 if not files:
449 print "'rcvs remove' requires at least one file"
450 return
451 self.cvs.remove(files)
452 self.cvs.putentries()
453 do_rm = do_remove
454
455 def do_log(self, opts, files):
456 """log [rlog-options] [file] ..."""
457 self.cvs.log(files, opts)
458 flags_log = 'bhLNRtd:s:V:r:'
459
460
461def remove(fn):
462 try:
463 os.unlink(fn)
464 except os.error:
465 pass
466
467
468def main():
469 r = rcvs()
470 try:
471 r.run()
472 finally:
473 r.close()
474
475
476if __name__ == "__main__":
477 main()
sys/src/cmd/python/Demo/pdist/rrcs+8−0
@@ -0,0 +1,8 @@
1#!/usr/bin/env python
2
3import addpack
4addpack.addpack('/home/guido/src/python/Demo/pdist')
5
6import rrcs
7
8rrcs.main()
sys/src/cmd/python/Demo/pdist/rrcs.py+160−0
@@ -0,0 +1,160 @@
1#! /usr/bin/env python
2
3"Remote RCS -- command line interface"
4
5import sys
6import os
7import getopt
8import string
9import md5
10import tempfile
11from rcsclient import openrcsclient
12
13def main():
14 sys.stdout = sys.stderr
15 try:
16 opts, rest = getopt.getopt(sys.argv[1:], 'h:p:d:qvL')
17 if not rest:
18 cmd = 'head'
19 else:
20 cmd, rest = rest[0], rest[1:]
21 if not commands.has_key(cmd):
22 raise getopt.error, "unknown command"
23 coptset, func = commands[cmd]
24 copts, files = getopt.getopt(rest, coptset)
25 except getopt.error, msg:
26 print msg
27 print "usage: rrcs [options] command [options] [file] ..."
28 print "where command can be:"
29 print " ci|put # checkin the given files"
30 print " co|get # checkout"
31 print " info # print header info"
32 print " head # print revision of head branch"
33 print " list # list filename if valid"
34 print " log # print full log"
35 print " diff # diff rcs file and work file"
36 print "if no files are given, all remote rcs files are assumed"
37 sys.exit(2)
38 x = openrcsclient(opts)
39 if not files:
40 files = x.listfiles()
41 for fn in files:
42 try:
43 func(x, copts, fn)
44 except (IOError, os.error), msg:
45 print "%s: %s" % (fn, msg)
46
47def checkin(x, copts, fn):
48 f = open(fn)
49 data = f.read()
50 f.close()
51 new = not x.isvalid(fn)
52 if not new and same(x, copts, fn, data):
53 print "%s: unchanged since last checkin" % fn
54 return
55 print "Checking in", fn, "..."
56 message = asklogmessage(new)
57 messages = x.put(fn, data, message)
58 if messages:
59 print messages
60
61def checkout(x, copts, fn):
62 data = x.get(fn)
63 f = open(fn, 'w')
64 f.write(data)
65 f.close()
66
67def lock(x, copts, fn):
68 x.lock(fn)
69
70def unlock(x, copts, fn):
71 x.unlock(fn)
72
73def info(x, copts, fn):
74 dict = x.info(fn)
75 keys = dict.keys()
76 keys.sort()
77 for key in keys:
78 print key + ':', dict[key]
79 print '='*70
80
81def head(x, copts, fn):
82 head = x.head(fn)
83 print fn, head
84
85def list(x, copts, fn):
86 if x.isvalid(fn):
87 print fn
88
89def log(x, copts, fn):
90 flags = ''
91 for o, a in copts:
92 flags = flags + ' ' + o + a
93 flags = flags[1:]
94 messages = x.log(fn, flags)
95 print messages
96
97def diff(x, copts, fn):
98 if same(x, copts, fn):
99 return
100 flags = ''
101 for o, a in copts:
102 flags = flags + ' ' + o + a
103 flags = flags[1:]
104 data = x.get(fn)
105 tf = tempfile.NamedTemporaryFile()
106 tf.write(data)
107 tf.flush()
108 print 'diff %s -r%s %s' % (flags, x.head(fn), fn)
109 sts = os.system('diff %s %s %s' % (flags, tf.name, fn))
110 if sts:
111 print '='*70
112
113def same(x, copts, fn, data = None):
114 if data is None:
115 f = open(fn)
116 data = f.read()
117 f.close()
118 lsum = md5.new(data).digest()
119 rsum = x.sum(fn)
120 return lsum == rsum
121
122def asklogmessage(new):
123 if new:
124 print "enter description,",
125 else:
126 print "enter log message,",
127 print "terminate with single '.' or end of file:"
128 if new:
129 print "NOTE: This is NOT the log message!"
130 message = ""
131 while 1:
132 sys.stderr.write(">> ")
133 sys.stderr.flush()
134 line = sys.stdin.readline()
135 if not line or line == '.\n': break
136 message = message + line
137 return message
138
139def remove(fn):
140 try:
141 os.unlink(fn)
142 except os.error:
143 pass
144
145commands = {
146 'ci': ('', checkin),
147 'put': ('', checkin),
148 'co': ('', checkout),
149 'get': ('', checkout),
150 'info': ('', info),
151 'head': ('', head),
152 'list': ('', list),
153 'lock': ('', lock),
154 'unlock': ('', unlock),
155 'log': ('bhLRtd:l:r:s:w:V:', log),
156 'diff': ('c', diff),
157 }
158
159if __name__ == '__main__':
160 main()
sys/src/cmd/python/Demo/pdist/security.py+33−0
@@ -0,0 +1,33 @@
1class Security:
2
3 def __init__(self):
4 import os
5 env = os.environ
6 if env.has_key('PYTHON_KEYFILE'):
7 keyfile = env['PYTHON_KEYFILE']
8 else:
9 keyfile = '.python_keyfile'
10 if env.has_key('HOME'):
11 keyfile = os.path.join(env['HOME'], keyfile)
12 if not os.path.exists(keyfile):
13 import sys
14 for dir in sys.path:
15 kf = os.path.join(dir, keyfile)
16 if os.path.exists(kf):
17 keyfile = kf
18 break
19 try:
20 self._key = eval(open(keyfile).readline())
21 except IOError:
22 raise IOError, "python keyfile %s: cannot open" % keyfile
23
24 def _generate_challenge(self):
25 import random
26 return random.randint(100, 100000)
27
28 def _compare_challenge_response(self, challenge, response):
29 return self._encode_challenge(challenge) == response
30
31 def _encode_challenge(self, challenge):
32 p, m = self._key
33 return pow(long(challenge), p, m)
sys/src/cmd/python/Demo/pdist/server.py+145−0
@@ -0,0 +1,145 @@
1"""RPC Server module."""
2
3import sys
4import socket
5import pickle
6from fnmatch import fnmatch
7from repr import repr
8
9
10# Default verbosity (0 = silent, 1 = print connections, 2 = print requests too)
11VERBOSE = 1
12
13
14class Server:
15
16 """RPC Server class. Derive a class to implement a particular service."""
17
18 def __init__(self, address, verbose = VERBOSE):
19 if type(address) == type(0):
20 address = ('', address)
21 self._address = address
22 self._verbose = verbose
23 self._socket = None
24 self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
25 self._socket.bind(address)
26 self._socket.listen(1)
27 self._listening = 1
28
29 def _setverbose(self, verbose):
30 self._verbose = verbose
31
32 def __del__(self):
33 self._close()
34
35 def _close(self):
36 self._listening = 0
37 if self._socket:
38 self._socket.close()
39 self._socket = None
40
41 def _serverloop(self):
42 while self._listening:
43 self._serve()
44
45 def _serve(self):
46 if self._verbose: print "Wait for connection ..."
47 conn, address = self._socket.accept()
48 if self._verbose: print "Accepted connection from %s" % repr(address)
49 if not self._verify(conn, address):
50 print "*** Connection from %s refused" % repr(address)
51 conn.close()
52 return
53 rf = conn.makefile('r')
54 wf = conn.makefile('w')
55 ok = 1
56 while ok:
57 wf.flush()
58 if self._verbose > 1: print "Wait for next request ..."
59 ok = self._dorequest(rf, wf)
60
61 _valid = ['192.16.201.*', '192.16.197.*', '132.151.1.*', '129.6.64.*']
62
63 def _verify(self, conn, address):
64 host, port = address
65 for pat in self._valid:
66 if fnmatch(host, pat): return 1
67 return 0
68
69 def _dorequest(self, rf, wf):
70 rp = pickle.Unpickler(rf)
71 try:
72 request = rp.load()
73 except EOFError:
74 return 0
75 if self._verbose > 1: print "Got request: %s" % repr(request)
76 try:
77 methodname, args, id = request
78 if '.' in methodname:
79 reply = (None, self._special(methodname, args), id)
80 elif methodname[0] == '_':
81 raise NameError, "illegal method name %s" % repr(methodname)
82 else:
83 method = getattr(self, methodname)
84 reply = (None, apply(method, args), id)
85 except:
86 reply = (sys.exc_type, sys.exc_value, id)
87 if id < 0 and reply[:2] == (None, None):
88 if self._verbose > 1: print "Suppress reply"
89 return 1
90 if self._verbose > 1: print "Send reply: %s" % repr(reply)
91 wp = pickle.Pickler(wf)
92 wp.dump(reply)
93 return 1
94
95 def _special(self, methodname, args):
96 if methodname == '.methods':
97 if not hasattr(self, '_methods'):
98 self._methods = tuple(self._listmethods())
99 return self._methods
100 raise NameError, "unrecognized special method name %s" % repr(methodname)
101
102 def _listmethods(self, cl=None):
103 if not cl: cl = self.__class__
104 names = cl.__dict__.keys()
105 names = filter(lambda x: x[0] != '_', names)
106 names.sort()
107 for base in cl.__bases__:
108 basenames = self._listmethods(base)
109 basenames = filter(lambda x, names=names: x not in names, basenames)
110 names[len(names):] = basenames
111 return names
112
113
114from security import Security
115
116
117class SecureServer(Server, Security):
118
119 def __init__(self, *args):
120 apply(Server.__init__, (self,) + args)
121 Security.__init__(self)
122
123 def _verify(self, conn, address):
124 import string
125 challenge = self._generate_challenge()
126 conn.send("%d\n" % challenge)
127 response = ""
128 while "\n" not in response and len(response) < 100:
129 data = conn.recv(100)
130 if not data:
131 break
132 response = response + data
133 try:
134 response = string.atol(string.strip(response))
135 except string.atol_error:
136 if self._verbose > 0:
137 print "Invalid response syntax", repr(response)
138 return 0
139 if not self._compare_challenge_response(challenge, response):
140 if self._verbose > 0:
141 print "Invalid response value", repr(response)
142 return 0
143 if self._verbose > 1:
144 print "Response matches challenge. Go ahead!"
145 return 1
sys/src/cmd/python/Demo/pdist/sumtree.py+24−0
@@ -0,0 +1,24 @@
1import time
2import FSProxy
3
4def main():
5 t1 = time.time()
6 #proxy = FSProxy.FSProxyClient(('voorn.cwi.nl', 4127))
7 proxy = FSProxy.FSProxyLocal()
8 sumtree(proxy)
9 proxy._close()
10 t2 = time.time()
11 print t2-t1, "seconds"
12 raw_input("[Return to exit] ")
13
14def sumtree(proxy):
15 print "PWD =", proxy.pwd()
16 files = proxy.listfiles()
17 proxy.infolist(files)
18 subdirs = proxy.listsubdirs()
19 for name in subdirs:
20 proxy.cd(name)
21 sumtree(proxy)
22 proxy.back()
23
24main()
sys/src/cmd/python/Demo/pysvr/Makefile+57−0
@@ -0,0 +1,57 @@
1# Makefile for 'pysvr' application embedding Python.
2# Tailored for Python 1.5a3 or later.
3# Some details are specific for Solaris or CNRI.
4# Also see ## comments for tailoring.
5
6# Which C compiler
7CC=gcc
8##PURIFY=/usr/local/pure/purify
9LINKCC=$(PURIFY) $(CC)
10
11# Optimization preferences
12OPT=-g
13
14# Which Python version we're using
15VER=2.2
16
17# Expressions using the above definitions
18PYVER=python$(VER)
19
20# Use these defs when compiling against installed Python
21##INST=/usr/local
22##PYC=$(INST)/lib/$(PYVER)/config
23##PYINCL=-I$(INST)/include/$(PYVER) -I$(PYC)
24##PYLIBS=$(PYC)/lib$(PYVER).a
25
26# Use these defs when compiling against built Python
27PLAT=linux
28PYINCL=-I../../Include -I../../$(PLAT)
29PYLIBS=../../$(PLAT)/lib$(PYVER).a
30
31# Libraries to link with -- very installation dependent
32# (See LIBS= in Modules/Makefile in build tree)
33RLLIBS=-lreadline -ltermcap
34OTHERLIBS=-lnsl -lpthread -ldl -lm -ldb -lutil
35
36# Compilation and link flags -- no need to change normally
37CFLAGS=$(OPT)
38CPPFLAGS=$(PYINCL)
39LIBS=$(PYLIBS) $(RLLIBS) $(OTHERLIBS)
40
41# Default port for the pysvr application
42PORT=4000
43
44# Default target
45all: pysvr
46
47# Target to build pysvr
48pysvr: pysvr.o $(PYOBJS) $(PYLIBS)
49 $(LINKCC) pysvr.o $(LIBS) -o pysvr
50
51# Target to build and run pysvr
52run: pysvr
53 pysvr $(PORT)
54
55# Target to clean up the directory
56clean:
57 -rm -f pysvr *.o *~ core
sys/src/cmd/python/Demo/pysvr/README+9−0
@@ -0,0 +1,9 @@
1This is an example of a multi-threaded C application embedding a
2Python interpreter.
3
4The particular application is a multi-threaded telnet-like server that
5provides you with a Python prompt (instead of a shell prompt).
6
7The file pysvr.py is a prototype in Python.
8
9THIS APPLICATION IS NOT SECURE -- ONLY USE IT FOR TESTING!
sys/src/cmd/python/Demo/pysvr/pysvr.c+370−0
@@ -0,0 +1,370 @@
1/* A multi-threaded telnet-like server that gives a Python prompt.
2
3Usage: pysvr [port]
4
5For security reasons, it only accepts requests from the current host.
6This can still be insecure, but restricts violations from people who
7can log in on your machine. Use with caution!
8
9*/
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <ctype.h>
15#include <errno.h>
16
17#include <sys/types.h>
18#include <sys/socket.h>
19#include <netinet/in.h>
20
21#include <pthread.h>
22#include <getopt.h>
23
24/* XXX Umpfh.
25 Python.h defines a typedef destructor, which conflicts with pthread.h.
26 So Python.h must be included after pthread.h. */
27
28#include "Python.h"
29
30extern int Py_VerboseFlag;
31
32#ifndef PORT
33#define PORT 4000
34#endif
35
36struct workorder {
37 int conn;
38 struct sockaddr_in addr;
39};
40
41/* Forward */
42static void init_python(void);
43static void usage(void);
44static void oprogname(void);
45static void main_thread(int);
46static void create_thread(int, struct sockaddr_in *);
47static void *service_thread(struct workorder *);
48static void run_interpreter(FILE *, FILE *);
49static int run_command(char *, PyObject *);
50static void ps(void);
51
52static char *progname = "pysvr";
53
54static PyThreadState *gtstate;
55
56main(int argc, char **argv)
57{
58 int port = PORT;
59 int c;
60
61 if (argc > 0 && argv[0] != NULL && argv[0][0] != '\0')
62 progname = argv[0];
63
64 while ((c = getopt(argc, argv, "v")) != EOF) {
65 switch (c) {
66 case 'v':
67 Py_VerboseFlag++;
68 break;
69 default:
70 usage();
71 }
72 }
73
74 if (optind < argc) {
75 if (optind+1 < argc) {
76 oprogname();
77 fprintf(stderr, "too many arguments\n");
78 usage();
79 }
80 port = atoi(argv[optind]);
81 if (port <= 0) {
82 fprintf(stderr, "bad port (%s)\n", argv[optind]);
83 usage();
84 }
85 }
86
87 main_thread(port);
88
89 fprintf(stderr, "Bye.\n");
90
91 exit(0);
92}
93
94static char usage_line[] = "usage: %s [port]\n";
95
96static void
97usage(void)
98{
99 fprintf(stderr, usage_line, progname);
100 exit(2);
101}
102
103static void
104main_thread(int port)
105{
106 int sock, conn, size, i;
107 struct sockaddr_in addr, clientaddr;
108
109 sock = socket(PF_INET, SOCK_STREAM, 0);
110 if (sock < 0) {
111 oprogname();
112 perror("can't create socket");
113 exit(1);
114 }
115
116#ifdef SO_REUSEADDR
117 i = 1;
118 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &i, sizeof i);
119#endif
120
121 memset((char *)&addr, '\0', sizeof addr);
122 addr.sin_family = AF_INET;
123 addr.sin_port = htons(port);
124 addr.sin_addr.s_addr = 0L;
125 if (bind(sock, (struct sockaddr *)&addr, sizeof addr) < 0) {
126 oprogname();
127 perror("can't bind socket to address");
128 exit(1);
129 }
130
131 if (listen(sock, 5) < 0) {
132 oprogname();
133 perror("can't listen on socket");
134 exit(1);
135 }
136
137 fprintf(stderr, "Listening on port %d...\n", port);
138
139 for (i = 0; ; i++) {
140 size = sizeof clientaddr;
141 memset((char *) &clientaddr, '\0', size);
142 conn = accept(sock, (struct sockaddr *) &clientaddr, &size);
143 if (conn < 0) {
144 oprogname();
145 perror("can't accept connection from socket");
146 exit(1);
147 }
148
149 size = sizeof addr;
150 memset((char *) &addr, '\0', size);
151 if (getsockname(conn, (struct sockaddr *)&addr, &size) < 0) {
152 oprogname();
153 perror("can't get socket name of connection");
154 exit(1);
155 }
156 if (clientaddr.sin_addr.s_addr != addr.sin_addr.s_addr) {
157 oprogname();
158 perror("connection from non-local host refused");
159 fprintf(stderr, "(addr=%lx, clientaddr=%lx)\n",
160 ntohl(addr.sin_addr.s_addr),
161 ntohl(clientaddr.sin_addr.s_addr));
162 close(conn);
163 continue;
164 }
165 if (i == 4) {
166 close(conn);
167 break;
168 }
169 create_thread(conn, &clientaddr);
170 }
171
172 close(sock);
173
174 if (gtstate) {
175 PyEval_AcquireThread(gtstate);
176 gtstate = NULL;
177 Py_Finalize();
178 /* And a second time, just because we can. */
179 Py_Finalize(); /* This should be harmless. */
180 }
181 exit(0);
182}
183
184static void
185create_thread(int conn, struct sockaddr_in *addr)
186{
187 struct workorder *work;
188 pthread_t tdata;
189
190 work = malloc(sizeof(struct workorder));
191 if (work == NULL) {
192 oprogname();
193 fprintf(stderr, "out of memory for thread.\n");
194 close(conn);
195 return;
196 }
197 work->conn = conn;
198 work->addr = *addr;
199
200 init_python();
201
202 if (pthread_create(&tdata, NULL, (void *)service_thread, work) < 0) {
203 oprogname();
204 perror("can't create new thread");
205 close(conn);
206 return;
207 }
208
209 if (pthread_detach(tdata) < 0) {
210 oprogname();
211 perror("can't detach from thread");
212 }
213}
214
215static PyThreadState *the_tstate;
216static PyInterpreterState *the_interp;
217static PyObject *the_builtins;
218
219static void
220init_python(void)
221{
222 if (gtstate)
223 return;
224 Py_Initialize(); /* Initialize the interpreter */
225 PyEval_InitThreads(); /* Create (and acquire) the interpreter lock */
226 gtstate = PyEval_SaveThread(); /* Release the thread state */
227}
228
229static void *
230service_thread(struct workorder *work)
231{
232 FILE *input, *output;
233
234 fprintf(stderr, "Start thread for connection %d.\n", work->conn);
235
236 ps();
237
238 input = fdopen(work->conn, "r");
239 if (input == NULL) {
240 oprogname();
241 perror("can't create input stream");
242 goto done;
243 }
244
245 output = fdopen(work->conn, "w");
246 if (output == NULL) {
247 oprogname();
248 perror("can't create output stream");
249 fclose(input);
250 goto done;
251 }
252
253 setvbuf(input, NULL, _IONBF, 0);
254 setvbuf(output, NULL, _IONBF, 0);
255
256 run_interpreter(input, output);
257
258 fclose(input);
259 fclose(output);
260
261 done:
262 fprintf(stderr, "End thread for connection %d.\n", work->conn);
263 close(work->conn);
264 free(work);
265}
266
267static void
268oprogname(void)
269{
270 int save = errno;
271 fprintf(stderr, "%s: ", progname);
272 errno = save;
273}
274
275static void
276run_interpreter(FILE *input, FILE *output)
277{
278 PyThreadState *tstate;
279 PyObject *new_stdin, *new_stdout;
280 PyObject *mainmod, *globals;
281 char buffer[1000];
282 char *p, *q;
283 int n, end;
284
285 PyEval_AcquireLock();
286 tstate = Py_NewInterpreter();
287 if (tstate == NULL) {
288 fprintf(output, "Sorry -- can't create an interpreter\n");
289 return;
290 }
291
292 mainmod = PyImport_AddModule("__main__");
293 globals = PyModule_GetDict(mainmod);
294 Py_INCREF(globals);
295
296 new_stdin = PyFile_FromFile(input, "<socket-in>", "r", NULL);
297 new_stdout = PyFile_FromFile(output, "<socket-out>", "w", NULL);
298
299 PySys_SetObject("stdin", new_stdin);
300 PySys_SetObject("stdout", new_stdout);
301 PySys_SetObject("stderr", new_stdout);
302
303 for (n = 1; !PyErr_Occurred(); n++) {
304 Py_BEGIN_ALLOW_THREADS
305 fprintf(output, "%d> ", n);
306 p = fgets(buffer, sizeof buffer, input);
307 Py_END_ALLOW_THREADS
308
309 if (p == NULL)
310 break;
311 if (p[0] == '\377' && p[1] == '\354')
312 break;
313
314 q = strrchr(p, '\r');
315 if (q && q[1] == '\n' && q[2] == '\0') {
316 *q++ = '\n';
317 *q++ = '\0';
318 }
319
320 while (*p && isspace(*p))
321 p++;
322 if (p[0] == '#' || p[0] == '\0')
323 continue;
324
325 end = run_command(buffer, globals);
326 if (end < 0)
327 PyErr_Print();
328
329 if (end)
330 break;
331 }
332
333 Py_XDECREF(globals);
334 Py_XDECREF(new_stdin);
335 Py_XDECREF(new_stdout);
336
337 Py_EndInterpreter(tstate);
338 PyEval_ReleaseLock();
339
340 fprintf(output, "Goodbye!\n");
341}
342
343static int
344run_command(char *buffer, PyObject *globals)
345{
346 PyObject *m, *d, *v;
347 fprintf(stderr, "run_command: %s", buffer);
348 if (strchr(buffer, '\n') == NULL)
349 fprintf(stderr, "\n");
350 v = PyRun_String(buffer, Py_single_input, globals, globals);
351 if (v == NULL) {
352 if (PyErr_Occurred() == PyExc_SystemExit) {
353 PyErr_Clear();
354 return 1;
355 }
356 PyErr_Print();
357 return 0;
358 }
359 Py_DECREF(v);
360 return 0;
361}
362
363static void
364ps(void)
365{
366 char buffer[100];
367 PyOS_snprintf(buffer, sizeof(buffer),
368 "ps -l -p %d </dev/null | sed 1d\n", getpid());
369 system(buffer);
370}
sys/src/cmd/python/Demo/pysvr/pysvr.py+124−0
@@ -0,0 +1,124 @@
1#! /usr/bin/env python
2
3"""A multi-threaded telnet-like server that gives a Python prompt.
4
5This is really a prototype for the same thing in C.
6
7Usage: pysvr.py [port]
8
9For security reasons, it only accepts requests from the current host.
10This can still be insecure, but restricts violations from people who
11can log in on your machine. Use with caution!
12
13"""
14
15import sys, os, string, getopt, thread, socket, traceback
16
17PORT = 4000 # Default port
18
19def main():
20 try:
21 opts, args = getopt.getopt(sys.argv[1:], "")
22 if len(args) > 1:
23 raise getopt.error, "Too many arguments."
24 except getopt.error, msg:
25 usage(msg)
26 for o, a in opts:
27 pass
28 if args:
29 try:
30 port = string.atoi(args[0])
31 except ValueError, msg:
32 usage(msg)
33 else:
34 port = PORT
35 main_thread(port)
36
37def usage(msg=None):
38 sys.stdout = sys.stderr
39 if msg:
40 print msg
41 print "\n", __doc__,
42 sys.exit(2)
43
44def main_thread(port):
45 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
46 sock.bind(("", port))
47 sock.listen(5)
48 print "Listening on port", port, "..."
49 while 1:
50 (conn, addr) = sock.accept()
51 if addr[0] != conn.getsockname()[0]:
52 conn.close()
53 print "Refusing connection from non-local host", addr[0], "."
54 continue
55 thread.start_new_thread(service_thread, (conn, addr))
56 del conn, addr
57
58def service_thread(conn, addr):
59 (caddr, cport) = addr
60 print "Thread %s has connection from %s.\n" % (str(thread.get_ident()),
61 caddr),
62 stdin = conn.makefile("r")
63 stdout = conn.makefile("w", 0)
64 run_interpreter(stdin, stdout)
65 print "Thread %s is done.\n" % str(thread.get_ident()),
66
67def run_interpreter(stdin, stdout):
68 globals = {}
69 try:
70 str(sys.ps1)
71 except:
72 sys.ps1 = ">>> "
73 source = ""
74 while 1:
75 stdout.write(sys.ps1)
76 line = stdin.readline()
77 if line[:2] == '\377\354':
78 line = ""
79 if not line and not source:
80 break
81 if line[-2:] == '\r\n':
82 line = line[:-2] + '\n'
83 source = source + line
84 try:
85 code = compile_command(source)
86 except SyntaxError, err:
87 source = ""
88 traceback.print_exception(SyntaxError, err, None, file=stdout)
89 continue
90 if not code:
91 continue
92 source = ""
93 try:
94 run_command(code, stdin, stdout, globals)
95 except SystemExit, how:
96 if how:
97 try:
98 how = str(how)
99 except:
100 how = ""
101 stdout.write("Exit %s\n" % how)
102 break
103 stdout.write("\nGoodbye.\n")
104
105def run_command(code, stdin, stdout, globals):
106 save = sys.stdin, sys.stdout, sys.stderr
107 try:
108 sys.stdout = sys.stderr = stdout
109 sys.stdin = stdin
110 try:
111 exec code in globals
112 except SystemExit, how:
113 raise SystemExit, how, sys.exc_info()[2]
114 except:
115 type, value, tb = sys.exc_info()
116 if tb: tb = tb.tb_next
117 traceback.print_exception(type, value, tb)
118 del tb
119 finally:
120 sys.stdin, sys.stdout, sys.stderr = save
121
122from code import compile_command
123
124main()
sys/src/cmd/python/Demo/rpc/MANIFEST+10−0
@@ -0,0 +1,10 @@
1 File Name Archive # Description
2-----------------------------------------------------------
3 MANIFEST 1 This shipping list
4 README 1
5 T.py 1
6 mountclient.py 1
7 nfsclient.py 1
8 rpc.py 1
9 test 1
10 xdr.py 1
sys/src/cmd/python/Demo/rpc/README+31−0
@@ -0,0 +1,31 @@
1This is a Python interface to Sun RPC, designed and implemented mostly
2by reading the Internet RFCs about the subject.
3
4*** NOTE: xdr.py has evolved into the standard module xdrlib.py ***
5
6There are two library modules, xdr.py and rpc.py, and several example
7clients: mountclient.py, nfsclient.py, and rnusersclient.py,
8implementing the NFS Mount protocol, (part of) the NFS protocol, and
9the "rnusers" protocol (used by rusers(1)), respectively. The latter
10demonstrates the use of broadcast via the Port mapper's CALLIT
11procedure.
12
13There is also a way to create servers in Python.
14
15To test the nfs client, run it from the shell with something like this:
16
17 python -c 'import nfsclient; nfsclient.test()' [hostname [filesystemname]]
18
19When called without a filesystemname, it lists the filesystems at the
20host; default host is the local machine.
21
22Other clients are tested similarly.
23
24For hostname, use e.g. wuarchive.wustl.edu or gatekeeper.dec.com (two
25hosts that are known to export NFS filesystems with little restrictions).
26
27There are now two different RPC compilers:
28
291) Wim Lewis rpcgen.py found on http://www.omnigroup.com/~wiml/soft/stale-index.html#python.
30
312) Peter �strands rpcgen.py, which is part of "pynfs" (http://www.cendio.se/~peter/pynfs/).
sys/src/cmd/python/Demo/rpc/T.py+22−0
@@ -0,0 +1,22 @@
1# Simple interface to report execution times of program fragments.
2# Call TSTART() to reset the timer, TSTOP(...) to report times.
3
4import sys, os, time
5
6def TSTART():
7 global t0, t1
8 u, s, cu, cs = os.times()
9 t0 = u+cu, s+cs, time.time()
10
11def TSTOP(*label):
12 global t0, t1
13 u, s, cu, cs = os.times()
14 t1 = u+cu, s+cs, time.time()
15 tt = []
16 for i in range(3):
17 tt.append(t1[i] - t0[i])
18 [u, s, r] = tt
19 msg = ''
20 for x in label: msg = msg + (x + ' ')
21 msg = msg + '%r user, %r sys, %r real\n' % (u, s, r)
22 sys.stderr.write(msg)
sys/src/cmd/python/Demo/rpc/mountclient.py+202−0
@@ -0,0 +1,202 @@
1# Mount RPC client -- RFC 1094 (NFS), Appendix A
2
3# This module demonstrates how to write your own RPC client in Python.
4# When this example was written, there was no RPC compiler for
5# Python. Without such a compiler, you must first create classes
6# derived from Packer and Unpacker to handle the data types for the
7# server you want to interface to. You then write the client class.
8# If you want to support both the TCP and the UDP version of a
9# protocol, use multiple inheritance as shown below.
10
11
12import rpc
13from rpc import Packer, Unpacker, TCPClient, UDPClient
14
15
16# Program number and version for the mount protocol
17MOUNTPROG = 100005
18MOUNTVERS = 1
19
20# Size of the 'fhandle' opaque structure
21FHSIZE = 32
22
23
24# Packer derived class for Mount protocol clients.
25# The only thing we need to pack beyond basic types is an 'fhandle'
26
27class MountPacker(Packer):
28
29 def pack_fhandle(self, fhandle):
30 self.pack_fopaque(FHSIZE, fhandle)
31
32
33# Unpacker derived class for Mount protocol clients.
34# The important types we need to unpack are fhandle, fhstatus,
35# mountlist and exportlist; mountstruct, exportstruct and groups are
36# used to unpack components of mountlist and exportlist and the
37# corresponding functions are passed as function argument to the
38# generic unpack_list function.
39
40class MountUnpacker(Unpacker):
41
42 def unpack_fhandle(self):
43 return self.unpack_fopaque(FHSIZE)
44
45 def unpack_fhstatus(self):
46 status = self.unpack_uint()
47 if status == 0:
48 fh = self.unpack_fhandle()
49 else:
50 fh = None
51 return status, fh
52
53 def unpack_mountlist(self):
54 return self.unpack_list(self.unpack_mountstruct)
55
56 def unpack_mountstruct(self):
57 hostname = self.unpack_string()
58 directory = self.unpack_string()
59 return (hostname, directory)
60
61 def unpack_exportlist(self):
62 return self.unpack_list(self.unpack_exportstruct)
63
64 def unpack_exportstruct(self):
65 filesys = self.unpack_string()
66 groups = self.unpack_groups()
67 return (filesys, groups)
68
69 def unpack_groups(self):
70 return self.unpack_list(self.unpack_string)
71
72
73# These are the procedures specific to the Mount client class.
74# Think of this as a derived class of either TCPClient or UDPClient.
75
76class PartialMountClient:
77
78 # This method is called by Client.__init__ to initialize
79 # self.packer and self.unpacker
80 def addpackers(self):
81 self.packer = MountPacker()
82 self.unpacker = MountUnpacker('')
83
84 # This method is called by Client.__init__ to bind the socket
85 # to a particular network interface and port. We use the
86 # default network interface, but if we're running as root,
87 # we want to bind to a reserved port
88 def bindsocket(self):
89 import os
90 try:
91 uid = os.getuid()
92 except AttributeError:
93 uid = 1
94 if uid == 0:
95 port = rpc.bindresvport(self.sock, '')
96 # 'port' is not used
97 else:
98 self.sock.bind(('', 0))
99
100 # This function is called to cough up a suitable
101 # authentication object for a call to procedure 'proc'.
102 def mkcred(self):
103 if self.cred == None:
104 self.cred = rpc.AUTH_UNIX, rpc.make_auth_unix_default()
105 return self.cred
106
107 # The methods Mnt, Dump etc. each implement one Remote
108 # Procedure Call. This is done by calling self.make_call()
109 # with as arguments:
110 #
111 # - the procedure number
112 # - the arguments (or None)
113 # - the "packer" function for the arguments (or None)
114 # - the "unpacker" function for the return value (or None)
115 #
116 # The packer and unpacker function, if not None, *must* be
117 # methods of self.packer and self.unpacker, respectively.
118 # A value of None means that there are no arguments or is no
119 # return value, respectively.
120 #
121 # The return value from make_call() is the return value from
122 # the remote procedure call, as unpacked by the "unpacker"
123 # function, or None if the unpacker function is None.
124 #
125 # (Even if you expect a result of None, you should still
126 # return the return value from make_call(), since this may be
127 # needed by a broadcasting version of the class.)
128 #
129 # If the call fails, make_call() raises an exception
130 # (this includes time-outs and invalid results).
131 #
132 # Note that (at least with the UDP protocol) there is no
133 # guarantee that a call is executed at most once. When you do
134 # get a reply, you know it has been executed at least once;
135 # when you don't get a reply, you know nothing.
136
137 def Mnt(self, directory):
138 return self.make_call(1, directory, \
139 self.packer.pack_string, \
140 self.unpacker.unpack_fhstatus)
141
142 def Dump(self):
143 return self.make_call(2, None, \
144 None, self.unpacker.unpack_mountlist)
145
146 def Umnt(self, directory):
147 return self.make_call(3, directory, \
148 self.packer.pack_string, None)
149
150 def Umntall(self):
151 return self.make_call(4, None, None, None)
152
153 def Export(self):
154 return self.make_call(5, None, \
155 None, self.unpacker.unpack_exportlist)
156
157
158# We turn the partial Mount client into a full one for either protocol
159# by use of multiple inheritance. (In general, when class C has base
160# classes B1...Bn, if x is an instance of class C, methods of x are
161# searched first in C, then in B1, then in B2, ..., finally in Bn.)
162
163class TCPMountClient(PartialMountClient, TCPClient):
164
165 def __init__(self, host):
166 TCPClient.__init__(self, host, MOUNTPROG, MOUNTVERS)
167
168
169class UDPMountClient(PartialMountClient, UDPClient):
170
171 def __init__(self, host):
172 UDPClient.__init__(self, host, MOUNTPROG, MOUNTVERS)
173
174
175# A little test program for the Mount client. This takes a host as
176# command line argument (default the local machine), prints its export
177# list, and attempts to mount and unmount each exported files system.
178# An optional first argument of -t or -u specifies the protocol to use
179# (TCP or UDP), default is UDP.
180
181def test():
182 import sys
183 if sys.argv[1:] and sys.argv[1] == '-t':
184 C = TCPMountClient
185 del sys.argv[1]
186 elif sys.argv[1:] and sys.argv[1] == '-u':
187 C = UDPMountClient
188 del sys.argv[1]
189 else:
190 C = UDPMountClient
191 if sys.argv[1:]: host = sys.argv[1]
192 else: host = ''
193 mcl = C(host)
194 list = mcl.Export()
195 for item in list:
196 print item
197 try:
198 mcl.Mnt(item[0])
199 except:
200 print 'Sorry'
201 continue
202 mcl.Umnt(item[0])
sys/src/cmd/python/Demo/rpc/nfsclient.py+201−0
@@ -0,0 +1,201 @@
1# NFS RPC client -- RFC 1094
2
3# XXX This is not yet complete.
4# XXX Only GETATTR, SETTTR, LOOKUP and READDIR are supported.
5
6# (See mountclient.py for some hints on how to write RPC clients in
7# Python in general)
8
9import rpc
10from rpc import UDPClient, TCPClient
11from mountclient import FHSIZE, MountPacker, MountUnpacker
12
13NFS_PROGRAM = 100003
14NFS_VERSION = 2
15
16# enum stat
17NFS_OK = 0
18# (...many error values...)
19
20# enum ftype
21NFNON = 0
22NFREG = 1
23NFDIR = 2
24NFBLK = 3
25NFCHR = 4
26NFLNK = 5
27
28
29class NFSPacker(MountPacker):
30
31 def pack_sattrargs(self, sa):
32 file, attributes = sa
33 self.pack_fhandle(file)
34 self.pack_sattr(attributes)
35
36 def pack_sattr(self, sa):
37 mode, uid, gid, size, atime, mtime = sa
38 self.pack_uint(mode)
39 self.pack_uint(uid)
40 self.pack_uint(gid)
41 self.pack_uint(size)
42 self.pack_timeval(atime)
43 self.pack_timeval(mtime)
44
45 def pack_diropargs(self, da):
46 dir, name = da
47 self.pack_fhandle(dir)
48 self.pack_string(name)
49
50 def pack_readdirargs(self, ra):
51 dir, cookie, count = ra
52 self.pack_fhandle(dir)
53 self.pack_uint(cookie)
54 self.pack_uint(count)
55
56 def pack_timeval(self, tv):
57 secs, usecs = tv
58 self.pack_uint(secs)
59 self.pack_uint(usecs)
60
61
62class NFSUnpacker(MountUnpacker):
63
64 def unpack_readdirres(self):
65 status = self.unpack_enum()
66 if status == NFS_OK:
67 entries = self.unpack_list(self.unpack_entry)
68 eof = self.unpack_bool()
69 rest = (entries, eof)
70 else:
71 rest = None
72 return (status, rest)
73
74 def unpack_entry(self):
75 fileid = self.unpack_uint()
76 name = self.unpack_string()
77 cookie = self.unpack_uint()
78 return (fileid, name, cookie)
79
80 def unpack_diropres(self):
81 status = self.unpack_enum()
82 if status == NFS_OK:
83 fh = self.unpack_fhandle()
84 fa = self.unpack_fattr()
85 rest = (fh, fa)
86 else:
87 rest = None
88 return (status, rest)
89
90 def unpack_attrstat(self):
91 status = self.unpack_enum()
92 if status == NFS_OK:
93 attributes = self.unpack_fattr()
94 else:
95 attributes = None
96 return status, attributes
97
98 def unpack_fattr(self):
99 type = self.unpack_enum()
100 mode = self.unpack_uint()
101 nlink = self.unpack_uint()
102 uid = self.unpack_uint()
103 gid = self.unpack_uint()
104 size = self.unpack_uint()
105 blocksize = self.unpack_uint()
106 rdev = self.unpack_uint()
107 blocks = self.unpack_uint()
108 fsid = self.unpack_uint()
109 fileid = self.unpack_uint()
110 atime = self.unpack_timeval()
111 mtime = self.unpack_timeval()
112 ctime = self.unpack_timeval()
113 return (type, mode, nlink, uid, gid, size, blocksize, \
114 rdev, blocks, fsid, fileid, atime, mtime, ctime)
115
116 def unpack_timeval(self):
117 secs = self.unpack_uint()
118 usecs = self.unpack_uint()
119 return (secs, usecs)
120
121
122class NFSClient(UDPClient):
123
124 def __init__(self, host):
125 UDPClient.__init__(self, host, NFS_PROGRAM, NFS_VERSION)
126
127 def addpackers(self):
128 self.packer = NFSPacker()
129 self.unpacker = NFSUnpacker('')
130
131 def mkcred(self):
132 if self.cred == None:
133 self.cred = rpc.AUTH_UNIX, rpc.make_auth_unix_default()
134 return self.cred
135
136 def Getattr(self, fh):
137 return self.make_call(1, fh, \
138 self.packer.pack_fhandle, \
139 self.unpacker.unpack_attrstat)
140
141 def Setattr(self, sa):
142 return self.make_call(2, sa, \
143 self.packer.pack_sattrargs, \
144 self.unpacker.unpack_attrstat)
145
146 # Root() is obsolete
147
148 def Lookup(self, da):
149 return self.make_call(4, da, \
150 self.packer.pack_diropargs, \
151 self.unpacker.unpack_diropres)
152
153 # ...
154
155 def Readdir(self, ra):
156 return self.make_call(16, ra, \
157 self.packer.pack_readdirargs, \
158 self.unpacker.unpack_readdirres)
159
160 # Shorthand to get the entire contents of a directory
161 def Listdir(self, dir):
162 list = []
163 ra = (dir, 0, 2000)
164 while 1:
165 (status, rest) = self.Readdir(ra)
166 if status <> NFS_OK:
167 break
168 entries, eof = rest
169 last_cookie = None
170 for fileid, name, cookie in entries:
171 list.append((fileid, name))
172 last_cookie = cookie
173 if eof or last_cookie == None:
174 break
175 ra = (ra[0], last_cookie, ra[2])
176 return list
177
178
179def test():
180 import sys
181 if sys.argv[1:]: host = sys.argv[1]
182 else: host = ''
183 if sys.argv[2:]: filesys = sys.argv[2]
184 else: filesys = None
185 from mountclient import UDPMountClient, TCPMountClient
186 mcl = TCPMountClient(host)
187 if filesys == None:
188 list = mcl.Export()
189 for item in list:
190 print item
191 return
192 sf = mcl.Mnt(filesys)
193 print sf
194 fh = sf[1]
195 if fh:
196 ncl = NFSClient(host)
197 as = ncl.Getattr(fh)
198 print as
199 list = ncl.Listdir(fh)
200 for item in list: print item
201 mcl.Umnt(filesys)
sys/src/cmd/python/Demo/rpc/rnusersclient.py+98−0
@@ -0,0 +1,98 @@
1# Remote nusers client interface
2
3import rpc
4from rpc import Packer, Unpacker, UDPClient, BroadcastUDPClient
5
6
7class RnusersPacker(Packer):
8 def pack_utmp(self, ui):
9 ut_line, ut_name, ut_host, ut_time = utmp
10 self.pack_string(ut_line)
11 self.pack_string(ut_name)
12 self.pack_string(ut_host)
13 self.pack_int(ut_time)
14 def pack_utmpidle(self, ui):
15 ui_itmp, ui_idle = ui
16 self.pack_utmp(ui_utmp)
17 self.pack_uint(ui_idle)
18 def pack_utmpidlearr(self, list):
19 self.pack_array(list, self.pack_itmpidle)
20
21
22class RnusersUnpacker(Unpacker):
23 def unpack_utmp(self):
24 ut_line = self.unpack_string()
25 ut_name = self.unpack_string()
26 ut_host = self.unpack_string()
27 ut_time = self.unpack_int()
28 return ut_line, ut_name, ut_host, ut_time
29 def unpack_utmpidle(self):
30 ui_utmp = self.unpack_utmp()
31 ui_idle = self.unpack_uint()
32 return ui_utmp, ui_idle
33 def unpack_utmpidlearr(self):
34 return self.unpack_array(self.unpack_utmpidle)
35
36
37class PartialRnusersClient:
38
39 def addpackers(self):
40 self.packer = RnusersPacker()
41 self.unpacker = RnusersUnpacker('')
42
43 def Num(self):
44 return self.make_call(1, None, None, self.unpacker.unpack_int)
45
46 def Names(self):
47 return self.make_call(2, None, \
48 None, self.unpacker.unpack_utmpidlearr)
49
50 def Allnames(self):
51 return self.make_call(3, None, \
52 None, self.unpacker.unpack_utmpidlearr)
53
54
55class RnusersClient(PartialRnusersClient, UDPClient):
56
57 def __init__(self, host):
58 UDPClient.__init__(self, host, 100002, 2)
59
60
61class BroadcastRnusersClient(PartialRnusersClient, BroadcastUDPClient):
62
63 def __init__(self, bcastaddr):
64 BroadcastUDPClient.__init__(self, bcastaddr, 100002, 2)
65
66
67def test():
68 import sys
69 if not sys.argv[1:]:
70 testbcast()
71 return
72 else:
73 host = sys.argv[1]
74 c = RnusersClient(host)
75 list = c.Names()
76 for (line, name, host, time), idle in list:
77 line = strip0(line)
78 name = strip0(name)
79 host = strip0(host)
80 print "%r %r %r %s %s" % (name, host, line, time, idle)
81
82def testbcast():
83 c = BroadcastRnusersClient('<broadcast>')
84 def listit(list, fromaddr):
85 host, port = fromaddr
86 print host + '\t:',
87 for (line, name, host, time), idle in list:
88 print strip0(name),
89 print
90 c.set_reply_handler(listit)
91 all = c.Names()
92 print 'Total Count:', len(all)
93
94def strip0(s):
95 while s and s[-1] == '\0': s = s[:-1]
96 return s
97
98test()
sys/src/cmd/python/Demo/rpc/rpc.py+893−0
@@ -0,0 +1,893 @@
1# Sun RPC version 2 -- RFC1057.
2
3# XXX There should be separate exceptions for the various reasons why
4# XXX an RPC can fail, rather than using RuntimeError for everything
5
6# XXX Need to use class based exceptions rather than string exceptions
7
8# XXX The UDP version of the protocol resends requests when it does
9# XXX not receive a timely reply -- use only for idempotent calls!
10
11# XXX There is no provision for call timeout on TCP connections
12
13import xdr
14import socket
15import os
16
17RPCVERSION = 2
18
19CALL = 0
20REPLY = 1
21
22AUTH_NULL = 0
23AUTH_UNIX = 1
24AUTH_SHORT = 2
25AUTH_DES = 3
26
27MSG_ACCEPTED = 0
28MSG_DENIED = 1
29
30SUCCESS = 0 # RPC executed successfully
31PROG_UNAVAIL = 1 # remote hasn't exported program
32PROG_MISMATCH = 2 # remote can't support version #
33PROC_UNAVAIL = 3 # program can't support procedure
34GARBAGE_ARGS = 4 # procedure can't decode params
35
36RPC_MISMATCH = 0 # RPC version number != 2
37AUTH_ERROR = 1 # remote can't authenticate caller
38
39AUTH_BADCRED = 1 # bad credentials (seal broken)
40AUTH_REJECTEDCRED = 2 # client must begin new session
41AUTH_BADVERF = 3 # bad verifier (seal broken)
42AUTH_REJECTEDVERF = 4 # verifier expired or replayed
43AUTH_TOOWEAK = 5 # rejected for security reasons
44
45
46class Packer(xdr.Packer):
47
48 def pack_auth(self, auth):
49 flavor, stuff = auth
50 self.pack_enum(flavor)
51 self.pack_opaque(stuff)
52
53 def pack_auth_unix(self, stamp, machinename, uid, gid, gids):
54 self.pack_uint(stamp)
55 self.pack_string(machinename)
56 self.pack_uint(uid)
57 self.pack_uint(gid)
58 self.pack_uint(len(gids))
59 for i in gids:
60 self.pack_uint(i)
61
62 def pack_callheader(self, xid, prog, vers, proc, cred, verf):
63 self.pack_uint(xid)
64 self.pack_enum(CALL)
65 self.pack_uint(RPCVERSION)
66 self.pack_uint(prog)
67 self.pack_uint(vers)
68 self.pack_uint(proc)
69 self.pack_auth(cred)
70 self.pack_auth(verf)
71 # Caller must add procedure-specific part of call
72
73 def pack_replyheader(self, xid, verf):
74 self.pack_uint(xid)
75 self.pack_enum(REPLY)
76 self.pack_uint(MSG_ACCEPTED)
77 self.pack_auth(verf)
78 self.pack_enum(SUCCESS)
79 # Caller must add procedure-specific part of reply
80
81
82# Exceptions
83BadRPCFormat = 'rpc.BadRPCFormat'
84BadRPCVersion = 'rpc.BadRPCVersion'
85GarbageArgs = 'rpc.GarbageArgs'
86
87class Unpacker(xdr.Unpacker):
88
89 def unpack_auth(self):
90 flavor = self.unpack_enum()
91 stuff = self.unpack_opaque()
92 return (flavor, stuff)
93
94 def unpack_callheader(self):
95 xid = self.unpack_uint()
96 temp = self.unpack_enum()
97 if temp != CALL:
98 raise BadRPCFormat, 'no CALL but %r' % (temp,)
99 temp = self.unpack_uint()
100 if temp != RPCVERSION:
101 raise BadRPCVersion, 'bad RPC version %r' % (temp,)
102 prog = self.unpack_uint()
103 vers = self.unpack_uint()
104 proc = self.unpack_uint()
105 cred = self.unpack_auth()
106 verf = self.unpack_auth()
107 return xid, prog, vers, proc, cred, verf
108 # Caller must add procedure-specific part of call
109
110 def unpack_replyheader(self):
111 xid = self.unpack_uint()
112 mtype = self.unpack_enum()
113 if mtype != REPLY:
114 raise RuntimeError, 'no REPLY but %r' % (mtype,)
115 stat = self.unpack_enum()
116 if stat == MSG_DENIED:
117 stat = self.unpack_enum()
118 if stat == RPC_MISMATCH:
119 low = self.unpack_uint()
120 high = self.unpack_uint()
121 raise RuntimeError, \
122 'MSG_DENIED: RPC_MISMATCH: %r' % ((low, high),)
123 if stat == AUTH_ERROR:
124 stat = self.unpack_uint()
125 raise RuntimeError, \
126 'MSG_DENIED: AUTH_ERROR: %r' % (stat,)
127 raise RuntimeError, 'MSG_DENIED: %r' % (stat,)
128 if stat != MSG_ACCEPTED:
129 raise RuntimeError, \
130 'Neither MSG_DENIED nor MSG_ACCEPTED: %r' % (stat,)
131 verf = self.unpack_auth()
132 stat = self.unpack_enum()
133 if stat == PROG_UNAVAIL:
134 raise RuntimeError, 'call failed: PROG_UNAVAIL'
135 if stat == PROG_MISMATCH:
136 low = self.unpack_uint()
137 high = self.unpack_uint()
138 raise RuntimeError, \
139 'call failed: PROG_MISMATCH: %r' % ((low, high),)
140 if stat == PROC_UNAVAIL:
141 raise RuntimeError, 'call failed: PROC_UNAVAIL'
142 if stat == GARBAGE_ARGS:
143 raise RuntimeError, 'call failed: GARBAGE_ARGS'
144 if stat != SUCCESS:
145 raise RuntimeError, 'call failed: %r' % (stat,)
146 return xid, verf
147 # Caller must get procedure-specific part of reply
148
149
150# Subroutines to create opaque authentication objects
151
152def make_auth_null():
153 return ''
154
155def make_auth_unix(seed, host, uid, gid, groups):
156 p = Packer()
157 p.pack_auth_unix(seed, host, uid, gid, groups)
158 return p.get_buf()
159
160def make_auth_unix_default():
161 try:
162 from os import getuid, getgid
163 uid = getuid()
164 gid = getgid()
165 except ImportError:
166 uid = gid = 0
167 import time
168 return make_auth_unix(int(time.time()-unix_epoch()), \
169 socket.gethostname(), uid, gid, [])
170
171_unix_epoch = -1
172def unix_epoch():
173 """Very painful calculation of when the Unix Epoch is.
174
175 This is defined as the return value of time.time() on Jan 1st,
176 1970, 00:00:00 GMT.
177
178 On a Unix system, this should always return 0.0. On a Mac, the
179 calculations are needed -- and hard because of integer overflow
180 and other limitations.
181
182 """
183 global _unix_epoch
184 if _unix_epoch >= 0: return _unix_epoch
185 import time
186 now = time.time()
187 localt = time.localtime(now) # (y, m, d, hh, mm, ss, ..., ..., ...)
188 gmt = time.gmtime(now)
189 offset = time.mktime(localt) - time.mktime(gmt)
190 y, m, d, hh, mm, ss = 1970, 1, 1, 0, 0, 0
191 offset, ss = divmod(ss + offset, 60)
192 offset, mm = divmod(mm + offset, 60)
193 offset, hh = divmod(hh + offset, 24)
194 d = d + offset
195 _unix_epoch = time.mktime((y, m, d, hh, mm, ss, 0, 0, 0))
196 print "Unix epoch:", time.ctime(_unix_epoch)
197 return _unix_epoch
198
199
200# Common base class for clients
201
202class Client:
203
204 def __init__(self, host, prog, vers, port):
205 self.host = host
206 self.prog = prog
207 self.vers = vers
208 self.port = port
209 self.makesocket() # Assigns to self.sock
210 self.bindsocket()
211 self.connsocket()
212 self.lastxid = 0 # XXX should be more random?
213 self.addpackers()
214 self.cred = None
215 self.verf = None
216
217 def close(self):
218 self.sock.close()
219
220 def makesocket(self):
221 # This MUST be overridden
222 raise RuntimeError, 'makesocket not defined'
223
224 def connsocket(self):
225 # Override this if you don't want/need a connection
226 self.sock.connect((self.host, self.port))
227
228 def bindsocket(self):
229 # Override this to bind to a different port (e.g. reserved)
230 self.sock.bind(('', 0))
231
232 def addpackers(self):
233 # Override this to use derived classes from Packer/Unpacker
234 self.packer = Packer()
235 self.unpacker = Unpacker('')
236
237 def make_call(self, proc, args, pack_func, unpack_func):
238 # Don't normally override this (but see Broadcast)
239 if pack_func is None and args is not None:
240 raise TypeError, 'non-null args with null pack_func'
241 self.start_call(proc)
242 if pack_func:
243 pack_func(args)
244 self.do_call()
245 if unpack_func:
246 result = unpack_func()
247 else:
248 result = None
249 self.unpacker.done()
250 return result
251
252 def start_call(self, proc):
253 # Don't override this
254 self.lastxid = xid = self.lastxid + 1
255 cred = self.mkcred()
256 verf = self.mkverf()
257 p = self.packer
258 p.reset()
259 p.pack_callheader(xid, self.prog, self.vers, proc, cred, verf)
260
261 def do_call(self):
262 # This MUST be overridden
263 raise RuntimeError, 'do_call not defined'
264
265 def mkcred(self):
266 # Override this to use more powerful credentials
267 if self.cred == None:
268 self.cred = (AUTH_NULL, make_auth_null())
269 return self.cred
270
271 def mkverf(self):
272 # Override this to use a more powerful verifier
273 if self.verf == None:
274 self.verf = (AUTH_NULL, make_auth_null())
275 return self.verf
276
277 def call_0(self): # Procedure 0 is always like this
278 return self.make_call(0, None, None, None)
279
280
281# Record-Marking standard support
282
283def sendfrag(sock, last, frag):
284 x = len(frag)
285 if last: x = x | 0x80000000L
286 header = (chr(int(x>>24 & 0xff)) + chr(int(x>>16 & 0xff)) + \
287 chr(int(x>>8 & 0xff)) + chr(int(x & 0xff)))
288 sock.send(header + frag)
289
290def sendrecord(sock, record):
291 sendfrag(sock, 1, record)
292
293def recvfrag(sock):
294 header = sock.recv(4)
295 if len(header) < 4:
296 raise EOFError
297 x = long(ord(header[0]))<<24 | ord(header[1])<<16 | \
298 ord(header[2])<<8 | ord(header[3])
299 last = ((x & 0x80000000) != 0)
300 n = int(x & 0x7fffffff)
301 frag = ''
302 while n > 0:
303 buf = sock.recv(n)
304 if not buf: raise EOFError
305 n = n - len(buf)
306 frag = frag + buf
307 return last, frag
308
309def recvrecord(sock):
310 record = ''
311 last = 0
312 while not last:
313 last, frag = recvfrag(sock)
314 record = record + frag
315 return record
316
317
318# Try to bind to a reserved port (must be root)
319
320last_resv_port_tried = None
321def bindresvport(sock, host):
322 global last_resv_port_tried
323 FIRST, LAST = 600, 1024 # Range of ports to try
324 if last_resv_port_tried == None:
325 import os
326 last_resv_port_tried = FIRST + os.getpid() % (LAST-FIRST)
327 for i in range(last_resv_port_tried, LAST) + \
328 range(FIRST, last_resv_port_tried):
329 last_resv_port_tried = i
330 try:
331 sock.bind((host, i))
332 return last_resv_port_tried
333 except socket.error, (errno, msg):
334 if errno != 114:
335 raise socket.error, (errno, msg)
336 raise RuntimeError, 'can\'t assign reserved port'
337
338
339# Client using TCP to a specific port
340
341class RawTCPClient(Client):
342
343 def makesocket(self):
344 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
345
346 def do_call(self):
347 call = self.packer.get_buf()
348 sendrecord(self.sock, call)
349 reply = recvrecord(self.sock)
350 u = self.unpacker
351 u.reset(reply)
352 xid, verf = u.unpack_replyheader()
353 if xid != self.lastxid:
354 # Can't really happen since this is TCP...
355 raise RuntimeError, 'wrong xid in reply %r instead of %r' % (
356 xid, self.lastxid)
357
358
359# Client using UDP to a specific port
360
361class RawUDPClient(Client):
362
363 def makesocket(self):
364 self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
365
366 def do_call(self):
367 call = self.packer.get_buf()
368 self.sock.send(call)
369 try:
370 from select import select
371 except ImportError:
372 print 'WARNING: select not found, RPC may hang'
373 select = None
374 BUFSIZE = 8192 # Max UDP buffer size
375 timeout = 1
376 count = 5
377 while 1:
378 r, w, x = [self.sock], [], []
379 if select:
380 r, w, x = select(r, w, x, timeout)
381 if self.sock not in r:
382 count = count - 1
383 if count < 0: raise RuntimeError, 'timeout'
384 if timeout < 25: timeout = timeout *2
385## print 'RESEND', timeout, count
386 self.sock.send(call)
387 continue
388 reply = self.sock.recv(BUFSIZE)
389 u = self.unpacker
390 u.reset(reply)
391 xid, verf = u.unpack_replyheader()
392 if xid != self.lastxid:
393## print 'BAD xid'
394 continue
395 break
396
397
398# Client using UDP broadcast to a specific port
399
400class RawBroadcastUDPClient(RawUDPClient):
401
402 def __init__(self, bcastaddr, prog, vers, port):
403 RawUDPClient.__init__(self, bcastaddr, prog, vers, port)
404 self.reply_handler = None
405 self.timeout = 30
406
407 def connsocket(self):
408 # Don't connect -- use sendto
409 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
410
411 def set_reply_handler(self, reply_handler):
412 self.reply_handler = reply_handler
413
414 def set_timeout(self, timeout):
415 self.timeout = timeout # Use None for infinite timeout
416
417 def make_call(self, proc, args, pack_func, unpack_func):
418 if pack_func is None and args is not None:
419 raise TypeError, 'non-null args with null pack_func'
420 self.start_call(proc)
421 if pack_func:
422 pack_func(args)
423 call = self.packer.get_buf()
424 self.sock.sendto(call, (self.host, self.port))
425 try:
426 from select import select
427 except ImportError:
428 print 'WARNING: select not found, broadcast will hang'
429 select = None
430 BUFSIZE = 8192 # Max UDP buffer size (for reply)
431 replies = []
432 if unpack_func is None:
433 def dummy(): pass
434 unpack_func = dummy
435 while 1:
436 r, w, x = [self.sock], [], []
437 if select:
438 if self.timeout is None:
439 r, w, x = select(r, w, x)
440 else:
441 r, w, x = select(r, w, x, self.timeout)
442 if self.sock not in r:
443 break
444 reply, fromaddr = self.sock.recvfrom(BUFSIZE)
445 u = self.unpacker
446 u.reset(reply)
447 xid, verf = u.unpack_replyheader()
448 if xid != self.lastxid:
449## print 'BAD xid'
450 continue
451 reply = unpack_func()
452 self.unpacker.done()
453 replies.append((reply, fromaddr))
454 if self.reply_handler:
455 self.reply_handler(reply, fromaddr)
456 return replies
457
458
459# Port mapper interface
460
461# Program number, version and (fixed!) port number
462PMAP_PROG = 100000
463PMAP_VERS = 2
464PMAP_PORT = 111
465
466# Procedure numbers
467PMAPPROC_NULL = 0 # (void) -> void
468PMAPPROC_SET = 1 # (mapping) -> bool
469PMAPPROC_UNSET = 2 # (mapping) -> bool
470PMAPPROC_GETPORT = 3 # (mapping) -> unsigned int
471PMAPPROC_DUMP = 4 # (void) -> pmaplist
472PMAPPROC_CALLIT = 5 # (call_args) -> call_result
473
474# A mapping is (prog, vers, prot, port) and prot is one of:
475
476IPPROTO_TCP = 6
477IPPROTO_UDP = 17
478
479# A pmaplist is a variable-length list of mappings, as follows:
480# either (1, mapping, pmaplist) or (0).
481
482# A call_args is (prog, vers, proc, args) where args is opaque;
483# a call_result is (port, res) where res is opaque.
484
485
486class PortMapperPacker(Packer):
487
488 def pack_mapping(self, mapping):
489 prog, vers, prot, port = mapping
490 self.pack_uint(prog)
491 self.pack_uint(vers)
492 self.pack_uint(prot)
493 self.pack_uint(port)
494
495 def pack_pmaplist(self, list):
496 self.pack_list(list, self.pack_mapping)
497
498 def pack_call_args(self, ca):
499 prog, vers, proc, args = ca
500 self.pack_uint(prog)
501 self.pack_uint(vers)
502 self.pack_uint(proc)
503 self.pack_opaque(args)
504
505
506class PortMapperUnpacker(Unpacker):
507
508 def unpack_mapping(self):
509 prog = self.unpack_uint()
510 vers = self.unpack_uint()
511 prot = self.unpack_uint()
512 port = self.unpack_uint()
513 return prog, vers, prot, port
514
515 def unpack_pmaplist(self):
516 return self.unpack_list(self.unpack_mapping)
517
518 def unpack_call_result(self):
519 port = self.unpack_uint()
520 res = self.unpack_opaque()
521 return port, res
522
523
524class PartialPortMapperClient:
525
526 def addpackers(self):
527 self.packer = PortMapperPacker()
528 self.unpacker = PortMapperUnpacker('')
529
530 def Set(self, mapping):
531 return self.make_call(PMAPPROC_SET, mapping, \
532 self.packer.pack_mapping, \
533 self.unpacker.unpack_uint)
534
535 def Unset(self, mapping):
536 return self.make_call(PMAPPROC_UNSET, mapping, \
537 self.packer.pack_mapping, \
538 self.unpacker.unpack_uint)
539
540 def Getport(self, mapping):
541 return self.make_call(PMAPPROC_GETPORT, mapping, \
542 self.packer.pack_mapping, \
543 self.unpacker.unpack_uint)
544
545 def Dump(self):
546 return self.make_call(PMAPPROC_DUMP, None, \
547 None, \
548 self.unpacker.unpack_pmaplist)
549
550 def Callit(self, ca):
551 return self.make_call(PMAPPROC_CALLIT, ca, \
552 self.packer.pack_call_args, \
553 self.unpacker.unpack_call_result)
554
555
556class TCPPortMapperClient(PartialPortMapperClient, RawTCPClient):
557
558 def __init__(self, host):
559 RawTCPClient.__init__(self, \
560 host, PMAP_PROG, PMAP_VERS, PMAP_PORT)
561
562
563class UDPPortMapperClient(PartialPortMapperClient, RawUDPClient):
564
565 def __init__(self, host):
566 RawUDPClient.__init__(self, \
567 host, PMAP_PROG, PMAP_VERS, PMAP_PORT)
568
569
570class BroadcastUDPPortMapperClient(PartialPortMapperClient, \
571 RawBroadcastUDPClient):
572
573 def __init__(self, bcastaddr):
574 RawBroadcastUDPClient.__init__(self, \
575 bcastaddr, PMAP_PROG, PMAP_VERS, PMAP_PORT)
576
577
578# Generic clients that find their server through the Port mapper
579
580class TCPClient(RawTCPClient):
581
582 def __init__(self, host, prog, vers):
583 pmap = TCPPortMapperClient(host)
584 port = pmap.Getport((prog, vers, IPPROTO_TCP, 0))
585 pmap.close()
586 if port == 0:
587 raise RuntimeError, 'program not registered'
588 RawTCPClient.__init__(self, host, prog, vers, port)
589
590
591class UDPClient(RawUDPClient):
592
593 def __init__(self, host, prog, vers):
594 pmap = UDPPortMapperClient(host)
595 port = pmap.Getport((prog, vers, IPPROTO_UDP, 0))
596 pmap.close()
597 if port == 0:
598 raise RuntimeError, 'program not registered'
599 RawUDPClient.__init__(self, host, prog, vers, port)
600
601
602class BroadcastUDPClient(Client):
603
604 def __init__(self, bcastaddr, prog, vers):
605 self.pmap = BroadcastUDPPortMapperClient(bcastaddr)
606 self.pmap.set_reply_handler(self.my_reply_handler)
607 self.prog = prog
608 self.vers = vers
609 self.user_reply_handler = None
610 self.addpackers()
611
612 def close(self):
613 self.pmap.close()
614
615 def set_reply_handler(self, reply_handler):
616 self.user_reply_handler = reply_handler
617
618 def set_timeout(self, timeout):
619 self.pmap.set_timeout(timeout)
620
621 def my_reply_handler(self, reply, fromaddr):
622 port, res = reply
623 self.unpacker.reset(res)
624 result = self.unpack_func()
625 self.unpacker.done()
626 self.replies.append((result, fromaddr))
627 if self.user_reply_handler is not None:
628 self.user_reply_handler(result, fromaddr)
629
630 def make_call(self, proc, args, pack_func, unpack_func):
631 self.packer.reset()
632 if pack_func:
633 pack_func(args)
634 if unpack_func is None:
635 def dummy(): pass
636 self.unpack_func = dummy
637 else:
638 self.unpack_func = unpack_func
639 self.replies = []
640 packed_args = self.packer.get_buf()
641 dummy_replies = self.pmap.Callit( \
642 (self.prog, self.vers, proc, packed_args))
643 return self.replies
644
645
646# Server classes
647
648# These are not symmetric to the Client classes
649# XXX No attempt is made to provide authorization hooks yet
650
651class Server:
652
653 def __init__(self, host, prog, vers, port):
654 self.host = host # Should normally be '' for default interface
655 self.prog = prog
656 self.vers = vers
657 self.port = port # Should normally be 0 for random port
658 self.makesocket() # Assigns to self.sock and self.prot
659 self.bindsocket()
660 self.host, self.port = self.sock.getsockname()
661 self.addpackers()
662
663 def register(self):
664 mapping = self.prog, self.vers, self.prot, self.port
665 p = TCPPortMapperClient(self.host)
666 if not p.Set(mapping):
667 raise RuntimeError, 'register failed'
668
669 def unregister(self):
670 mapping = self.prog, self.vers, self.prot, self.port
671 p = TCPPortMapperClient(self.host)
672 if not p.Unset(mapping):
673 raise RuntimeError, 'unregister failed'
674
675 def handle(self, call):
676 # Don't use unpack_header but parse the header piecewise
677 # XXX I have no idea if I am using the right error responses!
678 self.unpacker.reset(call)
679 self.packer.reset()
680 xid = self.unpacker.unpack_uint()
681 self.packer.pack_uint(xid)
682 temp = self.unpacker.unpack_enum()
683 if temp != CALL:
684 return None # Not worthy of a reply
685 self.packer.pack_uint(REPLY)
686 temp = self.unpacker.unpack_uint()
687 if temp != RPCVERSION:
688 self.packer.pack_uint(MSG_DENIED)
689 self.packer.pack_uint(RPC_MISMATCH)
690 self.packer.pack_uint(RPCVERSION)
691 self.packer.pack_uint(RPCVERSION)
692 return self.packer.get_buf()
693 self.packer.pack_uint(MSG_ACCEPTED)
694 self.packer.pack_auth((AUTH_NULL, make_auth_null()))
695 prog = self.unpacker.unpack_uint()
696 if prog != self.prog:
697 self.packer.pack_uint(PROG_UNAVAIL)
698 return self.packer.get_buf()
699 vers = self.unpacker.unpack_uint()
700 if vers != self.vers:
701 self.packer.pack_uint(PROG_MISMATCH)
702 self.packer.pack_uint(self.vers)
703 self.packer.pack_uint(self.vers)
704 return self.packer.get_buf()
705 proc = self.unpacker.unpack_uint()
706 methname = 'handle_' + repr(proc)
707 try:
708 meth = getattr(self, methname)
709 except AttributeError:
710 self.packer.pack_uint(PROC_UNAVAIL)
711 return self.packer.get_buf()
712 cred = self.unpacker.unpack_auth()
713 verf = self.unpacker.unpack_auth()
714 try:
715 meth() # Unpack args, call turn_around(), pack reply
716 except (EOFError, GarbageArgs):
717 # Too few or too many arguments
718 self.packer.reset()
719 self.packer.pack_uint(xid)
720 self.packer.pack_uint(REPLY)
721 self.packer.pack_uint(MSG_ACCEPTED)
722 self.packer.pack_auth((AUTH_NULL, make_auth_null()))
723 self.packer.pack_uint(GARBAGE_ARGS)
724 return self.packer.get_buf()
725
726 def turn_around(self):
727 try:
728 self.unpacker.done()
729 except RuntimeError:
730 raise GarbageArgs
731 self.packer.pack_uint(SUCCESS)
732
733 def handle_0(self): # Handle NULL message
734 self.turn_around()
735
736 def makesocket(self):
737 # This MUST be overridden
738 raise RuntimeError, 'makesocket not defined'
739
740 def bindsocket(self):
741 # Override this to bind to a different port (e.g. reserved)
742 self.sock.bind((self.host, self.port))
743
744 def addpackers(self):
745 # Override this to use derived classes from Packer/Unpacker
746 self.packer = Packer()
747 self.unpacker = Unpacker('')
748
749
750class TCPServer(Server):
751
752 def makesocket(self):
753 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
754 self.prot = IPPROTO_TCP
755
756 def loop(self):
757 self.sock.listen(0)
758 while 1:
759 self.session(self.sock.accept())
760
761 def session(self, connection):
762 sock, (host, port) = connection
763 while 1:
764 try:
765 call = recvrecord(sock)
766 except EOFError:
767 break
768 except socket.error, msg:
769 print 'socket error:', msg
770 break
771 reply = self.handle(call)
772 if reply is not None:
773 sendrecord(sock, reply)
774
775 def forkingloop(self):
776 # Like loop but uses forksession()
777 self.sock.listen(0)
778 while 1:
779 self.forksession(self.sock.accept())
780
781 def forksession(self, connection):
782 # Like session but forks off a subprocess
783 import os
784 # Wait for deceased children
785 try:
786 while 1:
787 pid, sts = os.waitpid(0, 1)
788 except os.error:
789 pass
790 pid = None
791 try:
792 pid = os.fork()
793 if pid: # Parent
794 connection[0].close()
795 return
796 # Child
797 self.session(connection)
798 finally:
799 # Make sure we don't fall through in the parent
800 if pid == 0:
801 os._exit(0)
802
803
804class UDPServer(Server):
805
806 def makesocket(self):
807 self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
808 self.prot = IPPROTO_UDP
809
810 def loop(self):
811 while 1:
812 self.session()
813
814 def session(self):
815 call, host_port = self.sock.recvfrom(8192)
816 reply = self.handle(call)
817 if reply != None:
818 self.sock.sendto(reply, host_port)
819
820
821# Simple test program -- dump local portmapper status
822
823def test():
824 pmap = UDPPortMapperClient('')
825 list = pmap.Dump()
826 list.sort()
827 for prog, vers, prot, port in list:
828 print prog, vers,
829 if prot == IPPROTO_TCP: print 'tcp',
830 elif prot == IPPROTO_UDP: print 'udp',
831 else: print prot,
832 print port
833
834
835# Test program for broadcast operation -- dump everybody's portmapper status
836
837def testbcast():
838 import sys
839 if sys.argv[1:]:
840 bcastaddr = sys.argv[1]
841 else:
842 bcastaddr = '<broadcast>'
843 def rh(reply, fromaddr):
844 host, port = fromaddr
845 print host + '\t' + repr(reply)
846 pmap = BroadcastUDPPortMapperClient(bcastaddr)
847 pmap.set_reply_handler(rh)
848 pmap.set_timeout(5)
849 replies = pmap.Getport((100002, 1, IPPROTO_UDP, 0))
850
851
852# Test program for server, with corresponding client
853# On machine A: python -c 'import rpc; rpc.testsvr()'
854# On machine B: python -c 'import rpc; rpc.testclt()' A
855# (A may be == B)
856
857def testsvr():
858 # Simple test class -- proc 1 doubles its string argument as reply
859 class S(UDPServer):
860 def handle_1(self):
861 arg = self.unpacker.unpack_string()
862 self.turn_around()
863 print 'RPC function 1 called, arg', repr(arg)
864 self.packer.pack_string(arg + arg)
865 #
866 s = S('', 0x20000000, 1, 0)
867 try:
868 s.unregister()
869 except RuntimeError, msg:
870 print 'RuntimeError:', msg, '(ignored)'
871 s.register()
872 print 'Service started...'
873 try:
874 s.loop()
875 finally:
876 s.unregister()
877 print 'Service interrupted.'
878
879
880def testclt():
881 import sys
882 if sys.argv[1:]: host = sys.argv[1]
883 else: host = ''
884 # Client for above server
885 class C(UDPClient):
886 def call_1(self, arg):
887 return self.make_call(1, arg, \
888 self.packer.pack_string, \
889 self.unpacker.unpack_string)
890 c = C(host, 0x20000000, 1)
891 print 'making call...'
892 reply = c.call_1('hello, world, ')
893 print 'call returned', repr(reply)
sys/src/cmd/python/Demo/rpc/test+24−0
@@ -0,0 +1,24 @@
1: ${PYTHON=python}
2: ${SERVER=charon.cwi.nl}
3
4set -xe
5
6$PYTHON -c 'from rpc import test; test()'
7$PYTHON -c 'from rpc import test; test()' ${SERVER}
8
9$PYTHON -c 'from rpc import testsvr; testsvr()' &
10PID=$!
11sleep 2
12$PYTHON -c 'from rpc import testclt; testclt()'
13kill -2 $PID
14
15$PYTHON -c 'from mountclient import test; test()'
16$PYTHON -c 'from mountclient import test; test()' gatekeeper.dec.com
17
18$PYTHON -c 'from nfsclient import test; test()'
19$PYTHON -c 'from nfsclient import test; test()' gatekeeper.dec.com
20$PYTHON -c 'from nfsclient import test; test()' gatekeeper.dec.com /archive
21
22$PYTHON -c 'from rnusersclient import test; test()' ''
23
24$PYTHON -c 'from rpc import testbcast; testbcast()'
sys/src/cmd/python/Demo/rpc/xdr.py+200−0
@@ -0,0 +1,200 @@
1# Implement (a subset of) Sun XDR -- RFC1014.
2
3
4try:
5 import struct
6except ImportError:
7 struct = None
8
9
10Long = type(0L)
11
12
13class Packer:
14
15 def __init__(self):
16 self.reset()
17
18 def reset(self):
19 self.buf = ''
20
21 def get_buf(self):
22 return self.buf
23
24 def pack_uint(self, x):
25 self.buf = self.buf + \
26 (chr(int(x>>24 & 0xff)) + chr(int(x>>16 & 0xff)) + \
27 chr(int(x>>8 & 0xff)) + chr(int(x & 0xff)))
28 if struct and struct.pack('l', 1) == '\0\0\0\1':
29 def pack_uint(self, x):
30 if type(x) == Long:
31 x = int((x + 0x80000000L) % 0x100000000L \
32 - 0x80000000L)
33 self.buf = self.buf + struct.pack('l', x)
34
35 pack_int = pack_uint
36
37 pack_enum = pack_int
38
39 def pack_bool(self, x):
40 if x: self.buf = self.buf + '\0\0\0\1'
41 else: self.buf = self.buf + '\0\0\0\0'
42
43 def pack_uhyper(self, x):
44 self.pack_uint(int(x>>32 & 0xffffffff))
45 self.pack_uint(int(x & 0xffffffff))
46
47 pack_hyper = pack_uhyper
48
49 def pack_float(self, x):
50 # XXX
51 self.buf = self.buf + struct.pack('f', x)
52
53 def pack_double(self, x):
54 # XXX
55 self.buf = self.buf + struct.pack('d', x)
56
57 def pack_fstring(self, n, s):
58 if n < 0:
59 raise ValueError, 'fstring size must be nonnegative'
60 n = ((n+3)/4)*4
61 data = s[:n]
62 data = data + (n - len(data)) * '\0'
63 self.buf = self.buf + data
64
65 pack_fopaque = pack_fstring
66
67 def pack_string(self, s):
68 n = len(s)
69 self.pack_uint(n)
70 self.pack_fstring(n, s)
71
72 pack_opaque = pack_string
73
74 def pack_list(self, list, pack_item):
75 for item in list:
76 self.pack_uint(1)
77 pack_item(item)
78 self.pack_uint(0)
79
80 def pack_farray(self, n, list, pack_item):
81 if len(list) <> n:
82 raise ValueError, 'wrong array size'
83 for item in list:
84 pack_item(item)
85
86 def pack_array(self, list, pack_item):
87 n = len(list)
88 self.pack_uint(n)
89 self.pack_farray(n, list, pack_item)
90
91
92class Unpacker:
93
94 def __init__(self, data):
95 self.reset(data)
96
97 def reset(self, data):
98 self.buf = data
99 self.pos = 0
100
101 def done(self):
102 if self.pos < len(self.buf):
103 raise RuntimeError, 'unextracted data remains'
104
105 def unpack_uint(self):
106 i = self.pos
107 self.pos = j = i+4
108 data = self.buf[i:j]
109 if len(data) < 4:
110 raise EOFError
111 x = long(ord(data[0]))<<24 | ord(data[1])<<16 | \
112 ord(data[2])<<8 | ord(data[3])
113 # Return a Python long only if the value is not representable
114 # as a nonnegative Python int
115 if x < 0x80000000L: x = int(x)
116 return x
117 if struct and struct.unpack('l', '\0\0\0\1') == 1:
118 def unpack_uint(self):
119 i = self.pos
120 self.pos = j = i+4
121 data = self.buf[i:j]
122 if len(data) < 4:
123 raise EOFError
124 return struct.unpack('l', data)
125
126 def unpack_int(self):
127 x = self.unpack_uint()
128 if x >= 0x80000000L: x = x - 0x100000000L
129 return int(x)
130
131 unpack_enum = unpack_int
132
133 unpack_bool = unpack_int
134
135 def unpack_uhyper(self):
136 hi = self.unpack_uint()
137 lo = self.unpack_uint()
138 return long(hi)<<32 | lo
139
140 def unpack_hyper(self):
141 x = self.unpack_uhyper()
142 if x >= 0x8000000000000000L: x = x - 0x10000000000000000L
143 return x
144
145 def unpack_float(self):
146 # XXX
147 i = self.pos
148 self.pos = j = i+4
149 data = self.buf[i:j]
150 if len(data) < 4:
151 raise EOFError
152 return struct.unpack('f', data)[0]
153
154 def unpack_double(self):
155 # XXX
156 i = self.pos
157 self.pos = j = i+8
158 data = self.buf[i:j]
159 if len(data) < 8:
160 raise EOFError
161 return struct.unpack('d', data)[0]
162
163 def unpack_fstring(self, n):
164 if n < 0:
165 raise ValueError, 'fstring size must be nonnegative'
166 i = self.pos
167 j = i + (n+3)/4*4
168 if j > len(self.buf):
169 raise EOFError
170 self.pos = j
171 return self.buf[i:i+n]
172
173 unpack_fopaque = unpack_fstring
174
175 def unpack_string(self):
176 n = self.unpack_uint()
177 return self.unpack_fstring(n)
178
179 unpack_opaque = unpack_string
180
181 def unpack_list(self, unpack_item):
182 list = []
183 while 1:
184 x = self.unpack_uint()
185 if x == 0: break
186 if x <> 1:
187 raise RuntimeError, '0 or 1 expected, got %r' % (x, )
188 item = unpack_item()
189 list.append(item)
190 return list
191
192 def unpack_farray(self, n, unpack_item):
193 list = []
194 for i in range(n):
195 list.append(unpack_item())
196 return list
197
198 def unpack_array(self, unpack_item):
199 n = self.unpack_uint()
200 return self.unpack_farray(n, unpack_item)
sys/src/cmd/python/Demo/scripts/README+23−0
@@ -0,0 +1,23 @@
1This directory contains a collection of executable Python scripts.
2
3See also the Tools/scripts directory!
4
5beer.py Print the classic 'bottles of beer' list.
6eqfix.py Fix .py files to use the correct equality test operator
7fact.py Factorize numbers
8find-uname.py Search for Unicode characters using regexps.
9from.py Summarize mailbox
10ftpstats.py Summarize ftp daemon log file
11lpwatch.py Watch BSD line printer queues
12makedir.py Like mkdir -p
13markov.py Markov chain simulation of words or characters
14mboxconvvert.py Convert MH or MMDF mailboxes to unix mailbox format
15mkrcs.py Fix symlinks named RCS into parallel tree
16morse.py Produce morse code (audible or on AIFF file)
17pi.py Print all digits of pi -- given enough time and memory
18pp.py Emulate some Perl command line options
19primes.py Print prime numbers
20queens.py Dijkstra's solution to Wirth's "N Queens problem"
21script.py Equivalent to BSD script(1) -- by Steen Lumholt
22unbirthday.py Print unbirthday count
23update.py Update a bunch of files according to a script.
sys/src/cmd/python/Demo/scripts/beer.py+14−0
@@ -0,0 +1,14 @@
1#! /usr/bin/env python
2# By GvR, demystified after a version by Fredrik Lundh.
3import sys
4n = 100
5if sys.argv[1:]: n = int(sys.argv[1])
6def bottle(n):
7 if n == 0: return "no more bottles of beer"
8 if n == 1: return "one bottle of beer"
9 return str(n) + " bottles of beer"
10for i in range(n):
11 print bottle(n-i), "on the wall,"
12 print bottle(n-i) + "."
13 print "Take one down, pass it around,"
14 print bottle(n-i-1), "on the wall."
sys/src/cmd/python/Demo/scripts/eqfix.py+198−0
@@ -0,0 +1,198 @@
1#! /usr/bin/env python
2
3# Fix Python source files to use the new equality test operator, i.e.,
4# if x = y: ...
5# is changed to
6# if x == y: ...
7# The script correctly tokenizes the Python program to reliably
8# distinguish between assignments and equality tests.
9#
10# Command line arguments are files or directories to be processed.
11# Directories are searched recursively for files whose name looks
12# like a python module.
13# Symbolic links are always ignored (except as explicit directory
14# arguments). Of course, the original file is kept as a back-up
15# (with a "~" attached to its name).
16# It complains about binaries (files containing null bytes)
17# and about files that are ostensibly not Python files: if the first
18# line starts with '#!' and does not contain the string 'python'.
19#
20# Changes made are reported to stdout in a diff-like format.
21#
22# Undoubtedly you can do this using find and sed or perl, but this is
23# a nice example of Python code that recurses down a directory tree
24# and uses regular expressions. Also note several subtleties like
25# preserving the file's mode and avoiding to even write a temp file
26# when no changes are needed for a file.
27#
28# NB: by changing only the function fixline() you can turn this
29# into a program for a different change to Python programs...
30
31import sys
32import re
33import os
34from stat import *
35import string
36
37err = sys.stderr.write
38dbg = err
39rep = sys.stdout.write
40
41def main():
42 bad = 0
43 if not sys.argv[1:]: # No arguments
44 err('usage: ' + sys.argv[0] + ' file-or-directory ...\n')
45 sys.exit(2)
46 for arg in sys.argv[1:]:
47 if os.path.isdir(arg):
48 if recursedown(arg): bad = 1
49 elif os.path.islink(arg):
50 err(arg + ': will not process symbolic links\n')
51 bad = 1
52 else:
53 if fix(arg): bad = 1
54 sys.exit(bad)
55
56ispythonprog = re.compile('^[a-zA-Z0-9_]+\.py$')
57def ispython(name):
58 return ispythonprog.match(name) >= 0
59
60def recursedown(dirname):
61 dbg('recursedown(%r)\n' % (dirname,))
62 bad = 0
63 try:
64 names = os.listdir(dirname)
65 except os.error, msg:
66 err('%s: cannot list directory: %r\n' % (dirname, msg))
67 return 1
68 names.sort()
69 subdirs = []
70 for name in names:
71 if name in (os.curdir, os.pardir): continue
72 fullname = os.path.join(dirname, name)
73 if os.path.islink(fullname): pass
74 elif os.path.isdir(fullname):
75 subdirs.append(fullname)
76 elif ispython(name):
77 if fix(fullname): bad = 1
78 for fullname in subdirs:
79 if recursedown(fullname): bad = 1
80 return bad
81
82def fix(filename):
83## dbg('fix(%r)\n' % (dirname,))
84 try:
85 f = open(filename, 'r')
86 except IOError, msg:
87 err('%s: cannot open: %r\n' % (filename, msg))
88 return 1
89 head, tail = os.path.split(filename)
90 tempname = os.path.join(head, '@' + tail)
91 g = None
92 # If we find a match, we rewind the file and start over but
93 # now copy everything to a temp file.
94 lineno = 0
95 while 1:
96 line = f.readline()
97 if not line: break
98 lineno = lineno + 1
99 if g is None and '\0' in line:
100 # Check for binary files
101 err(filename + ': contains null bytes; not fixed\n')
102 f.close()
103 return 1
104 if lineno == 1 and g is None and line[:2] == '#!':
105 # Check for non-Python scripts
106 words = string.split(line[2:])
107 if words and re.search('[pP]ython', words[0]) < 0:
108 msg = filename + ': ' + words[0]
109 msg = msg + ' script; not fixed\n'
110 err(msg)
111 f.close()
112 return 1
113 while line[-2:] == '\\\n':
114 nextline = f.readline()
115 if not nextline: break
116 line = line + nextline
117 lineno = lineno + 1
118 newline = fixline(line)
119 if newline != line:
120 if g is None:
121 try:
122 g = open(tempname, 'w')
123 except IOError, msg:
124 f.close()
125 err('%s: cannot create: %r\n' % (tempname, msg))
126 return 1
127 f.seek(0)
128 lineno = 0
129 rep(filename + ':\n')
130 continue # restart from the beginning
131 rep(repr(lineno) + '\n')
132 rep('< ' + line)
133 rep('> ' + newline)
134 if g is not None:
135 g.write(newline)
136
137 # End of file
138 f.close()
139 if not g: return 0 # No changes
140
141 # Finishing touch -- move files
142
143 # First copy the file's mode to the temp file
144 try:
145 statbuf = os.stat(filename)
146 os.chmod(tempname, statbuf[ST_MODE] & 07777)
147 except os.error, msg:
148 err('%s: warning: chmod failed (%r)\n' % (tempname, msg))
149 # Then make a backup of the original file as filename~
150 try:
151 os.rename(filename, filename + '~')
152 except os.error, msg:
153 err('%s: warning: backup failed (%r)\n' % (filename, msg))
154 # Now move the temp file to the original file
155 try:
156 os.rename(tempname, filename)
157 except os.error, msg:
158 err('%s: rename failed (%r)\n' % (filename, msg))
159 return 1
160 # Return succes
161 return 0
162
163
164from tokenize import tokenprog
165
166match = {'if':':', 'elif':':', 'while':':', 'return':'\n', \
167 '(':')', '[':']', '{':'}', '`':'`'}
168
169def fixline(line):
170 # Quick check for easy case
171 if '=' not in line: return line
172
173 i, n = 0, len(line)
174 stack = []
175 while i < n:
176 j = tokenprog.match(line, i)
177 if j < 0:
178 # A bad token; forget about the rest of this line
179 print '(Syntax error:)'
180 print line,
181 return line
182 a, b = tokenprog.regs[3] # Location of the token proper
183 token = line[a:b]
184 i = i+j
185 if stack and token == stack[-1]:
186 del stack[-1]
187 elif match.has_key(token):
188 stack.append(match[token])
189 elif token == '=' and stack:
190 line = line[:a] + '==' + line[b:]
191 i, n = a + len('=='), len(line)
192 elif token == '==' and not stack:
193 print '(Warning: \'==\' at top level:)'
194 print line,
195 return line
196
197if __name__ == "__main__":
198 main()
sys/src/cmd/python/Demo/scripts/fact.py+49−0
@@ -0,0 +1,49 @@
1#! /usr/bin/env python
2
3# Factorize numbers.
4# The algorithm is not efficient, but easy to understand.
5# If there are large factors, it will take forever to find them,
6# because we try all odd numbers between 3 and sqrt(n)...
7
8import sys
9from math import sqrt
10
11error = 'fact.error' # exception
12
13def fact(n):
14 if n < 1: raise error # fact() argument should be >= 1
15 if n == 1: return [] # special case
16 res = []
17 # Treat even factors special, so we can use i = i+2 later
18 while n%2 == 0:
19 res.append(2)
20 n = n/2
21 # Try odd numbers up to sqrt(n)
22 limit = sqrt(float(n+1))
23 i = 3
24 while i <= limit:
25 if n%i == 0:
26 res.append(i)
27 n = n/i
28 limit = sqrt(n+1)
29 else:
30 i = i+2
31 if n != 1:
32 res.append(n)
33 return res
34
35def main():
36 if len(sys.argv) > 1:
37 for arg in sys.argv[1:]:
38 n = eval(arg)
39 print n, fact(n)
40 else:
41 try:
42 while 1:
43 n = input()
44 print n, fact(n)
45 except EOFError:
46 pass
47
48if __name__ == "__main__":
49 main()
sys/src/cmd/python/Demo/scripts/find-uname.py+40−0
@@ -0,0 +1,40 @@
1#!/usr/bin/env python
2
3"""
4For each argument on the command line, look for it in the set of all Unicode
5names. Arguments are treated as case-insensitive regular expressions, e.g.:
6
7 % find-uname 'small letter a$' 'horizontal line'
8 *** small letter a$ matches ***
9 LATIN SMALL LETTER A (97)
10 COMBINING LATIN SMALL LETTER A (867)
11 CYRILLIC SMALL LETTER A (1072)
12 PARENTHESIZED LATIN SMALL LETTER A (9372)
13 CIRCLED LATIN SMALL LETTER A (9424)
14 FULLWIDTH LATIN SMALL LETTER A (65345)
15 *** horizontal line matches ***
16 HORIZONTAL LINE EXTENSION (9135)
17"""
18
19import unicodedata
20import sys
21import re
22
23def main(args):
24 unicode_names= []
25 for ix in range(sys.maxunicode+1):
26 try:
27 unicode_names.append( (ix, unicodedata.name(unichr(ix))) )
28 except ValueError: # no name for the character
29 pass
30 for arg in args:
31 pat = re.compile(arg, re.I)
32 matches = [(x,y) for (x,y) in unicode_names
33 if pat.search(y) is not None]
34 if matches:
35 print "***", arg, "matches", "***"
36 for (x,y) in matches:
37 print "%s (%d)" % (y,x)
38
39if __name__ == "__main__":
40 main(sys.argv[1:])
sys/src/cmd/python/Demo/scripts/from.py+35−0
@@ -0,0 +1,35 @@
1#! /usr/bin/env python
2
3# Print From and Subject of messages in $MAIL.
4# Extension to multiple mailboxes and other bells & whistles are left
5# as exercises for the reader.
6
7import sys, os
8
9# Open mailbox file. Exits with exception when this fails.
10
11try:
12 mailbox = os.environ['MAIL']
13except (AttributeError, KeyError):
14 sys.stderr.write('No environment variable $MAIL\n')
15 sys.exit(2)
16
17try:
18 mail = open(mailbox)
19except IOError:
20 sys.exit('Cannot open mailbox file: ' + mailbox)
21
22while 1:
23 line = mail.readline()
24 if not line:
25 break # EOF
26 if line.startswith('From '):
27 # Start of message found
28 print line[:-1],
29 while 1:
30 line = mail.readline()
31 if not line or line == '\n':
32 break
33 if line.startswith('Subject: '):
34 print repr(line[9:-1]),
35 print
sys/src/cmd/python/Demo/scripts/ftpstats.py+145−0
@@ -0,0 +1,145 @@
1#! /usr/bin/env python
2
3# Extract statistics from ftp daemon log.
4
5# Usage:
6# ftpstats [-m maxitems] [-s search] [file]
7# -m maxitems: restrict number of items in "top-N" lists, default 25.
8# -s string: restrict statistics to lines containing this string.
9# Default file is /usr/adm/ftpd; a "-" means read standard input.
10
11# The script must be run on the host where the ftp daemon runs.
12# (At CWI this is currently buizerd.)
13
14import os
15import sys
16import re
17import string
18import getopt
19
20pat = '^([a-zA-Z0-9 :]*)!(.*)!(.*)!([<>].*)!([0-9]+)!([0-9]+)$'
21prog = re.compile(pat)
22
23def main():
24 maxitems = 25
25 search = None
26 try:
27 opts, args = getopt.getopt(sys.argv[1:], 'm:s:')
28 except getopt.error, msg:
29 print msg
30 print 'usage: ftpstats [-m maxitems] [file]'
31 sys.exit(2)
32 for o, a in opts:
33 if o == '-m':
34 maxitems = string.atoi(a)
35 if o == '-s':
36 search = a
37 file = '/usr/adm/ftpd'
38 if args: file = args[0]
39 if file == '-':
40 f = sys.stdin
41 else:
42 try:
43 f = open(file, 'r')
44 except IOError, msg:
45 print file, ':', msg
46 sys.exit(1)
47 bydate = {}
48 bytime = {}
49 byfile = {}
50 bydir = {}
51 byhost = {}
52 byuser = {}
53 bytype = {}
54 lineno = 0
55 try:
56 while 1:
57 line = f.readline()
58 if not line: break
59 lineno = lineno + 1
60 if search and string.find(line, search) < 0:
61 continue
62 if prog.match(line) < 0:
63 print 'Bad line', lineno, ':', repr(line)
64 continue
65 items = prog.group(1, 2, 3, 4, 5, 6)
66 (logtime, loguser, loghost, logfile, logbytes,
67 logxxx2) = items
68## print logtime
69## print '-->', loguser
70## print '--> -->', loghost
71## print '--> --> -->', logfile
72## print '--> --> --> -->', logbytes
73## print '--> --> --> --> -->', logxxx2
74## for i in logtime, loghost, logbytes, logxxx2:
75## if '!' in i: print '???', i
76 add(bydate, logtime[-4:] + ' ' + logtime[:6], items)
77 add(bytime, logtime[7:9] + ':00-59', items)
78 direction, logfile = logfile[0], logfile[1:]
79 # The real path probably starts at the last //...
80 while 1:
81 i = string.find(logfile, '//')
82 if i < 0: break
83 logfile = logfile[i+1:]
84 add(byfile, logfile + ' ' + direction, items)
85 logdir = os.path.dirname(logfile)
86## logdir = os.path.normpath(logdir) + '/.'
87 while 1:
88 add(bydir, logdir + ' ' + direction, items)
89 dirhead = os.path.dirname(logdir)
90 if dirhead == logdir: break
91 logdir = dirhead
92 add(byhost, loghost, items)
93 add(byuser, loguser, items)
94 add(bytype, direction, items)
95 except KeyboardInterrupt:
96 print 'Interrupted at line', lineno
97 show(bytype, 'by transfer direction', maxitems)
98 show(bydir, 'by directory', maxitems)
99 show(byfile, 'by file', maxitems)
100 show(byhost, 'by host', maxitems)
101 show(byuser, 'by user', maxitems)
102 showbar(bydate, 'by date')
103 showbar(bytime, 'by time of day')
104
105def showbar(dict, title):
106 n = len(title)
107 print '='*((70-n)/2), title, '='*((71-n)/2)
108 list = []
109 keys = dict.keys()
110 keys.sort()
111 for key in keys:
112 n = len(str(key))
113 list.append((len(dict[key]), key))
114 maxkeylength = 0
115 maxcount = 0
116 for count, key in list:
117 maxkeylength = max(maxkeylength, len(key))
118 maxcount = max(maxcount, count)
119 maxbarlength = 72 - maxkeylength - 7
120 for count, key in list:
121 barlength = int(round(maxbarlength*float(count)/maxcount))
122 bar = '*'*barlength
123 print '%5d %-*s %s' % (count, maxkeylength, key, bar)
124
125def show(dict, title, maxitems):
126 if len(dict) > maxitems:
127 title = title + ' (first %d)'%maxitems
128 n = len(title)
129 print '='*((70-n)/2), title, '='*((71-n)/2)
130 list = []
131 keys = dict.keys()
132 for key in keys:
133 list.append((-len(dict[key]), key))
134 list.sort()
135 for count, key in list[:maxitems]:
136 print '%5d %s' % (-count, key)
137
138def add(dict, key, item):
139 if dict.has_key(key):
140 dict[key].append(item)
141 else:
142 dict[key] = [item]
143
144if __name__ == "__main__":
145 main()
sys/src/cmd/python/Demo/scripts/lpwatch.py+110−0
@@ -0,0 +1,110 @@
1#! /usr/bin/env python
2
3# Watch line printer queue(s).
4# Intended for BSD 4.3 lpq.
5
6import posix
7import sys
8import time
9import string
10
11DEF_PRINTER = 'psc'
12DEF_DELAY = 10
13
14def main():
15 delay = DEF_DELAY # XXX Use getopt() later
16 try:
17 thisuser = posix.environ['LOGNAME']
18 except:
19 thisuser = posix.environ['USER']
20 printers = sys.argv[1:]
21 if printers:
22 # Strip '-P' from printer names just in case
23 # the user specified it...
24 for i in range(len(printers)):
25 if printers[i][:2] == '-P':
26 printers[i] = printers[i][2:]
27 else:
28 if posix.environ.has_key('PRINTER'):
29 printers = [posix.environ['PRINTER']]
30 else:
31 printers = [DEF_PRINTER]
32 #
33 clearhome = posix.popen('clear', 'r').read()
34 #
35 while 1:
36 text = clearhome
37 for name in printers:
38 text = text + makestatus(name, thisuser) + '\n'
39 print text
40 time.sleep(delay)
41
42def makestatus(name, thisuser):
43 pipe = posix.popen('lpq -P' + name + ' 2>&1', 'r')
44 lines = []
45 users = {}
46 aheadbytes = 0
47 aheadjobs = 0
48 userseen = 0
49 totalbytes = 0
50 totaljobs = 0
51 while 1:
52 line = pipe.readline()
53 if not line: break
54 fields = string.split(line)
55 n = len(fields)
56 if len(fields) >= 6 and fields[n-1] == 'bytes':
57 rank = fields[0]
58 user = fields[1]
59 job = fields[2]
60 files = fields[3:-2]
61 bytes = eval(fields[n-2])
62 if user == thisuser:
63 userseen = 1
64 elif not userseen:
65 aheadbytes = aheadbytes + bytes
66 aheadjobs = aheadjobs + 1
67 totalbytes = totalbytes + bytes
68 totaljobs = totaljobs + 1
69 if users.has_key(user):
70 ujobs, ubytes = users[user]
71 else:
72 ujobs, ubytes = 0, 0
73 ujobs = ujobs + 1
74 ubytes = ubytes + bytes
75 users[user] = ujobs, ubytes
76 else:
77 if fields and fields[0] <> 'Rank':
78 line = string.strip(line)
79 if line == 'no entries':
80 line = name + ': idle'
81 elif line[-22:] == ' is ready and printing':
82 line = name
83 lines.append(line)
84 #
85 if totaljobs:
86 line = '%d K' % ((totalbytes+1023)/1024)
87 if totaljobs <> len(users):
88 line = line + ' (%d jobs)' % totaljobs
89 if len(users) == 1:
90 line = line + ' for %s' % (users.keys()[0],)
91 else:
92 line = line + ' for %d users' % len(users)
93 if userseen:
94 if aheadjobs == 0:
95 line = line + ' (%s first)' % thisuser
96 else:
97 line = line + ' (%d K before %s)' % (
98 (aheadbytes+1023)/1024, thisuser)
99 lines.append(line)
100 #
101 sts = pipe.close()
102 if sts:
103 lines.append('lpq exit status %r' % (sts,))
104 return string.joinfields(lines, ': ')
105
106if __name__ == "__main__":
107 try:
108 main()
109 except KeyboardInterrupt:
110 pass
sys/src/cmd/python/Demo/scripts/makedir.py+21−0
@@ -0,0 +1,21 @@
1#! /usr/bin/env python
2
3# Like mkdir, but also make intermediate directories if necessary.
4# It is not an error if the given directory already exists (as long
5# as it is a directory).
6# Errors are not treated specially -- you just get a Python exception.
7
8import sys, os
9
10def main():
11 for p in sys.argv[1:]:
12 makedirs(p)
13
14def makedirs(p):
15 if p and not os.path.isdir(p):
16 head, tail = os.path.split(p)
17 makedirs(head)
18 os.mkdir(p, 0777)
19
20if __name__ == "__main__":
21 main()
sys/src/cmd/python/Demo/scripts/markov.py+117−0
@@ -0,0 +1,117 @@
1#! /usr/bin/env python
2
3class Markov:
4 def __init__(self, histsize, choice):
5 self.histsize = histsize
6 self.choice = choice
7 self.trans = {}
8 def add(self, state, next):
9 if not self.trans.has_key(state):
10 self.trans[state] = [next]
11 else:
12 self.trans[state].append(next)
13 def put(self, seq):
14 n = self.histsize
15 add = self.add
16 add(None, seq[:0])
17 for i in range(len(seq)):
18 add(seq[max(0, i-n):i], seq[i:i+1])
19 add(seq[len(seq)-n:], None)
20 def get(self):
21 choice = self.choice
22 trans = self.trans
23 n = self.histsize
24 seq = choice(trans[None])
25 while 1:
26 subseq = seq[max(0, len(seq)-n):]
27 options = trans[subseq]
28 next = choice(options)
29 if not next: break
30 seq = seq + next
31 return seq
32
33def test():
34 import sys, string, random, getopt
35 args = sys.argv[1:]
36 try:
37 opts, args = getopt.getopt(args, '0123456789cdw')
38 except getopt.error:
39 print 'Usage: markov [-#] [-cddqw] [file] ...'
40 print 'Options:'
41 print '-#: 1-digit history size (default 2)'
42 print '-c: characters (default)'
43 print '-w: words'
44 print '-d: more debugging output'
45 print '-q: no debugging output'
46 print 'Input files (default stdin) are split in paragraphs'
47 print 'separated blank lines and each paragraph is split'
48 print 'in words by whitespace, then reconcatenated with'
49 print 'exactly one space separating words.'
50 print 'Output consists of paragraphs separated by blank'
51 print 'lines, where lines are no longer than 72 characters.'
52 histsize = 2
53 do_words = 0
54 debug = 1
55 for o, a in opts:
56 if '-0' <= o <= '-9': histsize = eval(o[1:])
57 if o == '-c': do_words = 0
58 if o == '-d': debug = debug + 1
59 if o == '-q': debug = 0
60 if o == '-w': do_words = 1
61 if not args: args = ['-']
62 m = Markov(histsize, random.choice)
63 try:
64 for filename in args:
65 if filename == '-':
66 f = sys.stdin
67 if f.isatty():
68 print 'Sorry, need stdin from file'
69 continue
70 else:
71 f = open(filename, 'r')
72 if debug: print 'processing', filename, '...'
73 text = f.read()
74 f.close()
75 paralist = string.splitfields(text, '\n\n')
76 for para in paralist:
77 if debug > 1: print 'feeding ...'
78 words = string.split(para)
79 if words:
80 if do_words: data = tuple(words)
81 else: data = string.joinfields(words, ' ')
82 m.put(data)
83 except KeyboardInterrupt:
84 print 'Interrupted -- continue with data read so far'
85 if not m.trans:
86 print 'No valid input files'
87 return
88 if debug: print 'done.'
89 if debug > 1:
90 for key in m.trans.keys():
91 if key is None or len(key) < histsize:
92 print repr(key), m.trans[key]
93 if histsize == 0: print repr(''), m.trans['']
94 print
95 while 1:
96 data = m.get()
97 if do_words: words = data
98 else: words = string.split(data)
99 n = 0
100 limit = 72
101 for w in words:
102 if n + len(w) > limit:
103 print
104 n = 0
105 print w,
106 n = n + len(w) + 1
107 print
108 print
109
110def tuple(list):
111 if len(list) == 0: return ()
112 if len(list) == 1: return (list[0],)
113 i = len(list)/2
114 return tuple(list[:i]) + tuple(list[i:])
115
116if __name__ == "__main__":
117 test()
sys/src/cmd/python/Demo/scripts/mboxconvert.py+124−0
@@ -0,0 +1,124 @@
1#! /usr/bin/env python
2
3# Convert MH directories (1 message per file) or MMDF mailboxes (4x^A
4# delimited) to unix mailbox (From ... delimited) on stdout.
5# If -f is given, files contain one message per file (e.g. MH messages)
6
7import rfc822
8import sys
9import time
10import os
11import stat
12import getopt
13import re
14
15def main():
16 dofile = mmdf
17 try:
18 opts, args = getopt.getopt(sys.argv[1:], 'f')
19 except getopt.error, msg:
20 sys.stderr.write('%s\n' % msg)
21 sys.exit(2)
22 for o, a in opts:
23 if o == '-f':
24 dofile = message
25 if not args:
26 args = ['-']
27 sts = 0
28 for arg in args:
29 if arg == '-' or arg == '':
30 sts = dofile(sys.stdin) or sts
31 elif os.path.isdir(arg):
32 sts = mh(arg) or sts
33 elif os.path.isfile(arg):
34 try:
35 f = open(arg)
36 except IOError, msg:
37 sys.stderr.write('%s: %s\n' % (arg, msg))
38 sts = 1
39 continue
40 sts = dofile(f) or sts
41 f.close()
42 else:
43 sys.stderr.write('%s: not found\n' % arg)
44 sts = 1
45 if sts:
46 sys.exit(sts)
47
48numeric = re.compile('[1-9][0-9]*')
49
50def mh(dir):
51 sts = 0
52 msgs = os.listdir(dir)
53 for msg in msgs:
54 if numeric.match(msg) != len(msg):
55 continue
56 fn = os.path.join(dir, msg)
57 try:
58 f = open(fn)
59 except IOError, msg:
60 sys.stderr.write('%s: %s\n' % (fn, msg))
61 sts = 1
62 continue
63 sts = message(f) or sts
64 return sts
65
66def mmdf(f):
67 sts = 0
68 while 1:
69 line = f.readline()
70 if not line:
71 break
72 if line == '\1\1\1\1\n':
73 sts = message(f, line) or sts
74 else:
75 sys.stderr.write(
76 'Bad line in MMFD mailbox: %r\n' % (line,))
77 return sts
78
79counter = 0 # for generating unique Message-ID headers
80
81def message(f, delimiter = ''):
82 sts = 0
83 # Parse RFC822 header
84 m = rfc822.Message(f)
85 # Write unix header line
86 fullname, email = m.getaddr('From')
87 tt = m.getdate('Date')
88 if tt:
89 t = time.mktime(tt)
90 else:
91 sys.stderr.write(
92 'Unparseable date: %r\n' % (m.getheader('Date'),))
93 t = os.fstat(f.fileno())[stat.ST_MTIME]
94 print 'From', email, time.ctime(t)
95 # Copy RFC822 header
96 for line in m.headers:
97 print line,
98 # Invent Message-ID header if none is present
99 if not m.has_key('message-id'):
100 global counter
101 counter = counter + 1
102 msgid = "<%s.%d>" % (hex(t), counter)
103 sys.stderr.write("Adding Message-ID %s (From %s)\n" %
104 (msgid, email))
105 print "Message-ID:", msgid
106 print
107 # Copy body
108 while 1:
109 line = f.readline()
110 if line == delimiter:
111 break
112 if not line:
113 sys.stderr.write('Unexpected EOF in message\n')
114 sts = 1
115 break
116 if line[:5] == 'From ':
117 line = '>' + line
118 print line,
119 # Print trailing newline
120 print
121 return sts
122
123if __name__ == "__main__":
124 main()
sys/src/cmd/python/Demo/scripts/mkrcs.py+61−0
@@ -0,0 +1,61 @@
1#! /usr/bin/env python
2
3# A rather specialized script to make sure that a symbolic link named
4# RCS exists pointing to a real RCS directory in a parallel tree
5# referenced as RCStree in an ancestor directory.
6# (I use this because I like my RCS files to reside on a physically
7# different machine).
8
9import os
10
11def main():
12 rcstree = 'RCStree'
13 rcs = 'RCS'
14 if os.path.islink(rcs):
15 print '%r is a symlink to %r' % (rcs, os.readlink(rcs))
16 return
17 if os.path.isdir(rcs):
18 print '%r is an ordinary directory' % (rcs,)
19 return
20 if os.path.exists(rcs):
21 print '%r is a file?!?!' % (rcs,)
22 return
23 #
24 p = os.getcwd()
25 up = ''
26 down = ''
27 # Invariants:
28 # (1) join(p, down) is the current directory
29 # (2) up is the same directory as p
30 # Ergo:
31 # (3) join(up, down) is the current directory
32 #print 'p =', repr(p)
33 while not os.path.isdir(os.path.join(p, rcstree)):
34 head, tail = os.path.split(p)
35 #print 'head = %r; tail = %r' % (head, tail)
36 if not tail:
37 print 'Sorry, no ancestor dir contains %r' % (rcstree,)
38 return
39 p = head
40 up = os.path.join(os.pardir, up)
41 down = os.path.join(tail, down)
42 #print 'p = %r; up = %r; down = %r' % (p, up, down)
43 there = os.path.join(up, rcstree)
44 there = os.path.join(there, down)
45 there = os.path.join(there, rcs)
46 if os.path.isdir(there):
47 print '%r already exists' % (there, )
48 else:
49 print 'making %r' % (there,)
50 makedirs(there)
51 print 'making symlink %r -> %r' % (rcs, there)
52 os.symlink(there, rcs)
53
54def makedirs(p):
55 if not os.path.isdir(p):
56 head, tail = os.path.split(p)
57 makedirs(head)
58 os.mkdir(p, 0777)
59
60if __name__ == "__main__":
61 main()
sys/src/cmd/python/Demo/scripts/morse.py+149−0
@@ -0,0 +1,149 @@
1# DAH should be three DOTs.
2# Space between DOTs and DAHs should be one DOT.
3# Space between two letters should be one DAH.
4# Space between two words should be DOT DAH DAH.
5
6import sys, math, audiodev
7
8DOT = 30
9DAH = 3 * DOT
10OCTAVE = 2 # 1 == 441 Hz, 2 == 882 Hz, ...
11
12morsetab = {
13 'A': '.-', 'a': '.-',
14 'B': '-...', 'b': '-...',
15 'C': '-.-.', 'c': '-.-.',
16 'D': '-..', 'd': '-..',
17 'E': '.', 'e': '.',
18 'F': '..-.', 'f': '..-.',
19 'G': '--.', 'g': '--.',
20 'H': '....', 'h': '....',
21 'I': '..', 'i': '..',
22 'J': '.---', 'j': '.---',
23 'K': '-.-', 'k': '-.-',
24 'L': '.-..', 'l': '.-..',
25 'M': '--', 'm': '--',
26 'N': '-.', 'n': '-.',
27 'O': '---', 'o': '---',
28 'P': '.--.', 'p': '.--.',
29 'Q': '--.-', 'q': '--.-',
30 'R': '.-.', 'r': '.-.',
31 'S': '...', 's': '...',
32 'T': '-', 't': '-',
33 'U': '..-', 'u': '..-',
34 'V': '...-', 'v': '...-',
35 'W': '.--', 'w': '.--',
36 'X': '-..-', 'x': '-..-',
37 'Y': '-.--', 'y': '-.--',
38 'Z': '--..', 'z': '--..',
39 '0': '-----',
40 '1': '.----',
41 '2': '..---',
42 '3': '...--',
43 '4': '....-',
44 '5': '.....',
45 '6': '-....',
46 '7': '--...',
47 '8': '---..',
48 '9': '----.',
49 ',': '--..--',
50 '.': '.-.-.-',
51 '?': '..--..',
52 ';': '-.-.-.',
53 ':': '---...',
54 "'": '.----.',
55 '-': '-....-',
56 '/': '-..-.',
57 '(': '-.--.-',
58 ')': '-.--.-',
59 '_': '..--.-',
60 ' ': ' '
61}
62
63# If we play at 44.1 kHz (which we do), then if we produce one sine
64# wave in 100 samples, we get a tone of 441 Hz. If we produce two
65# sine waves in these 100 samples, we get a tone of 882 Hz. 882 Hz
66# appears to be a nice one for playing morse code.
67def mkwave(octave):
68 global sinewave, nowave
69 sinewave = ''
70 for i in range(100):
71 val = int(math.sin(math.pi * float(i) * octave / 50.0) * 30000)
72 sinewave = sinewave + chr((val >> 8) & 255) + chr(val & 255)
73 nowave = '\0' * 200
74
75mkwave(OCTAVE)
76
77def main():
78 import getopt, string
79 try:
80 opts, args = getopt.getopt(sys.argv[1:], 'o:p:')
81 except getopt.error:
82 sys.stderr.write('Usage ' + sys.argv[0] +
83 ' [ -o outfile ] [ args ] ...\n')
84 sys.exit(1)
85 dev = None
86 for o, a in opts:
87 if o == '-o':
88 import aifc
89 dev = aifc.open(a, 'w')
90 dev.setframerate(44100)
91 dev.setsampwidth(2)
92 dev.setnchannels(1)
93 if o == '-p':
94 mkwave(string.atoi(a))
95 if not dev:
96 import audiodev
97 dev = audiodev.AudioDev()
98 dev.setoutrate(44100)
99 dev.setsampwidth(2)
100 dev.setnchannels(1)
101 dev.close = dev.stop
102 dev.writeframesraw = dev.writeframes
103 if args:
104 line = string.join(args)
105 else:
106 line = sys.stdin.readline()
107 while line:
108 mline = morse(line)
109 play(mline, dev)
110 if hasattr(dev, 'wait'):
111 dev.wait()
112 if not args:
113 line = sys.stdin.readline()
114 else:
115 line = ''
116 dev.close()
117
118# Convert a string to morse code with \001 between the characters in
119# the string.
120def morse(line):
121 res = ''
122 for c in line:
123 try:
124 res = res + morsetab[c] + '\001'
125 except KeyError:
126 pass
127 return res
128
129# Play a line of morse code.
130def play(line, dev):
131 for c in line:
132 if c == '.':
133 sine(dev, DOT)
134 elif c == '-':
135 sine(dev, DAH)
136 else: # space
137 pause(dev, DAH + DOT)
138 pause(dev, DOT)
139
140def sine(dev, length):
141 for i in range(length):
142 dev.writeframesraw(sinewave)
143
144def pause(dev, length):
145 for i in range(length):
146 dev.writeframesraw(nowave)
147
148if __name__ == '__main__' or sys.argv[0] == __name__:
149 main()
sys/src/cmd/python/Demo/scripts/newslist.doc+59−0
@@ -0,0 +1,59 @@
1 NEWSLIST
2 ========
3 A program to assist HTTP browsing of newsgroups
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
6WWW browsers such as NCSA Mosaic allow the user to read newsgroup
7articles by specifying the group name in a URL eg 'news:comp.answers'.
8
9To browse through many groups, though, (and there are several thousand
10of them) you really need a page or pages containing links to all the
11groups. There are some good ones out there, for example,
12
13 http://info.cern.ch/hypertext/DataSources/News/Groups/Overview.html
14
15is the standard one at CERN, but it only shows the groups available there,
16which may be rather different from those available on your machine.
17
18Newslist is a program which creates a hierarchy of pages for you based
19on the groups available from YOUR server. It is written in python - a
20splendid interpreted object-oriented language which I suggest you get
21right now from the directory /pub/python at ftp.cwi.nl, if you haven't
22already got it.
23
24You should be able to see some sample output by looking at:
25 http://pelican.cl.cam.ac.uk/newspage/root.html
26
27Descriptions of newsgroups can be added from a file with one group
28per line. eg:
29
30 alt.foo Articles about foo
31 comp.bar Programming in 'bar' and related languages
32
33A suitable list detailing most groups can be found at ftp.uu.net in
34/uunet-info/newsgroups.gz.
35
36Make sure you read the information at the beginning of the program source and
37configure the variables before running.
38
39In addition to python, you need:
40
41 An NNTP-based news feed.
42 A directory in which to put the pages.
43
44The programming is not very beautiful, but it works! It comes with no
45warranty, express or implied, but with the hope that some others may
46find it useful.
47
48Comments, improvements & suggestions welcomed.
49Quentin Stafford-Fraser
50
51 ----------------------------------------------------------------------
52 Quentin Stafford-Fraser
53 http://pelican.cl.cam.ac.uk/people/qs101/me.html
54
55 Cambridge University Computer Lab Rank Xerox Cambridge EuroPARC
56 qs101@cl.cam.ac.uk fraser@europarc.xerox.com
57 Tel: +44 223 334411 Tel: +44 223 341521
58 Fax: +44 223 334679 Fax: +44 223 341510
59 ----------------------------------------------------------------------
sys/src/cmd/python/Demo/scripts/newslist.py+366−0
@@ -0,0 +1,366 @@
1#! /usr/bin/env python
2#######################################################################
3# Newslist $Revision: 37320 $
4#
5# Syntax:
6# newslist [ -a ]
7#
8# This is a program to create a directory full of HTML pages
9# which between them contain links to all the newsgroups available
10# on your server.
11#
12# The -a option causes a complete list of all groups to be read from
13# the server rather than just the ones which have appeared since last
14# execution. This recreates the local list from scratch. Use this on
15# the first invocation of the program, and from time to time thereafter.
16# When new groups are first created they may appear on your server as
17# empty groups. By default, empty groups are ignored by the -a option.
18# However, these new groups will not be created again, and so will not
19# appear in the server's list of 'new groups' at a later date. Hence it
20# won't appear until you do a '-a' after some articles have appeared.
21#
22# I should really keep a list of ignored empty groups and re-check them
23# for articles on every run, but I haven't got around to it yet.
24#
25# This assumes an NNTP news feed.
26#
27# Feel free to copy, distribute and modify this code for
28# non-commercial use. If you make any useful modifications, let me
29# know!
30#
31# (c) Quentin Stafford-Fraser 1994
32# fraser@europarc.xerox.com qs101@cl.cam.ac.uk
33# #
34#######################################################################
35import sys,nntplib, string, marshal, time, os, posix, string
36
37#######################################################################
38# Check these variables before running! #
39
40# Top directory.
41# Filenames which don't start with / are taken as being relative to this.
42topdir='/anfs/qsbigdisc/web/html/newspage'
43
44# The name of your NNTP host
45# eg.
46# newshost = 'nntp-serv.cl.cam.ac.uk'
47# or use following to get the name from the NNTPSERVER environment
48# variable:
49# newshost = posix.environ['NNTPSERVER']
50newshost = 'nntp-serv.cl.cam.ac.uk'
51
52# The filename for a local cache of the newsgroup list
53treefile = 'grouptree'
54
55# The filename for descriptions of newsgroups
56# I found a suitable one at ftp.uu.net in /uunet-info/newgroups.gz
57# You can set this to '' if you don't wish to use one.
58descfile = 'newsgroups'
59
60# The directory in which HTML pages should be created
61# eg.
62# pagedir = '/usr/local/lib/html/newspage'
63# pagedir = 'pages'
64pagedir = topdir
65
66# The html prefix which will refer to this directory
67# eg.
68# httppref = '/newspage/',
69# or leave blank for relative links between pages: (Recommended)
70# httppref = ''
71httppref = ''
72
73# The name of the 'root' news page in this directory.
74# A .html suffix will be added.
75rootpage = 'root'
76
77# Set skipempty to 0 if you wish to see links to empty groups as well.
78# Only affects the -a option.
79skipempty = 1
80
81# pagelinkicon can contain html to put an icon after links to
82# further pages. This helps to make important links stand out.
83# Set to '' if not wanted, or '...' is quite a good one.
84pagelinkicon='... <img src="http://pelican.cl.cam.ac.uk/icons/page.xbm"> '
85
86# ---------------------------------------------------------------------
87# Less important personal preferences:
88
89# Sublistsize controls the maximum number of items the will appear as
90# an indented sub-list before the whole thing is moved onto a different
91# page. The smaller this is, the more pages you will have, but the
92# shorter each will be.
93sublistsize = 4
94
95# That should be all. #
96#######################################################################
97
98for dir in os.curdir, os.environ['HOME']:
99 rcfile = os.path.join(dir, '.newslistrc.py')
100 if os.path.exists(rcfile):
101 print rcfile
102 execfile(rcfile)
103 break
104
105from nntplib import NNTP
106from stat import *
107
108rcsrev = '$Revision: 37320 $'
109rcsrev = string.join(filter(lambda s: '$' not in s, string.split(rcsrev)))
110desc = {}
111
112# Make (possibly) relative filenames into absolute ones
113treefile = os.path.join(topdir,treefile)
114descfile = os.path.join(topdir,descfile)
115page = os.path.join(topdir,pagedir)
116
117# First the bits for creating trees ---------------------------
118
119# Addtotree creates/augments a tree from a list of group names
120def addtotree(tree, groups):
121 print 'Updating tree...'
122 for i in groups:
123 parts = string.splitfields(i,'.')
124 makeleaf(tree, parts)
125
126# Makeleaf makes a leaf and the branch leading to it if necessary
127def makeleaf(tree,path):
128 j = path[0]
129 l = len(path)
130
131 if not tree.has_key(j):
132 tree[j] = {}
133 if l == 1:
134 tree[j]['.'] = '.'
135 if l > 1:
136 makeleaf(tree[j],path[1:])
137
138# Then the bits for outputting trees as pages ----------------
139
140# Createpage creates an HTML file named <root>.html containing links
141# to those groups beginning with <root>.
142
143def createpage(root, tree, p):
144 filename = os.path.join(pagedir,root+'.html')
145 if root == rootpage:
146 detail = ''
147 else:
148 detail = ' under ' + root
149 f = open(filename,'w')
150 # f.write('Content-Type: text/html\n')
151 f.write('<TITLE>Newsgroups available' + detail + '</TITLE>\n')
152 f.write('<H1>Newsgroups available' + detail +'</H1>\n')
153 f.write('<A HREF="'+httppref+rootpage+'.html">Back to top level</A><P>\n')
154 printtree(f,tree,0,p)
155 f.write('<I>This page automatically created by \'newslist\' v. '+rcsrev+'.')
156 f.write(time.ctime(time.time()) + '</I><P>')
157 f.close()
158
159# Printtree prints the groups as a bulleted list. Groups with
160# more than <sublistsize> subgroups will be put on a separate page.
161# Other sets of subgroups are just indented.
162
163def printtree(f, tree, indent, p):
164 global desc
165 l = len(tree)
166
167 if l > sublistsize and indent>0:
168 # Create a new page and a link to it
169 f.write('<LI><B><A HREF="'+httppref+p[1:]+'.html">')
170 f.write(p[1:]+'.*')
171 f.write('</A></B>'+pagelinkicon+'\n')
172 createpage(p[1:], tree, p)
173 return
174
175 kl = tree.keys()
176
177 if l > 1:
178 kl.sort()
179 if indent > 0:
180 # Create a sub-list
181 f.write('<LI>'+p[1:]+'\n<UL>')
182 else:
183 # Create a main list
184 f.write('<UL>')
185 indent = indent + 1
186
187 for i in kl:
188 if i == '.':
189 # Output a newsgroup
190 f.write('<LI><A HREF="news:' + p[1:] + '">'+ p[1:] + '</A> ')
191 if desc.has_key(p[1:]):
192 f.write(' <I>'+desc[p[1:]]+'</I>\n')
193 else:
194 f.write('\n')
195 else:
196 # Output a hierarchy
197 printtree(f,tree[i], indent, p+'.'+i)
198
199 if l > 1:
200 f.write('\n</UL>')
201
202# Reading descriptions file ---------------------------------------
203
204# This returns an array mapping group name to its description
205
206def readdesc(descfile):
207 global desc
208
209 desc = {}
210
211 if descfile == '':
212 return
213
214 try:
215 d = open(descfile, 'r')
216 print 'Reading descriptions...'
217 except (IOError):
218 print 'Failed to open description file ' + descfile
219 return
220 l = d.readline()
221 while l != '':
222 bits = string.split(l)
223 try:
224 grp = bits[0]
225 dsc = string.join(bits[1:])
226 if len(dsc)>1:
227 desc[grp] = dsc
228 except (IndexError):
229 pass
230 l = d.readline()
231
232# Check that ouput directory exists, ------------------------------
233# and offer to create it if not
234
235def checkopdir(pagedir):
236 if not os.path.isdir(pagedir):
237 print 'Directory '+pagedir+' does not exist.'
238 print 'Shall I create it for you? (y/n)'
239 if sys.stdin.readline()[0] == 'y':
240 try:
241 os.mkdir(pagedir,0777)
242 except:
243 print 'Sorry - failed!'
244 sys.exit(1)
245 else:
246 print 'OK. Exiting.'
247 sys.exit(1)
248
249# Read and write current local tree ----------------------------------
250
251def readlocallist(treefile):
252 print 'Reading current local group list...'
253 tree = {}
254 try:
255 treetime = time.localtime(os.stat(treefile)[ST_MTIME])
256 except:
257 print '\n*** Failed to open local group cache '+treefile
258 print 'If this is the first time you have run newslist, then'
259 print 'use the -a option to create it.'
260 sys.exit(1)
261 treedate = '%02d%02d%02d' % (treetime[0] % 100 ,treetime[1], treetime[2])
262 try:
263 dump = open(treefile,'r')
264 tree = marshal.load(dump)
265 dump.close()
266 except (IOError):
267 print 'Cannot open local group list ' + treefile
268 return (tree, treedate)
269
270def writelocallist(treefile, tree):
271 try:
272 dump = open(treefile,'w')
273 groups = marshal.dump(tree,dump)
274 dump.close()
275 print 'Saved list to '+treefile+'\n'
276 except:
277 print 'Sorry - failed to write to local group cache '+treefile
278 print 'Does it (or its directory) have the correct permissions?'
279 sys.exit(1)
280
281# Return list of all groups on server -----------------------------
282
283def getallgroups(server):
284 print 'Getting list of all groups...'
285 treedate='010101'
286 info = server.list()[1]
287 groups = []
288 print 'Processing...'
289 if skipempty:
290 print '\nIgnoring following empty groups:'
291 for i in info:
292 grpname = string.split(i[0])[0]
293 if skipempty and string.atoi(i[1]) < string.atoi(i[2]):
294 print grpname+' ',
295 else:
296 groups.append(grpname)
297 print '\n'
298 if skipempty:
299 print '(End of empty groups)'
300 return groups
301
302# Return list of new groups on server -----------------------------
303
304def getnewgroups(server, treedate):
305 print 'Getting list of new groups since start of '+treedate+'...',
306 info = server.newgroups(treedate,'000001')[1]
307 print 'got %d.' % len(info)
308 print 'Processing...',
309 groups = []
310 for i in info:
311 grpname = string.split(i)[0]
312 groups.append(grpname)
313 print 'Done'
314 return groups
315
316# Now the main program --------------------------------------------
317
318def main():
319 global desc
320
321 tree={}
322
323 # Check that the output directory exists
324 checkopdir(pagedir);
325
326 try:
327 print 'Connecting to '+newshost+'...'
328 if sys.version[0] == '0':
329 s = NNTP.init(newshost)
330 else:
331 s = NNTP(newshost)
332 connected = 1
333 except (nntplib.error_temp, nntplib.error_perm), x:
334 print 'Error connecting to host:', x
335 print 'I\'ll try to use just the local list.'
336 connected = 0
337
338 # If -a is specified, read the full list of groups from server
339 if connected and len(sys.argv) > 1 and sys.argv[1] == '-a':
340
341 groups = getallgroups(s)
342
343 # Otherwise just read the local file and then add
344 # groups created since local file last modified.
345 else:
346
347 (tree, treedate) = readlocallist(treefile)
348 if connected:
349 groups = getnewgroups(s, treedate)
350
351 if connected:
352 addtotree(tree, groups)
353 writelocallist(treefile,tree)
354
355 # Read group descriptions
356 readdesc(descfile)
357
358 print 'Creating pages...'
359 createpage(rootpage, tree, '')
360 print 'Done'
361
362if __name__ == "__main__":
363 main()
364
365# That's all folks
366######################################################################
sys/src/cmd/python/Demo/scripts/pi.py+34−0
@@ -0,0 +1,34 @@
1#! /usr/bin/env python
2
3# Print digits of pi forever.
4#
5# The algorithm, using Python's 'long' integers ("bignums"), works
6# with continued fractions, and was conceived by Lambert Meertens.
7#
8# See also the ABC Programmer's Handbook, by Geurts, Meertens & Pemberton,
9# published by Prentice-Hall (UK) Ltd., 1990.
10
11import sys
12
13def main():
14 k, a, b, a1, b1 = 2L, 4L, 1L, 12L, 4L
15 while 1:
16 # Next approximation
17 p, q, k = k*k, 2L*k+1L, k+1L
18 a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1
19 # Print common digits
20 d, d1 = a/b, a1/b1
21 while d == d1:
22 output(d)
23 a, a1 = 10L*(a%b), 10L*(a1%b1)
24 d, d1 = a/b, a1/b1
25
26def output(d):
27 # Use write() to avoid spaces between the digits
28 # Use str() to avoid the 'L'
29 sys.stdout.write(str(d))
30 # Flush so the output is seen immediately
31 sys.stdout.flush()
32
33if __name__ == "__main__":
34 main()
sys/src/cmd/python/Demo/scripts/pp.py+130−0
@@ -0,0 +1,130 @@
1#! /usr/bin/env python
2
3# Emulate some Perl command line options.
4# Usage: pp [-a] [-c] [-d] [-e scriptline] [-F fieldsep] [-n] [-p] [file] ...
5# Where the options mean the following:
6# -a : together with -n or -p, splits each line into list F
7# -c : check syntax only, do not execute any code
8# -d : run the script under the debugger, pdb
9# -e scriptline : gives one line of the Python script; may be repeated
10# -F fieldsep : sets the field separator for the -a option [not in Perl]
11# -n : runs the script for each line of input
12# -p : prints the line after the script has run
13# When no script lines have been passed, the first file argument
14# contains the script. With -n or -p, the remaining arguments are
15# read as input to the script, line by line. If a file is '-'
16# or missing, standard input is read.
17
18# XXX To do:
19# - add -i extension option (change files in place)
20# - make a single loop over the files and lines (changes effect of 'break')?
21# - add an option to specify the record separator
22# - except for -n/-p, run directly from the file if at all possible
23
24import sys
25import string
26import getopt
27
28FS = ''
29SCRIPT = []
30AFLAG = 0
31CFLAG = 0
32DFLAG = 0
33NFLAG = 0
34PFLAG = 0
35
36try:
37 optlist, ARGS = getopt.getopt(sys.argv[1:], 'acde:F:np')
38except getopt.error, msg:
39 sys.stderr.write(sys.argv[0] + ': ' + msg + '\n')
40 sys.exit(2)
41
42for option, optarg in optlist:
43 if option == '-a':
44 AFLAG = 1
45 elif option == '-c':
46 CFLAG = 1
47 elif option == '-d':
48 DFLAG = 1
49 elif option == '-e':
50 for line in string.splitfields(optarg, '\n'):
51 SCRIPT.append(line)
52 elif option == '-F':
53 FS = optarg
54 elif option == '-n':
55 NFLAG = 1
56 PFLAG = 0
57 elif option == '-p':
58 NFLAG = 1
59 PFLAG = 1
60 else:
61 print option, 'not recognized???'
62
63if not ARGS: ARGS.append('-')
64
65if not SCRIPT:
66 if ARGS[0] == '-':
67 fp = sys.stdin
68 else:
69 fp = open(ARGS[0], 'r')
70 while 1:
71 line = fp.readline()
72 if not line: break
73 SCRIPT.append(line[:-1])
74 del fp
75 del ARGS[0]
76 if not ARGS: ARGS.append('-')
77
78if CFLAG:
79 prologue = ['if 0:']
80 epilogue = []
81elif NFLAG:
82 # Note that it is on purpose that AFLAG and PFLAG are
83 # tested dynamically each time through the loop
84 prologue = [ \
85 'LINECOUNT = 0', \
86 'for FILE in ARGS:', \
87 ' \tif FILE == \'-\':', \
88 ' \t \tFP = sys.stdin', \
89 ' \telse:', \
90 ' \t \tFP = open(FILE, \'r\')', \
91 ' \tLINENO = 0', \
92 ' \twhile 1:', \
93 ' \t \tLINE = FP.readline()', \
94 ' \t \tif not LINE: break', \
95 ' \t \tLINENO = LINENO + 1', \
96 ' \t \tLINECOUNT = LINECOUNT + 1', \
97 ' \t \tL = LINE[:-1]', \
98 ' \t \taflag = AFLAG', \
99 ' \t \tif aflag:', \
100 ' \t \t \tif FS: F = string.splitfields(L, FS)', \
101 ' \t \t \telse: F = string.split(L)' \
102 ]
103 epilogue = [ \
104 ' \t \tif not PFLAG: continue', \
105 ' \t \tif aflag:', \
106 ' \t \t \tif FS: print string.joinfields(F, FS)', \
107 ' \t \t \telse: print string.join(F)', \
108 ' \t \telse: print L', \
109 ]
110else:
111 prologue = ['if 1:']
112 epilogue = []
113
114# Note that we indent using tabs only, so that any indentation style
115# used in 'command' will come out right after re-indentation.
116
117program = string.joinfields(prologue, '\n') + '\n'
118for line in SCRIPT:
119 program = program + (' \t \t' + line + '\n')
120program = program + (string.joinfields(epilogue, '\n') + '\n')
121
122import tempfile
123fp = tempfile.NamedTemporaryFile()
124fp.write(program)
125fp.flush()
126if DFLAG:
127 import pdb
128 pdb.run('execfile(%r)' % (tfn,))
129else:
130 execfile(tfn)
sys/src/cmd/python/Demo/scripts/primes.py+27−0
@@ -0,0 +1,27 @@
1#! /usr/bin/env python
2
3# Print prime numbers in a given range
4
5def main():
6 import sys
7 min, max = 2, 0x7fffffff
8 if sys.argv[1:]:
9 min = int(eval(sys.argv[1]))
10 if sys.argv[2:]:
11 max = int(eval(sys.argv[2]))
12 primes(min, max)
13
14def primes(min, max):
15 if 2 >= min: print 2
16 primes = [2]
17 i = 3
18 while i <= max:
19 for p in primes:
20 if i%p == 0 or p*p > i: break
21 if i%p <> 0:
22 primes.append(i)
23 if i >= min: print i
24 i = i+2
25
26if __name__ == "__main__":
27 main()
sys/src/cmd/python/Demo/scripts/queens.py+85−0
@@ -0,0 +1,85 @@
1#! /usr/bin/env python
2
3"""N queens problem.
4
5The (well-known) problem is due to Niklaus Wirth.
6
7This solution is inspired by Dijkstra (Structured Programming). It is
8a classic recursive backtracking approach.
9
10"""
11
12N = 8 # Default; command line overrides
13
14class Queens:
15
16 def __init__(self, n=N):
17 self.n = n
18 self.reset()
19
20 def reset(self):
21 n = self.n
22 self.y = [None]*n # Where is the queen in column x
23 self.row = [0]*n # Is row[y] safe?
24 self.up = [0] * (2*n-1) # Is upward diagonal[x-y] safe?
25 self.down = [0] * (2*n-1) # Is downward diagonal[x+y] safe?
26 self.nfound = 0 # Instrumentation
27
28 def solve(self, x=0): # Recursive solver
29 for y in range(self.n):
30 if self.safe(x, y):
31 self.place(x, y)
32 if x+1 == self.n:
33 self.display()
34 else:
35 self.solve(x+1)
36 self.remove(x, y)
37
38 def safe(self, x, y):
39 return not self.row[y] and not self.up[x-y] and not self.down[x+y]
40
41 def place(self, x, y):
42 self.y[x] = y
43 self.row[y] = 1
44 self.up[x-y] = 1
45 self.down[x+y] = 1
46
47 def remove(self, x, y):
48 self.y[x] = None
49 self.row[y] = 0
50 self.up[x-y] = 0
51 self.down[x+y] = 0
52
53 silent = 0 # If set, count solutions only
54
55 def display(self):
56 self.nfound = self.nfound + 1
57 if self.silent:
58 return
59 print '+-' + '--'*self.n + '+'
60 for y in range(self.n-1, -1, -1):
61 print '|',
62 for x in range(self.n):
63 if self.y[x] == y:
64 print "Q",
65 else:
66 print ".",
67 print '|'
68 print '+-' + '--'*self.n + '+'
69
70def main():
71 import sys
72 silent = 0
73 n = N
74 if sys.argv[1:2] == ['-n']:
75 silent = 1
76 del sys.argv[1]
77 if sys.argv[1:]:
78 n = int(sys.argv[1])
79 q = Queens(n)
80 q.silent = silent
81 q.solve()
82 print "Found", q.nfound, "solutions."
83
84if __name__ == "__main__":
85 main()
sys/src/cmd/python/Demo/scripts/script.py+33−0
@@ -0,0 +1,33 @@
1#! /usr/bin/env python
2# script.py -- Make typescript of terminal session.
3# Usage:
4# -a Append to typescript.
5# -p Use Python as shell.
6# Author: Steen Lumholt.
7
8
9import os, time, sys
10import pty
11
12def read(fd):
13 data = os.read(fd, 1024)
14 file.write(data)
15 return data
16
17shell = 'sh'
18filename = 'typescript'
19mode = 'w'
20if os.environ.has_key('SHELL'):
21 shell = os.environ['SHELL']
22if '-a' in sys.argv:
23 mode = 'a'
24if '-p' in sys.argv:
25 shell = 'python'
26
27file = open(filename, mode)
28
29sys.stdout.write('Script started, file is %s\n' % filename)
30file.write('Script started on %s\n' % time.ctime(time.time()))
31pty.spawn(shell, read)
32file.write('Script done on %s\n' % time.ctime(time.time()))
33sys.stdout.write('Script done, file is %s\n' % filename)
sys/src/cmd/python/Demo/scripts/unbirthday.py+107−0
@@ -0,0 +1,107 @@
1#! /usr/bin/env python
2
3# Calculate your unbirthday count (see Alice in Wonderland).
4# This is defined as the number of days from your birth until today
5# that weren't your birthday. (The day you were born is not counted).
6# Leap years make it interesting.
7
8import sys
9import time
10import calendar
11
12def main():
13 # Note that the range checks below also check for bad types,
14 # e.g. 3.14 or (). However syntactically invalid replies
15 # will raise an exception.
16 if sys.argv[1:]:
17 year = int(sys.argv[1])
18 else:
19 year = int(raw_input('In which year were you born? '))
20 if 0<=year<100:
21 print "I'll assume that by", year,
22 year = year + 1900
23 print 'you mean', year, 'and not the early Christian era'
24 elif not (1850<=year<=2002):
25 print "It's hard to believe you were born in", year
26 return
27 #
28 if sys.argv[2:]:
29 month = int(sys.argv[2])
30 else:
31 month = int(raw_input('And in which month? (1-12) '))
32 if not (1<=month<=12):
33 print 'There is no month numbered', month
34 return
35 #
36 if sys.argv[3:]:
37 day = int(sys.argv[3])
38 else:
39 day = int(raw_input('And on what day of that month? (1-31) '))
40 if month == 2 and calendar.isleap(year):
41 maxday = 29
42 else:
43 maxday = calendar.mdays[month]
44 if not (1<=day<=maxday):
45 print 'There are no', day, 'days in that month!'
46 return
47 #
48 bdaytuple = (year, month, day)
49 bdaydate = mkdate(bdaytuple)
50 print 'You were born on', format(bdaytuple)
51 #
52 todaytuple = time.localtime()[:3]
53 todaydate = mkdate(todaytuple)
54 print 'Today is', format(todaytuple)
55 #
56 if bdaytuple > todaytuple:
57 print 'You are a time traveler. Go back to the future!'
58 return
59 #
60 if bdaytuple == todaytuple:
61 print 'You were born today. Have a nice life!'
62 return
63 #
64 days = todaydate - bdaydate
65 print 'You have lived', days, 'days'
66 #
67 age = 0
68 for y in range(year, todaytuple[0] + 1):
69 if bdaytuple < (y, month, day) <= todaytuple:
70 age = age + 1
71 #
72 print 'You are', age, 'years old'
73 #
74 if todaytuple[1:] == bdaytuple[1:]:
75 print 'Congratulations! Today is your', nth(age), 'birthday'
76 print 'Yesterday was your',
77 else:
78 print 'Today is your',
79 print nth(days - age), 'unbirthday'
80
81def format((year, month, day)):
82 return '%d %s %d' % (day, calendar.month_name[month], year)
83
84def nth(n):
85 if n == 1: return '1st'
86 if n == 2: return '2nd'
87 if n == 3: return '3rd'
88 return '%dth' % n
89
90def mkdate((year, month, day)):
91 # Januari 1st, in 0 A.D. is arbitrarily defined to be day 1,
92 # even though that day never actually existed and the calendar
93 # was different then...
94 days = year*365 # years, roughly
95 days = days + (year+3)/4 # plus leap years, roughly
96 days = days - (year+99)/100 # minus non-leap years every century
97 days = days + (year+399)/400 # plus leap years every 4 centirues
98 for i in range(1, month):
99 if i == 2 and calendar.isleap(year):
100 days = days + 29
101 else:
102 days = days + calendar.mdays[i]
103 days = days + day
104 return days
105
106if __name__ == "__main__":
107 main()
sys/src/cmd/python/Demo/scripts/update.py+92−0
@@ -0,0 +1,92 @@
1#! /usr/bin/env python
2
3# Update a bunch of files according to a script.
4# The input file contains lines of the form <filename>:<lineno>:<text>,
5# meaning that the given line of the given file is to be replaced
6# by the given text. This is useful for performing global substitutions
7# on grep output:
8
9import os
10import sys
11import re
12
13pat = '^([^: \t\n]+):([1-9][0-9]*):'
14prog = re.compile(pat)
15
16class FileObj:
17 def __init__(self, filename):
18 self.filename = filename
19 self.changed = 0
20 try:
21 self.lines = open(filename, 'r').readlines()
22 except IOError, msg:
23 print '*** Can\'t open "%s":' % filename, msg
24 self.lines = None
25 return
26 print 'diffing', self.filename
27
28 def finish(self):
29 if not self.changed:
30 print 'no changes to', self.filename
31 return
32 try:
33 os.rename(self.filename, self.filename + '~')
34 fp = open(self.filename, 'w')
35 except (os.error, IOError), msg:
36 print '*** Can\'t rewrite "%s":' % self.filename, msg
37 return
38 print 'writing', self.filename
39 for line in self.lines:
40 fp.write(line)
41 fp.close()
42 self.changed = 0
43
44 def process(self, lineno, rest):
45 if self.lines is None:
46 print '(not processed): %s:%s:%s' % (
47 self.filename, lineno, rest),
48 return
49 i = eval(lineno) - 1
50 if not 0 <= i < len(self.lines):
51 print '*** Line number out of range: %s:%s:%s' % (
52 self.filename, lineno, rest),
53 return
54 if self.lines[i] == rest:
55 print '(no change): %s:%s:%s' % (
56 self.filename, lineno, rest),
57 return
58 if not self.changed:
59 self.changed = 1
60 print '%sc%s' % (lineno, lineno)
61 print '<', self.lines[i],
62 print '---'
63 self.lines[i] = rest
64 print '>', self.lines[i],
65
66def main():
67 if sys.argv[1:]:
68 try:
69 fp = open(sys.argv[1], 'r')
70 except IOError, msg:
71 print 'Can\'t open "%s":' % sys.argv[1], msg
72 sys.exit(1)
73 else:
74 fp = sys.stdin
75 curfile = None
76 while 1:
77 line = fp.readline()
78 if not line:
79 if curfile: curfile.finish()
80 break
81 n = prog.match(line)
82 if n < 0:
83 print 'Funny line:', line,
84 continue
85 filename, lineno = prog.group(1, 2)
86 if not curfile or filename <> curfile.filename:
87 if curfile: curfile.finish()
88 curfile = FileObj(filename)
89 curfile.process(lineno, line[n:])
90
91if __name__ == "__main__":
92 main()
sys/src/cmd/python/Demo/scripts/wh.py+2−0
@@ -0,0 +1,2 @@
1# This is here so I can use 'wh' instead of 'which' in '~/bin/generic_python'
2import which
sys/src/cmd/python/Demo/sockets/README+21−0
@@ -0,0 +1,21 @@
1This directory contains some demonstrations of the socket module:
2
3broadcast.py Broadcast the time to radio.py.
4echosvr.py About the simplest TCP server possible.
5finger.py Client for the 'finger' protocol.
6ftp.py A very simple ftp client.
7gopher.py A simple gopher client.
8radio.py Receive time broadcasts from broadcast.py.
9telnet.py Client for the 'telnet' protocol.
10throughput.py Client and server to measure TCP throughput.
11unixclient.py Unix socket example, client side
12unixserver.py Unix socket example, server side
13udpecho.py Client and server for the UDP echo protocol.
14
15The following file is only relevant on SGI machines (or other systems
16that support multicast):
17
18mcast.py A Python translation of
19 /usr/people/4Dgifts/examples/network/mcast.c
20 (Note that IN.py is in ../../lib/sgi.)
21
sys/src/cmd/python/Demo/sockets/broadcast.py+15−0
@@ -0,0 +1,15 @@
1# Send UDP broadcast packets
2
3MYPORT = 50000
4
5import sys, time
6from socket import *
7
8s = socket(AF_INET, SOCK_DGRAM)
9s.bind(('', 0))
10s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
11
12while 1:
13 data = repr(time.time()) + '\n'
14 s.sendto(data, ('<broadcast>', MYPORT))
15 time.sleep(2)
sys/src/cmd/python/Demo/sockets/echosvr.py+31−0
@@ -0,0 +1,31 @@
1#! /usr/bin/env python
2
3# Python implementation of an 'echo' tcp server: echo all data it receives.
4#
5# This is the simplest possible server, servicing a single request only.
6
7import sys
8from socket import *
9
10# The standard echo port isn't very useful, it requires root permissions!
11# ECHO_PORT = 7
12ECHO_PORT = 50000 + 7
13BUFSIZE = 1024
14
15def main():
16 if len(sys.argv) > 1:
17 port = int(eval(sys.argv[1]))
18 else:
19 port = ECHO_PORT
20 s = socket(AF_INET, SOCK_STREAM)
21 s.bind(('', port))
22 s.listen(1)
23 conn, (remotehost, remoteport) = s.accept()
24 print 'connected by', remotehost, remoteport
25 while 1:
26 data = conn.recv(BUFSIZE)
27 if not data:
28 break
29 conn.send(data)
30
31main()
sys/src/cmd/python/Demo/sockets/finger.py+58−0
@@ -0,0 +1,58 @@
1#! /usr/bin/env python
2
3# Python interface to the Internet finger daemon.
4#
5# Usage: finger [options] [user][@host] ...
6#
7# If no host is given, the finger daemon on the local host is contacted.
8# Options are passed uninterpreted to the finger daemon!
9
10
11import sys, string
12from socket import *
13
14
15# Hardcode the number of the finger port here.
16# It's not likely to change soon...
17#
18FINGER_PORT = 79
19
20
21# Function to do one remote finger invocation.
22# Output goes directly to stdout (although this can be changed).
23#
24def finger(host, args):
25 s = socket(AF_INET, SOCK_STREAM)
26 s.connect((host, FINGER_PORT))
27 s.send(args + '\n')
28 while 1:
29 buf = s.recv(1024)
30 if not buf: break
31 sys.stdout.write(buf)
32 sys.stdout.flush()
33
34
35# Main function: argument parsing.
36#
37def main():
38 options = ''
39 i = 1
40 while i < len(sys.argv) and sys.argv[i][:1] == '-':
41 options = options + sys.argv[i] + ' '
42 i = i+1
43 args = sys.argv[i:]
44 if not args:
45 args = ['']
46 for arg in args:
47 if '@' in arg:
48 at = string.index(arg, '@')
49 host = arg[at+1:]
50 arg = arg[:at]
51 else:
52 host = ''
53 finger(host, options + arg)
54
55
56# Call the main function.
57#
58main()
sys/src/cmd/python/Demo/sockets/ftp.py+146−0
@@ -0,0 +1,146 @@
1# A simple FTP client.
2#
3# The information to write this program was gathered from RFC 959,
4# but this is not a complete implementation! Yet it shows how a simple
5# FTP client can be built, and you are welcome to extend it to suit
6# it to your needs...
7#
8# How it works (assuming you've read the RFC):
9#
10# User commands are passed uninterpreted to the server. However, the
11# user never needs to send a PORT command. Rather, the client opens a
12# port right away and sends the appropriate PORT command to the server.
13# When a response code 150 is received, this port is used to receive
14# the data (which is written to stdout in this version), and when the
15# data is exhausted, a new port is opened and a corresponding PORT
16# command sent. In order to avoid errors when reusing ports quickly
17# (and because there is no s.getsockname() method in Python yet) we
18# cycle through a number of ports in the 50000 range.
19
20
21import sys, posix, string
22from socket import *
23
24
25BUFSIZE = 1024
26
27# Default port numbers used by the FTP protocol.
28#
29FTP_PORT = 21
30FTP_DATA_PORT = FTP_PORT - 1
31
32# Change the data port to something not needing root permissions.
33#
34FTP_DATA_PORT = FTP_DATA_PORT + 50000
35
36
37# Main program (called at the end of this file).
38#
39def main():
40 hostname = sys.argv[1]
41 control(hostname)
42
43
44# Control process (user interface and user protocol interpreter).
45#
46def control(hostname):
47 #
48 # Create control connection
49 #
50 s = socket(AF_INET, SOCK_STREAM)
51 s.connect((hostname, FTP_PORT))
52 f = s.makefile('r') # Reading the replies is easier from a file...
53 #
54 # Control loop
55 #
56 r = None
57 while 1:
58 code = getreply(f)
59 if code in ('221', 'EOF'): break
60 if code == '150':
61 getdata(r)
62 code = getreply(f)
63 r = None
64 if not r:
65 r = newdataport(s, f)
66 cmd = getcommand()
67 if not cmd: break
68 s.send(cmd + '\r\n')
69
70
71# Create a new data port and send a PORT command to the server for it.
72# (Cycle through a number of ports to avoid problems with reusing
73# a port within a short time.)
74#
75nextport = 0
76#
77def newdataport(s, f):
78 global nextport
79 port = nextport + FTP_DATA_PORT
80 nextport = (nextport+1) % 16
81 r = socket(AF_INET, SOCK_STREAM)
82 r.bind((gethostbyname(gethostname()), port))
83 r.listen(1)
84 sendportcmd(s, f, port)
85 return r
86
87
88# Send an appropriate port command.
89#
90def sendportcmd(s, f, port):
91 hostname = gethostname()
92 hostaddr = gethostbyname(hostname)
93 hbytes = string.splitfields(hostaddr, '.')
94 pbytes = [repr(port/256), repr(port%256)]
95 bytes = hbytes + pbytes
96 cmd = 'PORT ' + string.joinfields(bytes, ',')
97 s.send(cmd + '\r\n')
98 code = getreply(f)
99
100
101# Process an ftp reply and return the 3-digit reply code (as a string).
102# The reply should be a line of text starting with a 3-digit number.
103# If the 4th char is '-', it is a multi-line reply and is
104# terminate by a line starting with the same 3-digit number.
105# Any text while receiving the reply is echoed to the file.
106#
107def getreply(f):
108 line = f.readline()
109 if not line: return 'EOF'
110 print line,
111 code = line[:3]
112 if line[3:4] == '-':
113 while 1:
114 line = f.readline()
115 if not line: break # Really an error
116 print line,
117 if line[:3] == code and line[3:4] != '-': break
118 return code
119
120
121# Get the data from the data connection.
122#
123def getdata(r):
124 print '(accepting data connection)'
125 conn, host = r.accept()
126 print '(data connection accepted)'
127 while 1:
128 data = conn.recv(BUFSIZE)
129 if not data: break
130 sys.stdout.write(data)
131 print '(end of data connection)'
132
133# Get a command from the user.
134#
135def getcommand():
136 try:
137 while 1:
138 line = raw_input('ftp.py> ')
139 if line: return line
140 except EOFError:
141 return ''
142
143
144# Call the main program.
145#
146main()
sys/src/cmd/python/Demo/sockets/gopher.py+347−0
@@ -0,0 +1,347 @@
1#! /usr/bin/env python
2
3# A simple gopher client.
4#
5# Usage: gopher [ [selector] host [port] ]
6
7import string
8import sys
9import os
10import socket
11
12# Default selector, host and port
13DEF_SELECTOR = ''
14DEF_HOST = 'gopher.micro.umn.edu'
15DEF_PORT = 70
16
17# Recognized file types
18T_TEXTFILE = '0'
19T_MENU = '1'
20T_CSO = '2'
21T_ERROR = '3'
22T_BINHEX = '4'
23T_DOS = '5'
24T_UUENCODE = '6'
25T_SEARCH = '7'
26T_TELNET = '8'
27T_BINARY = '9'
28T_REDUNDANT = '+'
29T_SOUND = 's'
30
31# Dictionary mapping types to strings
32typename = {'0': '<TEXT>', '1': '<DIR>', '2': '<CSO>', '3': '<ERROR>', \
33 '4': '<BINHEX>', '5': '<DOS>', '6': '<UUENCODE>', '7': '<SEARCH>', \
34 '8': '<TELNET>', '9': '<BINARY>', '+': '<REDUNDANT>', 's': '<SOUND>'}
35
36# Oft-used characters and strings
37CRLF = '\r\n'
38TAB = '\t'
39
40# Open a TCP connection to a given host and port
41def open_socket(host, port):
42 if not port:
43 port = DEF_PORT
44 elif type(port) == type(''):
45 port = string.atoi(port)
46 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
47 s.connect((host, port))
48 return s
49
50# Send a selector to a given host and port, return a file with the reply
51def send_request(selector, host, port):
52 s = open_socket(host, port)
53 s.send(selector + CRLF)
54 s.shutdown(1)
55 return s.makefile('r')
56
57# Get a menu in the form of a list of entries
58def get_menu(selector, host, port):
59 f = send_request(selector, host, port)
60 list = []
61 while 1:
62 line = f.readline()
63 if not line:
64 print '(Unexpected EOF from server)'
65 break
66 if line[-2:] == CRLF:
67 line = line[:-2]
68 elif line[-1:] in CRLF:
69 line = line[:-1]
70 if line == '.':
71 break
72 if not line:
73 print '(Empty line from server)'
74 continue
75 typechar = line[0]
76 parts = string.splitfields(line[1:], TAB)
77 if len(parts) < 4:
78 print '(Bad line from server: %r)' % (line,)
79 continue
80 if len(parts) > 4:
81 print '(Extra info from server: %r)' % (parts[4:],)
82 parts.insert(0, typechar)
83 list.append(parts)
84 f.close()
85 return list
86
87# Get a text file as a list of lines, with trailing CRLF stripped
88def get_textfile(selector, host, port):
89 list = []
90 get_alt_textfile(selector, host, port, list.append)
91 return list
92
93# Get a text file and pass each line to a function, with trailing CRLF stripped
94def get_alt_textfile(selector, host, port, func):
95 f = send_request(selector, host, port)
96 while 1:
97 line = f.readline()
98 if not line:
99 print '(Unexpected EOF from server)'
100 break
101 if line[-2:] == CRLF:
102 line = line[:-2]
103 elif line[-1:] in CRLF:
104 line = line[:-1]
105 if line == '.':
106 break
107 if line[:2] == '..':
108 line = line[1:]
109 func(line)
110 f.close()
111
112# Get a binary file as one solid data block
113def get_binary(selector, host, port):
114 f = send_request(selector, host, port)
115 data = f.read()
116 f.close()
117 return data
118
119# Get a binary file and pass each block to a function
120def get_alt_binary(selector, host, port, func, blocksize):
121 f = send_request(selector, host, port)
122 while 1:
123 data = f.read(blocksize)
124 if not data:
125 break
126 func(data)
127
128# A *very* simple interactive browser
129
130# Browser main command, has default arguments
131def browser(*args):
132 selector = DEF_SELECTOR
133 host = DEF_HOST
134 port = DEF_PORT
135 n = len(args)
136 if n > 0 and args[0]:
137 selector = args[0]
138 if n > 1 and args[1]:
139 host = args[1]
140 if n > 2 and args[2]:
141 port = args[2]
142 if n > 3:
143 raise RuntimeError, 'too many args'
144 try:
145 browse_menu(selector, host, port)
146 except socket.error, msg:
147 print 'Socket error:', msg
148 sys.exit(1)
149 except KeyboardInterrupt:
150 print '\n[Goodbye]'
151
152# Browse a menu
153def browse_menu(selector, host, port):
154 list = get_menu(selector, host, port)
155 while 1:
156 print '----- MENU -----'
157 print 'Selector:', repr(selector)
158 print 'Host:', host, ' Port:', port
159 print
160 for i in range(len(list)):
161 item = list[i]
162 typechar, description = item[0], item[1]
163 print string.rjust(repr(i+1), 3) + ':', description,
164 if typename.has_key(typechar):
165 print typename[typechar]
166 else:
167 print '<TYPE=' + repr(typechar) + '>'
168 print
169 while 1:
170 try:
171 str = raw_input('Choice [CR == up a level]: ')
172 except EOFError:
173 print
174 return
175 if not str:
176 return
177 try:
178 choice = string.atoi(str)
179 except string.atoi_error:
180 print 'Choice must be a number; try again:'
181 continue
182 if not 0 < choice <= len(list):
183 print 'Choice out of range; try again:'
184 continue
185 break
186 item = list[choice-1]
187 typechar = item[0]
188 [i_selector, i_host, i_port] = item[2:5]
189 if typebrowser.has_key(typechar):
190 browserfunc = typebrowser[typechar]
191 try:
192 browserfunc(i_selector, i_host, i_port)
193 except (IOError, socket.error):
194 print '***', sys.exc_type, ':', sys.exc_value
195 else:
196 print 'Unsupported object type'
197
198# Browse a text file
199def browse_textfile(selector, host, port):
200 x = None
201 try:
202 p = os.popen('${PAGER-more}', 'w')
203 x = SaveLines(p)
204 get_alt_textfile(selector, host, port, x.writeln)
205 except IOError, msg:
206 print 'IOError:', msg
207 if x:
208 x.close()
209 f = open_savefile()
210 if not f:
211 return
212 x = SaveLines(f)
213 try:
214 get_alt_textfile(selector, host, port, x.writeln)
215 print 'Done.'
216 except IOError, msg:
217 print 'IOError:', msg
218 x.close()
219
220# Browse a search index
221def browse_search(selector, host, port):
222 while 1:
223 print '----- SEARCH -----'
224 print 'Selector:', repr(selector)
225 print 'Host:', host, ' Port:', port
226 print
227 try:
228 query = raw_input('Query [CR == up a level]: ')
229 except EOFError:
230 print
231 break
232 query = string.strip(query)
233 if not query:
234 break
235 if '\t' in query:
236 print 'Sorry, queries cannot contain tabs'
237 continue
238 browse_menu(selector + TAB + query, host, port)
239
240# "Browse" telnet-based information, i.e. open a telnet session
241def browse_telnet(selector, host, port):
242 if selector:
243 print 'Log in as', repr(selector)
244 if type(port) <> type(''):
245 port = repr(port)
246 sts = os.system('set -x; exec telnet ' + host + ' ' + port)
247 if sts:
248 print 'Exit status:', sts
249
250# "Browse" a binary file, i.e. save it to a file
251def browse_binary(selector, host, port):
252 f = open_savefile()
253 if not f:
254 return
255 x = SaveWithProgress(f)
256 get_alt_binary(selector, host, port, x.write, 8*1024)
257 x.close()
258
259# "Browse" a sound file, i.e. play it or save it
260def browse_sound(selector, host, port):
261 browse_binary(selector, host, port)
262
263# Dictionary mapping types to browser functions
264typebrowser = {'0': browse_textfile, '1': browse_menu, \
265 '4': browse_binary, '5': browse_binary, '6': browse_textfile, \
266 '7': browse_search, \
267 '8': browse_telnet, '9': browse_binary, 's': browse_sound}
268
269# Class used to save lines, appending a newline to each line
270class SaveLines:
271 def __init__(self, f):
272 self.f = f
273 def writeln(self, line):
274 self.f.write(line + '\n')
275 def close(self):
276 sts = self.f.close()
277 if sts:
278 print 'Exit status:', sts
279
280# Class used to save data while showing progress
281class SaveWithProgress:
282 def __init__(self, f):
283 self.f = f
284 def write(self, data):
285 sys.stdout.write('#')
286 sys.stdout.flush()
287 self.f.write(data)
288 def close(self):
289 print
290 sts = self.f.close()
291 if sts:
292 print 'Exit status:', sts
293
294# Ask for and open a save file, or return None if not to save
295def open_savefile():
296 try:
297 savefile = raw_input( \
298 'Save as file [CR == don\'t save; |pipeline or ~user/... OK]: ')
299 except EOFError:
300 print
301 return None
302 savefile = string.strip(savefile)
303 if not savefile:
304 return None
305 if savefile[0] == '|':
306 cmd = string.strip(savefile[1:])
307 try:
308 p = os.popen(cmd, 'w')
309 except IOError, msg:
310 print repr(cmd), ':', msg
311 return None
312 print 'Piping through', repr(cmd), '...'
313 return p
314 if savefile[0] == '~':
315 savefile = os.path.expanduser(savefile)
316 try:
317 f = open(savefile, 'w')
318 except IOError, msg:
319 print repr(savefile), ':', msg
320 return None
321 print 'Saving to', repr(savefile), '...'
322 return f
323
324# Test program
325def test():
326 if sys.argv[4:]:
327 print 'usage: gopher [ [selector] host [port] ]'
328 sys.exit(2)
329 elif sys.argv[3:]:
330 browser(sys.argv[1], sys.argv[2], sys.argv[3])
331 elif sys.argv[2:]:
332 try:
333 port = string.atoi(sys.argv[2])
334 selector = ''
335 host = sys.argv[1]
336 except string.atoi_error:
337 selector = sys.argv[1]
338 host = sys.argv[2]
339 port = ''
340 browser(selector, host, port)
341 elif sys.argv[1:]:
342 browser('', sys.argv[1])
343 else:
344 browser()
345
346# Call the test program as a main program
347test()
sys/src/cmd/python/Demo/sockets/mcast.py+93−0
@@ -0,0 +1,93 @@
1# Send/receive UDP multicast packets.
2# Requires that your OS kernel supports IP multicast.
3# This is built-in on SGI, still optional for most other vendors.
4#
5# Usage:
6# mcast -s (sender)
7# mcast -b (sender, using broadcast instead multicast)
8# mcast (receivers)
9
10MYPORT = 8123
11MYGROUP = '225.0.0.250'
12
13import sys
14import time
15import struct
16from socket import *
17
18
19# Main program
20def main():
21 flags = sys.argv[1:]
22 #
23 if flags:
24 sender(flags[0])
25 else:
26 receiver()
27
28
29# Sender subroutine (only one per local area network)
30def sender(flag):
31 s = socket(AF_INET, SOCK_DGRAM)
32 if flag == '-b':
33 s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
34 mygroup = '<broadcast>'
35 else:
36 mygroup = MYGROUP
37 ttl = struct.pack('b', 1) # Time-to-live
38 s.setsockopt(IPPROTO_IP, IP_MULTICAST_TTL, ttl)
39 while 1:
40 data = repr(time.time())
41## data = data + (1400 - len(data)) * '\0'
42 s.sendto(data, (mygroup, MYPORT))
43 time.sleep(1)
44
45
46# Receiver subroutine (as many as you like)
47def receiver():
48 # Open and initialize the socket
49 s = openmcastsock(MYGROUP, MYPORT)
50 #
51 # Loop, printing any data we receive
52 while 1:
53 data, sender = s.recvfrom(1500)
54 while data[-1:] == '\0': data = data[:-1] # Strip trailing \0's
55 print sender, ':', repr(data)
56
57
58# Open a UDP socket, bind it to a port and select a multicast group
59def openmcastsock(group, port):
60 # Import modules used only here
61 import string
62 import struct
63 #
64 # Create a socket
65 s = socket(AF_INET, SOCK_DGRAM)
66 #
67 # Allow multiple copies of this program on one machine
68 # (not strictly needed)
69 s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
70 #
71 # Bind it to the port
72 s.bind(('', port))
73 #
74 # Look up multicast group address in name server
75 # (doesn't hurt if it is already in ddd.ddd.ddd.ddd format)
76 group = gethostbyname(group)
77 #
78 # Construct binary group address
79 bytes = map(int, string.split(group, "."))
80 grpaddr = 0
81 for byte in bytes: grpaddr = (grpaddr << 8) | byte
82 #
83 # Construct struct mreq from grpaddr and ifaddr
84 ifaddr = INADDR_ANY
85 mreq = struct.pack('ll', htonl(grpaddr), htonl(ifaddr))
86 #
87 # Add group membership
88 s.setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq)
89 #
90 return s
91
92
93main()
sys/src/cmd/python/Demo/sockets/radio.py+14−0
@@ -0,0 +1,14 @@
1# Receive UDP packets transmitted by a broadcasting service
2
3MYPORT = 50000
4
5import sys
6from socket import *
7
8s = socket(AF_INET, SOCK_DGRAM)
9s.bind(('', MYPORT))
10
11while 1:
12 data, wherefrom = s.recvfrom(1500, 0)
13 sys.stderr.write(repr(wherefrom) + '\n')
14 sys.stdout.write(data)
sys/src/cmd/python/Demo/sockets/rpython.py+35−0
@@ -0,0 +1,35 @@
1#! /usr/bin/env python
2
3# Remote python client.
4# Execute Python commands remotely and send output back.
5
6import sys
7import string
8from socket import *
9
10PORT = 4127
11BUFSIZE = 1024
12
13def main():
14 if len(sys.argv) < 3:
15 print "usage: rpython host command"
16 sys.exit(2)
17 host = sys.argv[1]
18 port = PORT
19 i = string.find(host, ':')
20 if i >= 0:
21 port = string.atoi(port[i+1:])
22 host = host[:i]
23 command = string.join(sys.argv[2:])
24 s = socket(AF_INET, SOCK_STREAM)
25 s.connect((host, port))
26 s.send(command)
27 s.shutdown(1)
28 reply = ''
29 while 1:
30 data = s.recv(BUFSIZE)
31 if not data: break
32 reply = reply + data
33 print reply,
34
35main()
sys/src/cmd/python/Demo/sockets/rpythond.py+52−0
@@ -0,0 +1,52 @@
1#! /usr/bin/env python
2
3# Remote python server.
4# Execute Python commands remotely and send output back.
5# WARNING: This version has a gaping security hole -- it accepts requests
6# from any host on the Internet!
7
8import sys
9from socket import *
10import StringIO
11import traceback
12
13PORT = 4127
14BUFSIZE = 1024
15
16def main():
17 if len(sys.argv) > 1:
18 port = int(eval(sys.argv[1]))
19 else:
20 port = PORT
21 s = socket(AF_INET, SOCK_STREAM)
22 s.bind(('', port))
23 s.listen(1)
24 while 1:
25 conn, (remotehost, remoteport) = s.accept()
26 print 'connected by', remotehost, remoteport
27 request = ''
28 while 1:
29 data = conn.recv(BUFSIZE)
30 if not data:
31 break
32 request = request + data
33 reply = execute(request)
34 conn.send(reply)
35 conn.close()
36
37def execute(request):
38 stdout = sys.stdout
39 stderr = sys.stderr
40 sys.stdout = sys.stderr = fakefile = StringIO.StringIO()
41 try:
42 try:
43 exec request in {}, {}
44 except:
45 print
46 traceback.print_exc(100)
47 finally:
48 sys.stderr = stderr
49 sys.stdout = stdout
50 return fakefile.getvalue()
51
52main()
sys/src/cmd/python/Demo/sockets/telnet.py+109−0
@@ -0,0 +1,109 @@
1#! /usr/bin/env python
2
3# Minimal interface to the Internet telnet protocol.
4#
5# It refuses all telnet options and does not recognize any of the other
6# telnet commands, but can still be used to connect in line-by-line mode.
7# It's also useful to play with a number of other services,
8# like time, finger, smtp and even ftp.
9#
10# Usage: telnet host [port]
11#
12# The port may be a service name or a decimal port number;
13# it defaults to 'telnet'.
14
15
16import sys, posix, time
17from socket import *
18
19BUFSIZE = 1024
20
21# Telnet protocol characters
22
23IAC = chr(255) # Interpret as command
24DONT = chr(254)
25DO = chr(253)
26WONT = chr(252)
27WILL = chr(251)
28
29def main():
30 host = sys.argv[1]
31 try:
32 hostaddr = gethostbyname(host)
33 except error:
34 sys.stderr.write(sys.argv[1] + ': bad host name\n')
35 sys.exit(2)
36 #
37 if len(sys.argv) > 2:
38 servname = sys.argv[2]
39 else:
40 servname = 'telnet'
41 #
42 if '0' <= servname[:1] <= '9':
43 port = eval(servname)
44 else:
45 try:
46 port = getservbyname(servname, 'tcp')
47 except error:
48 sys.stderr.write(servname + ': bad tcp service name\n')
49 sys.exit(2)
50 #
51 s = socket(AF_INET, SOCK_STREAM)
52 #
53 try:
54 s.connect((host, port))
55 except error, msg:
56 sys.stderr.write('connect failed: ' + repr(msg) + '\n')
57 sys.exit(1)
58 #
59 pid = posix.fork()
60 #
61 if pid == 0:
62 # child -- read stdin, write socket
63 while 1:
64 line = sys.stdin.readline()
65 s.send(line)
66 else:
67 # parent -- read socket, write stdout
68 iac = 0 # Interpret next char as command
69 opt = '' # Interpret next char as option
70 while 1:
71 data = s.recv(BUFSIZE)
72 if not data:
73 # EOF; kill child and exit
74 sys.stderr.write( '(Closed by remote host)\n')
75 posix.kill(pid, 9)
76 sys.exit(1)
77 cleandata = ''
78 for c in data:
79 if opt:
80 print ord(c)
81 s.send(opt + c)
82 opt = ''
83 elif iac:
84 iac = 0
85 if c == IAC:
86 cleandata = cleandata + c
87 elif c in (DO, DONT):
88 if c == DO: print '(DO)',
89 else: print '(DONT)',
90 opt = IAC + WONT
91 elif c in (WILL, WONT):
92 if c == WILL: print '(WILL)',
93 else: print '(WONT)',
94 opt = IAC + DONT
95 else:
96 print '(command)', ord(c)
97 elif c == IAC:
98 iac = 1
99 print '(IAC)',
100 else:
101 cleandata = cleandata + c
102 sys.stdout.write(cleandata)
103 sys.stdout.flush()
104
105
106try:
107 main()
108except KeyboardInterrupt:
109 pass
sys/src/cmd/python/Demo/sockets/throughput.py+93−0
@@ -0,0 +1,93 @@
1#! /usr/bin/env python
2
3# Test network throughput.
4#
5# Usage:
6# 1) on host_A: throughput -s [port] # start a server
7# 2) on host_B: throughput -c count host_A [port] # start a client
8#
9# The server will service multiple clients until it is killed.
10#
11# The client performs one transfer of count*BUFSIZE bytes and
12# measures the time it takes (roundtrip!).
13
14
15import sys, time
16from socket import *
17
18MY_PORT = 50000 + 42
19
20BUFSIZE = 1024
21
22
23def main():
24 if len(sys.argv) < 2:
25 usage()
26 if sys.argv[1] == '-s':
27 server()
28 elif sys.argv[1] == '-c':
29 client()
30 else:
31 usage()
32
33
34def usage():
35 sys.stdout = sys.stderr
36 print 'Usage: (on host_A) throughput -s [port]'
37 print 'and then: (on host_B) throughput -c count host_A [port]'
38 sys.exit(2)
39
40
41def server():
42 if len(sys.argv) > 2:
43 port = eval(sys.argv[2])
44 else:
45 port = MY_PORT
46 s = socket(AF_INET, SOCK_STREAM)
47 s.bind(('', port))
48 s.listen(1)
49 print 'Server ready...'
50 while 1:
51 conn, (host, remoteport) = s.accept()
52 while 1:
53 data = conn.recv(BUFSIZE)
54 if not data:
55 break
56 del data
57 conn.send('OK\n')
58 conn.close()
59 print 'Done with', host, 'port', remoteport
60
61
62def client():
63 if len(sys.argv) < 4:
64 usage()
65 count = int(eval(sys.argv[2]))
66 host = sys.argv[3]
67 if len(sys.argv) > 4:
68 port = eval(sys.argv[4])
69 else:
70 port = MY_PORT
71 testdata = 'x' * (BUFSIZE-1) + '\n'
72 t1 = time.time()
73 s = socket(AF_INET, SOCK_STREAM)
74 t2 = time.time()
75 s.connect((host, port))
76 t3 = time.time()
77 i = 0
78 while i < count:
79 i = i+1
80 s.send(testdata)
81 s.shutdown(1) # Send EOF
82 t4 = time.time()
83 data = s.recv(BUFSIZE)
84 t5 = time.time()
85 print data
86 print 'Raw timers:', t1, t2, t3, t4, t5
87 print 'Intervals:', t2-t1, t3-t2, t4-t3, t5-t4
88 print 'Total:', t5-t1
89 print 'Throughput:', round((BUFSIZE*count*0.001) / (t5-t1), 3),
90 print 'K/sec.'
91
92
93main()
sys/src/cmd/python/Demo/sockets/udpecho.py+63−0
@@ -0,0 +1,63 @@
1#! /usr/bin/env python
2
3# Client and server for udp (datagram) echo.
4#
5# Usage: udpecho -s [port] (to start a server)
6# or: udpecho -c host [port] <file (client)
7
8import sys
9from socket import *
10
11ECHO_PORT = 50000 + 7
12BUFSIZE = 1024
13
14def main():
15 if len(sys.argv) < 2:
16 usage()
17 if sys.argv[1] == '-s':
18 server()
19 elif sys.argv[1] == '-c':
20 client()
21 else:
22 usage()
23
24def usage():
25 sys.stdout = sys.stderr
26 print 'Usage: udpecho -s [port] (server)'
27 print 'or: udpecho -c host [port] <file (client)'
28 sys.exit(2)
29
30def server():
31 if len(sys.argv) > 2:
32 port = eval(sys.argv[2])
33 else:
34 port = ECHO_PORT
35 s = socket(AF_INET, SOCK_DGRAM)
36 s.bind(('', port))
37 print 'udp echo server ready'
38 while 1:
39 data, addr = s.recvfrom(BUFSIZE)
40 print 'server received %r from %r' % (data, addr)
41 s.sendto(data, addr)
42
43def client():
44 if len(sys.argv) < 3:
45 usage()
46 host = sys.argv[2]
47 if len(sys.argv) > 3:
48 port = eval(sys.argv[3])
49 else:
50 port = ECHO_PORT
51 addr = host, port
52 s = socket(AF_INET, SOCK_DGRAM)
53 s.bind(('', 0))
54 print 'udp echo client ready, reading stdin'
55 while 1:
56 line = sys.stdin.readline()
57 if not line:
58 break
59 s.sendto(line, addr)
60 data, fromaddr = s.recvfrom(BUFSIZE)
61 print 'client received %r from %r' % (data, fromaddr)
62
63main()
sys/src/cmd/python/Demo/sockets/unicast.py+14−0
@@ -0,0 +1,14 @@
1# Send UDP broadcast packets
2
3MYPORT = 50000
4
5import sys, time
6from socket import *
7
8s = socket(AF_INET, SOCK_DGRAM)
9s.bind(('', 0))
10
11while 1:
12 data = repr(time.time()) + '\n'
13 s.sendto(data, ('', MYPORT))
14 time.sleep(2)
sys/src/cmd/python/Demo/sockets/unixclient.py+12−0
@@ -0,0 +1,12 @@
1# Echo client demo using Unix sockets
2# Piet van Oostrum
3
4from socket import *
5
6FILE = 'unix-socket'
7s = socket(AF_UNIX, SOCK_STREAM)
8s.connect(FILE)
9s.send('Hello, world')
10data = s.recv(1024)
11s.close()
12print 'Received', repr(data)
sys/src/cmd/python/Demo/sockets/unixserver.py+24−0
@@ -0,0 +1,24 @@
1# Echo server demo using Unix sockets (handles one connection only)
2# Piet van Oostrum
3
4import os
5from socket import *
6
7FILE = 'unix-socket'
8s = socket(AF_UNIX, SOCK_STREAM)
9s.bind(FILE)
10
11print 'Sock name is: ['+s.getsockname()+']'
12
13# Wait for a connection
14s.listen(1)
15conn, addr = s.accept()
16
17while True:
18 data = conn.recv(1024)
19 if not data:
20 break
21 conn.send(data)
22
23conn.close()
24os.unlink(FILE)
sys/src/cmd/python/Demo/threads/Coroutine.py+159−0
@@ -0,0 +1,159 @@
1# Coroutine implementation using Python threads.
2#
3# Combines ideas from Guido's Generator module, and from the coroutine
4# features of Icon and Simula 67.
5#
6# To run a collection of functions as coroutines, you need to create
7# a Coroutine object to control them:
8# co = Coroutine()
9# and then 'create' a subsidiary object for each function in the
10# collection:
11# cof1 = co.create(f1 [, arg1, arg2, ...]) # [] means optional,
12# cof2 = co.create(f2 [, arg1, arg2, ...]) #... not list
13# cof3 = co.create(f3 [, arg1, arg2, ...])
14# etc. The functions need not be distinct; 'create'ing the same
15# function multiple times gives you independent instances of the
16# function.
17#
18# To start the coroutines running, use co.tran on one of the create'd
19# functions; e.g., co.tran(cof2). The routine that first executes
20# co.tran is called the "main coroutine". It's special in several
21# respects: it existed before you created the Coroutine object; if any of
22# the create'd coroutines exits (does a return, or suffers an unhandled
23# exception), EarlyExit error is raised in the main coroutine; and the
24# co.detach() method transfers control directly to the main coroutine
25# (you can't use co.tran() for this because the main coroutine doesn't
26# have a name ...).
27#
28# Coroutine objects support these methods:
29#
30# handle = .create(func [, arg1, arg2, ...])
31# Creates a coroutine for an invocation of func(arg1, arg2, ...),
32# and returns a handle ("name") for the coroutine so created. The
33# handle can be used as the target in a subsequent .tran().
34#
35# .tran(target, data=None)
36# Transfer control to the create'd coroutine "target", optionally
37# passing it an arbitrary piece of data. To the coroutine A that does
38# the .tran, .tran acts like an ordinary function call: another
39# coroutine B can .tran back to it later, and if it does A's .tran
40# returns the 'data' argument passed to B's tran. E.g.,
41#
42# in coroutine coA in coroutine coC in coroutine coB
43# x = co.tran(coC) co.tran(coB) co.tran(coA,12)
44# print x # 12
45#
46# The data-passing feature is taken from Icon, and greatly cuts
47# the need to use global variables for inter-coroutine communication.
48#
49# .back( data=None )
50# The same as .tran(invoker, data=None), where 'invoker' is the
51# coroutine that most recently .tran'ed control to the coroutine
52# doing the .back. This is akin to Icon's "&source".
53#
54# .detach( data=None )
55# The same as .tran(main, data=None), where 'main' is the
56# (unnameable!) coroutine that started it all. 'main' has all the
57# rights of any other coroutine: upon receiving control, it can
58# .tran to an arbitrary coroutine of its choosing, go .back to
59# the .detach'er, or .kill the whole thing.
60#
61# .kill()
62# Destroy all the coroutines, and return control to the main
63# coroutine. None of the create'ed coroutines can be resumed after a
64# .kill(). An EarlyExit exception does a .kill() automatically. It's
65# a good idea to .kill() coroutines you're done with, since the
66# current implementation consumes a thread for each coroutine that
67# may be resumed.
68
69import thread
70import sync
71
72class _CoEvent:
73 def __init__(self, func):
74 self.f = func
75 self.e = sync.event()
76
77 def __repr__(self):
78 if self.f is None:
79 return 'main coroutine'
80 else:
81 return 'coroutine for func ' + self.f.func_name
82
83 def __hash__(self):
84 return id(self)
85
86 def __cmp__(x,y):
87 return cmp(id(x), id(y))
88
89 def resume(self):
90 self.e.post()
91
92 def wait(self):
93 self.e.wait()
94 self.e.clear()
95
96Killed = 'Coroutine.Killed'
97EarlyExit = 'Coroutine.EarlyExit'
98
99class Coroutine:
100 def __init__(self):
101 self.active = self.main = _CoEvent(None)
102 self.invokedby = {self.main: None}
103 self.killed = 0
104 self.value = None
105 self.terminated_by = None
106
107 def create(self, func, *args):
108 me = _CoEvent(func)
109 self.invokedby[me] = None
110 thread.start_new_thread(self._start, (me,) + args)
111 return me
112
113 def _start(self, me, *args):
114 me.wait()
115 if not self.killed:
116 try:
117 try:
118 apply(me.f, args)
119 except Killed:
120 pass
121 finally:
122 if not self.killed:
123 self.terminated_by = me
124 self.kill()
125
126 def kill(self):
127 if self.killed:
128 raise TypeError, 'kill() called on dead coroutines'
129 self.killed = 1
130 for coroutine in self.invokedby.keys():
131 coroutine.resume()
132
133 def back(self, data=None):
134 return self.tran( self.invokedby[self.active], data )
135
136 def detach(self, data=None):
137 return self.tran( self.main, data )
138
139 def tran(self, target, data=None):
140 if not self.invokedby.has_key(target):
141 raise TypeError, '.tran target %r is not an active coroutine' % (target,)
142 if self.killed:
143 raise TypeError, '.tran target %r is killed' % (target,)
144 self.value = data
145 me = self.active
146 self.invokedby[target] = me
147 self.active = target
148 target.resume()
149
150 me.wait()
151 if self.killed:
152 if self.main is not me:
153 raise Killed
154 if self.terminated_by is not None:
155 raise EarlyExit, '%r terminated early' % (self.terminated_by,)
156
157 return self.value
158
159# end of module
sys/src/cmd/python/Demo/threads/Generator.py+84−0
@@ -0,0 +1,84 @@
1# Generator implementation using threads
2
3import thread
4
5Killed = 'Generator.Killed'
6
7class Generator:
8 # Constructor
9 def __init__(self, func, args):
10 self.getlock = thread.allocate_lock()
11 self.putlock = thread.allocate_lock()
12 self.getlock.acquire()
13 self.putlock.acquire()
14 self.func = func
15 self.args = args
16 self.done = 0
17 self.killed = 0
18 thread.start_new_thread(self._start, ())
19 # Internal routine
20 def _start(self):
21 try:
22 self.putlock.acquire()
23 if not self.killed:
24 try:
25 apply(self.func, (self,) + self.args)
26 except Killed:
27 pass
28 finally:
29 if not self.killed:
30 self.done = 1
31 self.getlock.release()
32 # Called by producer for each value; raise Killed if no more needed
33 def put(self, value):
34 if self.killed:
35 raise TypeError, 'put() called on killed generator'
36 self.value = value
37 self.getlock.release() # Resume consumer thread
38 self.putlock.acquire() # Wait for next get() call
39 if self.killed:
40 raise Killed
41 # Called by producer to get next value; raise EOFError if no more
42 def get(self):
43 if self.killed:
44 raise TypeError, 'get() called on killed generator'
45 self.putlock.release() # Resume producer thread
46 self.getlock.acquire() # Wait for value to appear
47 if self.done:
48 raise EOFError # Say there are no more values
49 return self.value
50 # Called by consumer if no more values wanted
51 def kill(self):
52 if self.killed:
53 raise TypeError, 'kill() called on killed generator'
54 self.killed = 1
55 self.putlock.release()
56 # Clone constructor
57 def clone(self):
58 return Generator(self.func, self.args)
59
60def pi(g):
61 k, a, b, a1, b1 = 2L, 4L, 1L, 12L, 4L
62 while 1:
63 # Next approximation
64 p, q, k = k*k, 2L*k+1L, k+1L
65 a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1
66 # Print common digits
67 d, d1 = a/b, a1/b1
68 while d == d1:
69 g.put(int(d))
70 a, a1 = 10L*(a%b), 10L*(a1%b1)
71 d, d1 = a/b, a1/b1
72
73def test():
74 g = Generator(pi, ())
75 g.kill()
76 g = Generator(pi, ())
77 for i in range(10): print g.get(),
78 print
79 h = g.clone()
80 g.kill()
81 while 1:
82 print h.get(),
83
84test()
sys/src/cmd/python/Demo/threads/README+13−0
@@ -0,0 +1,13 @@
1This directory contains some demonstrations of the thread module.
2
3These are mostly "proof of concept" type applications:
4
5Generator.py Generator class implemented with threads.
6find.py Parallelized "find(1)" (looks for directories).
7sync.py Condition variables primitives by Tim Peters.
8telnet.py Version of ../sockets/telnet.py using threads.
9wpi.py Version of ../scripts/pi.py using threads (needs stdwin).
10
11Coroutine.py Coroutines using threads, by Tim Peters (22 May 94)
12fcmp.py Example of above, by Tim
13squasher.py Another example of above, also by Tim
sys/src/cmd/python/Demo/threads/fcmp.py+64−0
@@ -0,0 +1,64 @@
1# Coroutine example: controlling multiple instances of a single function
2
3from Coroutine import *
4
5# fringe visits a nested list in inorder, and detaches for each non-list
6# element; raises EarlyExit after the list is exhausted
7def fringe(co, list):
8 for x in list:
9 if type(x) is type([]):
10 fringe(co, x)
11 else:
12 co.back(x)
13
14def printinorder(list):
15 co = Coroutine()
16 f = co.create(fringe, co, list)
17 try:
18 while 1:
19 print co.tran(f),
20 except EarlyExit:
21 pass
22 print
23
24printinorder([1,2,3]) # 1 2 3
25printinorder([[[[1,[2]]],3]]) # ditto
26x = [0, 1, [2, [3]], [4,5], [[[6]]] ]
27printinorder(x) # 0 1 2 3 4 5 6
28
29# fcmp lexicographically compares the fringes of two nested lists
30def fcmp(l1, l2):
31 co1 = Coroutine(); f1 = co1.create(fringe, co1, l1)
32 co2 = Coroutine(); f2 = co2.create(fringe, co2, l2)
33 while 1:
34 try:
35 v1 = co1.tran(f1)
36 except EarlyExit:
37 try:
38 v2 = co2.tran(f2)
39 except EarlyExit:
40 return 0
41 co2.kill()
42 return -1
43 try:
44 v2 = co2.tran(f2)
45 except EarlyExit:
46 co1.kill()
47 return 1
48 if v1 != v2:
49 co1.kill(); co2.kill()
50 return cmp(v1,v2)
51
52print fcmp(range(7), x) # 0; fringes are equal
53print fcmp(range(6), x) # -1; 1st list ends early
54print fcmp(x, range(6)) # 1; 2nd list ends early
55print fcmp(range(8), x) # 1; 2nd list ends early
56print fcmp(x, range(8)) # -1; 1st list ends early
57print fcmp([1,[[2],8]],
58 [[[1],2],8]) # 0
59print fcmp([1,[[3],8]],
60 [[[1],2],8]) # 1
61print fcmp([1,[[2],8]],
62 [[[1],2],9]) # -1
63
64# end of example
sys/src/cmd/python/Demo/threads/find.py+155−0
@@ -0,0 +1,155 @@
1# A parallelized "find(1)" using the thread module.
2
3# This demonstrates the use of a work queue and worker threads.
4# It really does do more stats/sec when using multiple threads,
5# although the improvement is only about 20-30 percent.
6# (That was 8 years ago. In 2002, on Linux, I can't measure
7# a speedup. :-( )
8
9# I'm too lazy to write a command line parser for the full find(1)
10# command line syntax, so the predicate it searches for is wired-in,
11# see function selector() below. (It currently searches for files with
12# world write permission.)
13
14# Usage: parfind.py [-w nworkers] [directory] ...
15# Default nworkers is 4
16
17
18import sys
19import getopt
20import string
21import time
22import os
23from stat import *
24import thread
25
26
27# Work queue class. Usage:
28# wq = WorkQ()
29# wq.addwork(func, (arg1, arg2, ...)) # one or more calls
30# wq.run(nworkers)
31# The work is done when wq.run() completes.
32# The function calls executed by the workers may add more work.
33# Don't use keyboard interrupts!
34
35class WorkQ:
36
37 # Invariants:
38
39 # - busy and work are only modified when mutex is locked
40 # - len(work) is the number of jobs ready to be taken
41 # - busy is the number of jobs being done
42 # - todo is locked iff there is no work and somebody is busy
43
44 def __init__(self):
45 self.mutex = thread.allocate()
46 self.todo = thread.allocate()
47 self.todo.acquire()
48 self.work = []
49 self.busy = 0
50
51 def addwork(self, func, args):
52 job = (func, args)
53 self.mutex.acquire()
54 self.work.append(job)
55 self.mutex.release()
56 if len(self.work) == 1:
57 self.todo.release()
58
59 def _getwork(self):
60 self.todo.acquire()
61 self.mutex.acquire()
62 if self.busy == 0 and len(self.work) == 0:
63 self.mutex.release()
64 self.todo.release()
65 return None
66 job = self.work[0]
67 del self.work[0]
68 self.busy = self.busy + 1
69 self.mutex.release()
70 if len(self.work) > 0:
71 self.todo.release()
72 return job
73
74 def _donework(self):
75 self.mutex.acquire()
76 self.busy = self.busy - 1
77 if self.busy == 0 and len(self.work) == 0:
78 self.todo.release()
79 self.mutex.release()
80
81 def _worker(self):
82 time.sleep(0.00001) # Let other threads run
83 while 1:
84 job = self._getwork()
85 if not job:
86 break
87 func, args = job
88 apply(func, args)
89 self._donework()
90
91 def run(self, nworkers):
92 if not self.work:
93 return # Nothing to do
94 for i in range(nworkers-1):
95 thread.start_new(self._worker, ())
96 self._worker()
97 self.todo.acquire()
98
99
100# Main program
101
102def main():
103 nworkers = 4
104 opts, args = getopt.getopt(sys.argv[1:], '-w:')
105 for opt, arg in opts:
106 if opt == '-w':
107 nworkers = string.atoi(arg)
108 if not args:
109 args = [os.curdir]
110
111 wq = WorkQ()
112 for dir in args:
113 wq.addwork(find, (dir, selector, wq))
114
115 t1 = time.time()
116 wq.run(nworkers)
117 t2 = time.time()
118
119 sys.stderr.write('Total time %r sec.\n' % (t2-t1))
120
121
122# The predicate -- defines what files we look for.
123# Feel free to change this to suit your purpose
124
125def selector(dir, name, fullname, stat):
126 # Look for world writable files that are not symlinks
127 return (stat[ST_MODE] & 0002) != 0 and not S_ISLNK(stat[ST_MODE])
128
129
130# The find procedure -- calls wq.addwork() for subdirectories
131
132def find(dir, pred, wq):
133 try:
134 names = os.listdir(dir)
135 except os.error, msg:
136 print repr(dir), ':', msg
137 return
138 for name in names:
139 if name not in (os.curdir, os.pardir):
140 fullname = os.path.join(dir, name)
141 try:
142 stat = os.lstat(fullname)
143 except os.error, msg:
144 print repr(fullname), ':', msg
145 continue
146 if pred(dir, name, fullname, stat):
147 print fullname
148 if S_ISDIR(stat[ST_MODE]):
149 if not os.path.ismount(fullname):
150 wq.addwork(find, (fullname, pred, wq))
151
152
153# Call the main program
154
155main()
sys/src/cmd/python/Demo/threads/squasher.py+105−0
@@ -0,0 +1,105 @@
1# Coroutine example: general coroutine transfers
2#
3# The program is a variation of a Simula 67 program due to Dahl & Hoare,
4# (Dahl/Dijkstra/Hoare, Structured Programming; Academic Press, 1972)
5# who in turn credit the original example to Conway.
6#
7# We have a number of input lines, terminated by a 0 byte. The problem
8# is to squash them together into output lines containing 72 characters
9# each. A semicolon must be added between input lines. Runs of blanks
10# and tabs in input lines must be squashed into single blanks.
11# Occurrences of "**" in input lines must be replaced by "^".
12#
13# Here's a test case:
14
15test = """\
16 d = sqrt(b**2 - 4*a*c)
17twoa = 2*a
18 L = -b/twoa
19 R = d/twoa
20 A1 = L + R
21 A2 = L - R\0
22"""
23
24# The program should print:
25
26# d = sqrt(b^2 - 4*a*c);twoa = 2*a; L = -b/twoa; R = d/twoa; A1 = L + R;
27#A2 = L - R
28#done
29
30# getline: delivers the next input line to its invoker
31# disassembler: grabs input lines from getline, and delivers them one
32# character at a time to squasher, also inserting a semicolon into
33# the stream between lines
34# squasher: grabs characters from disassembler and passes them on to
35# assembler, first replacing "**" with "^" and squashing runs of
36# whitespace
37# assembler: grabs characters from squasher and packs them into lines
38# with 72 character each, delivering each such line to putline;
39# when it sees a null byte, passes the last line to putline and
40# then kills all the coroutines
41# putline: grabs lines from assembler, and just prints them
42
43from Coroutine import *
44
45def getline(text):
46 for line in string.splitfields(text, '\n'):
47 co.tran(codisassembler, line)
48
49def disassembler():
50 while 1:
51 card = co.tran(cogetline)
52 for i in range(len(card)):
53 co.tran(cosquasher, card[i])
54 co.tran(cosquasher, ';')
55
56def squasher():
57 while 1:
58 ch = co.tran(codisassembler)
59 if ch == '*':
60 ch2 = co.tran(codisassembler)
61 if ch2 == '*':
62 ch = '^'
63 else:
64 co.tran(coassembler, ch)
65 ch = ch2
66 if ch in ' \t':
67 while 1:
68 ch2 = co.tran(codisassembler)
69 if ch2 not in ' \t':
70 break
71 co.tran(coassembler, ' ')
72 ch = ch2
73 co.tran(coassembler, ch)
74
75def assembler():
76 line = ''
77 while 1:
78 ch = co.tran(cosquasher)
79 if ch == '\0':
80 break
81 if len(line) == 72:
82 co.tran(coputline, line)
83 line = ''
84 line = line + ch
85 line = line + ' ' * (72 - len(line))
86 co.tran(coputline, line)
87 co.kill()
88
89def putline():
90 while 1:
91 line = co.tran(coassembler)
92 print line
93
94import string
95co = Coroutine()
96cogetline = co.create(getline, test)
97coputline = co.create(putline)
98coassembler = co.create(assembler)
99codisassembler = co.create(disassembler)
100cosquasher = co.create(squasher)
101
102co.tran(coputline)
103print 'done'
104
105# end of example
sys/src/cmd/python/Demo/threads/sync.py+603−0
@@ -0,0 +1,603 @@
1# Defines classes that provide synchronization objects. Note that use of
2# this module requires that your Python support threads.
3#
4# condition(lock=None) # a POSIX-like condition-variable object
5# barrier(n) # an n-thread barrier
6# event() # an event object
7# semaphore(n=1) # a semaphore object, with initial count n
8# mrsw() # a multiple-reader single-writer lock
9#
10# CONDITIONS
11#
12# A condition object is created via
13# import this_module
14# your_condition_object = this_module.condition(lock=None)
15#
16# As explained below, a condition object has a lock associated with it,
17# used in the protocol to protect condition data. You can specify a
18# lock to use in the constructor, else the constructor will allocate
19# an anonymous lock for you. Specifying a lock explicitly can be useful
20# when more than one condition keys off the same set of shared data.
21#
22# Methods:
23# .acquire()
24# acquire the lock associated with the condition
25# .release()
26# release the lock associated with the condition
27# .wait()
28# block the thread until such time as some other thread does a
29# .signal or .broadcast on the same condition, and release the
30# lock associated with the condition. The lock associated with
31# the condition MUST be in the acquired state at the time
32# .wait is invoked.
33# .signal()
34# wake up exactly one thread (if any) that previously did a .wait
35# on the condition; that thread will awaken with the lock associated
36# with the condition in the acquired state. If no threads are
37# .wait'ing, this is a nop. If more than one thread is .wait'ing on
38# the condition, any of them may be awakened.
39# .broadcast()
40# wake up all threads (if any) that are .wait'ing on the condition;
41# the threads are woken up serially, each with the lock in the
42# acquired state, so should .release() as soon as possible. If no
43# threads are .wait'ing, this is a nop.
44#
45# Note that if a thread does a .wait *while* a signal/broadcast is
46# in progress, it's guaranteeed to block until a subsequent
47# signal/broadcast.
48#
49# Secret feature: `broadcast' actually takes an integer argument,
50# and will wake up exactly that many waiting threads (or the total
51# number waiting, if that's less). Use of this is dubious, though,
52# and probably won't be supported if this form of condition is
53# reimplemented in C.
54#
55# DIFFERENCES FROM POSIX
56#
57# + A separate mutex is not needed to guard condition data. Instead, a
58# condition object can (must) be .acquire'ed and .release'ed directly.
59# This eliminates a common error in using POSIX conditions.
60#
61# + Because of implementation difficulties, a POSIX `signal' wakes up
62# _at least_ one .wait'ing thread. Race conditions make it difficult
63# to stop that. This implementation guarantees to wake up only one,
64# but you probably shouldn't rely on that.
65#
66# PROTOCOL
67#
68# Condition objects are used to block threads until "some condition" is
69# true. E.g., a thread may wish to wait until a producer pumps out data
70# for it to consume, or a server may wish to wait until someone requests
71# its services, or perhaps a whole bunch of threads want to wait until a
72# preceding pass over the data is complete. Early models for conditions
73# relied on some other thread figuring out when a blocked thread's
74# condition was true, and made the other thread responsible both for
75# waking up the blocked thread and guaranteeing that it woke up with all
76# data in a correct state. This proved to be very delicate in practice,
77# and gave conditions a bad name in some circles.
78#
79# The POSIX model addresses these problems by making a thread responsible
80# for ensuring that its own state is correct when it wakes, and relies
81# on a rigid protocol to make this easy; so long as you stick to the
82# protocol, POSIX conditions are easy to "get right":
83#
84# A) The thread that's waiting for some arbitrarily-complex condition
85# (ACC) to become true does:
86#
87# condition.acquire()
88# while not (code to evaluate the ACC):
89# condition.wait()
90# # That blocks the thread, *and* releases the lock. When a
91# # condition.signal() happens, it will wake up some thread that
92# # did a .wait, *and* acquire the lock again before .wait
93# # returns.
94# #
95# # Because the lock is acquired at this point, the state used
96# # in evaluating the ACC is frozen, so it's safe to go back &
97# # reevaluate the ACC.
98#
99# # At this point, ACC is true, and the thread has the condition
100# # locked.
101# # So code here can safely muck with the shared state that
102# # went into evaluating the ACC -- if it wants to.
103# # When done mucking with the shared state, do
104# condition.release()
105#
106# B) Threads that are mucking with shared state that may affect the
107# ACC do:
108#
109# condition.acquire()
110# # muck with shared state
111# condition.release()
112# if it's possible that ACC is true now:
113# condition.signal() # or .broadcast()
114#
115# Note: You may prefer to put the "if" clause before the release().
116# That's fine, but do note that anyone waiting on the signal will
117# stay blocked until the release() is done (since acquiring the
118# condition is part of what .wait() does before it returns).
119#
120# TRICK OF THE TRADE
121#
122# With simpler forms of conditions, it can be impossible to know when
123# a thread that's supposed to do a .wait has actually done it. But
124# because this form of condition releases a lock as _part_ of doing a
125# wait, the state of that lock can be used to guarantee it.
126#
127# E.g., suppose thread A spawns thread B and later wants to wait for B to
128# complete:
129#
130# In A: In B:
131#
132# B_done = condition() ... do work ...
133# B_done.acquire() B_done.acquire(); B_done.release()
134# spawn B B_done.signal()
135# ... some time later ... ... and B exits ...
136# B_done.wait()
137#
138# Because B_done was in the acquire'd state at the time B was spawned,
139# B's attempt to acquire B_done can't succeed until A has done its
140# B_done.wait() (which releases B_done). So B's B_done.signal() is
141# guaranteed to be seen by the .wait(). Without the lock trick, B
142# may signal before A .waits, and then A would wait forever.
143#
144# BARRIERS
145#
146# A barrier object is created via
147# import this_module
148# your_barrier = this_module.barrier(num_threads)
149#
150# Methods:
151# .enter()
152# the thread blocks until num_threads threads in all have done
153# .enter(). Then the num_threads threads that .enter'ed resume,
154# and the barrier resets to capture the next num_threads threads
155# that .enter it.
156#
157# EVENTS
158#
159# An event object is created via
160# import this_module
161# your_event = this_module.event()
162#
163# An event has two states, `posted' and `cleared'. An event is
164# created in the cleared state.
165#
166# Methods:
167#
168# .post()
169# Put the event in the posted state, and resume all threads
170# .wait'ing on the event (if any).
171#
172# .clear()
173# Put the event in the cleared state.
174#
175# .is_posted()
176# Returns 0 if the event is in the cleared state, or 1 if the event
177# is in the posted state.
178#
179# .wait()
180# If the event is in the posted state, returns immediately.
181# If the event is in the cleared state, blocks the calling thread
182# until the event is .post'ed by another thread.
183#
184# Note that an event, once posted, remains posted until explicitly
185# cleared. Relative to conditions, this is both the strength & weakness
186# of events. It's a strength because the .post'ing thread doesn't have to
187# worry about whether the threads it's trying to communicate with have
188# already done a .wait (a condition .signal is seen only by threads that
189# do a .wait _prior_ to the .signal; a .signal does not persist). But
190# it's a weakness because .clear'ing an event is error-prone: it's easy
191# to mistakenly .clear an event before all the threads you intended to
192# see the event get around to .wait'ing on it. But so long as you don't
193# need to .clear an event, events are easy to use safely.
194#
195# SEMAPHORES
196#
197# A semaphore object is created via
198# import this_module
199# your_semaphore = this_module.semaphore(count=1)
200#
201# A semaphore has an integer count associated with it. The initial value
202# of the count is specified by the optional argument (which defaults to
203# 1) passed to the semaphore constructor.
204#
205# Methods:
206#
207# .p()
208# If the semaphore's count is greater than 0, decrements the count
209# by 1 and returns.
210# Else if the semaphore's count is 0, blocks the calling thread
211# until a subsequent .v() increases the count. When that happens,
212# the count will be decremented by 1 and the calling thread resumed.
213#
214# .v()
215# Increments the semaphore's count by 1, and wakes up a thread (if
216# any) blocked by a .p(). It's an (detected) error for a .v() to
217# increase the semaphore's count to a value larger than the initial
218# count.
219#
220# MULTIPLE-READER SINGLE-WRITER LOCKS
221#
222# A mrsw lock is created via
223# import this_module
224# your_mrsw_lock = this_module.mrsw()
225#
226# This kind of lock is often useful with complex shared data structures.
227# The object lets any number of "readers" proceed, so long as no thread
228# wishes to "write". When a (one or more) thread declares its intention
229# to "write" (e.g., to update a shared structure), all current readers
230# are allowed to finish, and then a writer gets exclusive access; all
231# other readers & writers are blocked until the current writer completes.
232# Finally, if some thread is waiting to write and another is waiting to
233# read, the writer takes precedence.
234#
235# Methods:
236#
237# .read_in()
238# If no thread is writing or waiting to write, returns immediately.
239# Else blocks until no thread is writing or waiting to write. So
240# long as some thread has completed a .read_in but not a .read_out,
241# writers are blocked.
242#
243# .read_out()
244# Use sometime after a .read_in to declare that the thread is done
245# reading. When all threads complete reading, a writer can proceed.
246#
247# .write_in()
248# If no thread is writing (has completed a .write_in, but hasn't yet
249# done a .write_out) or reading (similarly), returns immediately.
250# Else blocks the calling thread, and threads waiting to read, until
251# the current writer completes writing or all the current readers
252# complete reading; if then more than one thread is waiting to
253# write, one of them is allowed to proceed, but which one is not
254# specified.
255#
256# .write_out()
257# Use sometime after a .write_in to declare that the thread is done
258# writing. Then if some other thread is waiting to write, it's
259# allowed to proceed. Else all threads (if any) waiting to read are
260# allowed to proceed.
261#
262# .write_to_read()
263# Use instead of a .write_in to declare that the thread is done
264# writing but wants to continue reading without other writers
265# intervening. If there are other threads waiting to write, they
266# are allowed to proceed only if the current thread calls
267# .read_out; threads waiting to read are only allowed to proceed
268# if there are are no threads waiting to write. (This is a
269# weakness of the interface!)
270
271import thread
272
273class condition:
274 def __init__(self, lock=None):
275 # the lock actually used by .acquire() and .release()
276 if lock is None:
277 self.mutex = thread.allocate_lock()
278 else:
279 if hasattr(lock, 'acquire') and \
280 hasattr(lock, 'release'):
281 self.mutex = lock
282 else:
283 raise TypeError, 'condition constructor requires ' \
284 'a lock argument'
285
286 # lock used to block threads until a signal
287 self.checkout = thread.allocate_lock()
288 self.checkout.acquire()
289
290 # internal critical-section lock, & the data it protects
291 self.idlock = thread.allocate_lock()
292 self.id = 0
293 self.waiting = 0 # num waiters subject to current release
294 self.pending = 0 # num waiters awaiting next signal
295 self.torelease = 0 # num waiters to release
296 self.releasing = 0 # 1 iff release is in progress
297
298 def acquire(self):
299 self.mutex.acquire()
300
301 def release(self):
302 self.mutex.release()
303
304 def wait(self):
305 mutex, checkout, idlock = self.mutex, self.checkout, self.idlock
306 if not mutex.locked():
307 raise ValueError, \
308 "condition must be .acquire'd when .wait() invoked"
309
310 idlock.acquire()
311 myid = self.id
312 self.pending = self.pending + 1
313 idlock.release()
314
315 mutex.release()
316
317 while 1:
318 checkout.acquire(); idlock.acquire()
319 if myid < self.id:
320 break
321 checkout.release(); idlock.release()
322
323 self.waiting = self.waiting - 1
324 self.torelease = self.torelease - 1
325 if self.torelease:
326 checkout.release()
327 else:
328 self.releasing = 0
329 if self.waiting == self.pending == 0:
330 self.id = 0
331 idlock.release()
332 mutex.acquire()
333
334 def signal(self):
335 self.broadcast(1)
336
337 def broadcast(self, num = -1):
338 if num < -1:
339 raise ValueError, '.broadcast called with num %r' % (num,)
340 if num == 0:
341 return
342 self.idlock.acquire()
343 if self.pending:
344 self.waiting = self.waiting + self.pending
345 self.pending = 0
346 self.id = self.id + 1
347 if num == -1:
348 self.torelease = self.waiting
349 else:
350 self.torelease = min( self.waiting,
351 self.torelease + num )
352 if self.torelease and not self.releasing:
353 self.releasing = 1
354 self.checkout.release()
355 self.idlock.release()
356
357class barrier:
358 def __init__(self, n):
359 self.n = n
360 self.togo = n
361 self.full = condition()
362
363 def enter(self):
364 full = self.full
365 full.acquire()
366 self.togo = self.togo - 1
367 if self.togo:
368 full.wait()
369 else:
370 self.togo = self.n
371 full.broadcast()
372 full.release()
373
374class event:
375 def __init__(self):
376 self.state = 0
377 self.posted = condition()
378
379 def post(self):
380 self.posted.acquire()
381 self.state = 1
382 self.posted.broadcast()
383 self.posted.release()
384
385 def clear(self):
386 self.posted.acquire()
387 self.state = 0
388 self.posted.release()
389
390 def is_posted(self):
391 self.posted.acquire()
392 answer = self.state
393 self.posted.release()
394 return answer
395
396 def wait(self):
397 self.posted.acquire()
398 if not self.state:
399 self.posted.wait()
400 self.posted.release()
401
402class semaphore:
403 def __init__(self, count=1):
404 if count <= 0:
405 raise ValueError, 'semaphore count %d; must be >= 1' % count
406 self.count = count
407 self.maxcount = count
408 self.nonzero = condition()
409
410 def p(self):
411 self.nonzero.acquire()
412 while self.count == 0:
413 self.nonzero.wait()
414 self.count = self.count - 1
415 self.nonzero.release()
416
417 def v(self):
418 self.nonzero.acquire()
419 if self.count == self.maxcount:
420 raise ValueError, '.v() tried to raise semaphore count above ' \
421 'initial value %r' % self.maxcount
422 self.count = self.count + 1
423 self.nonzero.signal()
424 self.nonzero.release()
425
426class mrsw:
427 def __init__(self):
428 # critical-section lock & the data it protects
429 self.rwOK = thread.allocate_lock()
430 self.nr = 0 # number readers actively reading (not just waiting)
431 self.nw = 0 # number writers either waiting to write or writing
432 self.writing = 0 # 1 iff some thread is writing
433
434 # conditions
435 self.readOK = condition(self.rwOK) # OK to unblock readers
436 self.writeOK = condition(self.rwOK) # OK to unblock writers
437
438 def read_in(self):
439 self.rwOK.acquire()
440 while self.nw:
441 self.readOK.wait()
442 self.nr = self.nr + 1
443 self.rwOK.release()
444
445 def read_out(self):
446 self.rwOK.acquire()
447 if self.nr <= 0:
448 raise ValueError, \
449 '.read_out() invoked without an active reader'
450 self.nr = self.nr - 1
451 if self.nr == 0:
452 self.writeOK.signal()
453 self.rwOK.release()
454
455 def write_in(self):
456 self.rwOK.acquire()
457 self.nw = self.nw + 1
458 while self.writing or self.nr:
459 self.writeOK.wait()
460 self.writing = 1
461 self.rwOK.release()
462
463 def write_out(self):
464 self.rwOK.acquire()
465 if not self.writing:
466 raise ValueError, \
467 '.write_out() invoked without an active writer'
468 self.writing = 0
469 self.nw = self.nw - 1
470 if self.nw:
471 self.writeOK.signal()
472 else:
473 self.readOK.broadcast()
474 self.rwOK.release()
475
476 def write_to_read(self):
477 self.rwOK.acquire()
478 if not self.writing:
479 raise ValueError, \
480 '.write_to_read() invoked without an active writer'
481 self.writing = 0
482 self.nw = self.nw - 1
483 self.nr = self.nr + 1
484 if not self.nw:
485 self.readOK.broadcast()
486 self.rwOK.release()
487
488# The rest of the file is a test case, that runs a number of parallelized
489# quicksorts in parallel. If it works, you'll get about 600 lines of
490# tracing output, with a line like
491# test passed! 209 threads created in all
492# as the last line. The content and order of preceding lines will
493# vary across runs.
494
495def _new_thread(func, *args):
496 global TID
497 tid.acquire(); id = TID = TID+1; tid.release()
498 io.acquire(); alive.append(id); \
499 print 'starting thread', id, '--', len(alive), 'alive'; \
500 io.release()
501 thread.start_new_thread( func, (id,) + args )
502
503def _qsort(tid, a, l, r, finished):
504 # sort a[l:r]; post finished when done
505 io.acquire(); print 'thread', tid, 'qsort', l, r; io.release()
506 if r-l > 1:
507 pivot = a[l]
508 j = l+1 # make a[l:j] <= pivot, and a[j:r] > pivot
509 for i in range(j, r):
510 if a[i] <= pivot:
511 a[j], a[i] = a[i], a[j]
512 j = j + 1
513 a[l], a[j-1] = a[j-1], pivot
514
515 l_subarray_sorted = event()
516 r_subarray_sorted = event()
517 _new_thread(_qsort, a, l, j-1, l_subarray_sorted)
518 _new_thread(_qsort, a, j, r, r_subarray_sorted)
519 l_subarray_sorted.wait()
520 r_subarray_sorted.wait()
521
522 io.acquire(); print 'thread', tid, 'qsort done'; \
523 alive.remove(tid); io.release()
524 finished.post()
525
526def _randarray(tid, a, finished):
527 io.acquire(); print 'thread', tid, 'randomizing array'; \
528 io.release()
529 for i in range(1, len(a)):
530 wh.acquire(); j = randint(0,i); wh.release()
531 a[i], a[j] = a[j], a[i]
532 io.acquire(); print 'thread', tid, 'randomizing done'; \
533 alive.remove(tid); io.release()
534 finished.post()
535
536def _check_sort(a):
537 if a != range(len(a)):
538 raise ValueError, ('a not sorted', a)
539
540def _run_one_sort(tid, a, bar, done):
541 # randomize a, and quicksort it
542 # for variety, all the threads running this enter a barrier
543 # at the end, and post `done' after the barrier exits
544 io.acquire(); print 'thread', tid, 'randomizing', a; \
545 io.release()
546 finished = event()
547 _new_thread(_randarray, a, finished)
548 finished.wait()
549
550 io.acquire(); print 'thread', tid, 'sorting', a; io.release()
551 finished.clear()
552 _new_thread(_qsort, a, 0, len(a), finished)
553 finished.wait()
554 _check_sort(a)
555
556 io.acquire(); print 'thread', tid, 'entering barrier'; \
557 io.release()
558 bar.enter()
559 io.acquire(); print 'thread', tid, 'leaving barrier'; \
560 io.release()
561 io.acquire(); alive.remove(tid); io.release()
562 bar.enter() # make sure they've all removed themselves from alive
563 ## before 'done' is posted
564 bar.enter() # just to be cruel
565 done.post()
566
567def test():
568 global TID, tid, io, wh, randint, alive
569 import random
570 randint = random.randint
571
572 TID = 0 # thread ID (1, 2, ...)
573 tid = thread.allocate_lock() # for changing TID
574 io = thread.allocate_lock() # for printing, and 'alive'
575 wh = thread.allocate_lock() # for calls to random
576 alive = [] # IDs of active threads
577
578 NSORTS = 5
579 arrays = []
580 for i in range(NSORTS):
581 arrays.append( range( (i+1)*10 ) )
582
583 bar = barrier(NSORTS)
584 finished = event()
585 for i in range(NSORTS):
586 _new_thread(_run_one_sort, arrays[i], bar, finished)
587 finished.wait()
588
589 print 'all threads done, and checking results ...'
590 if alive:
591 raise ValueError, ('threads still alive at end', alive)
592 for i in range(NSORTS):
593 a = arrays[i]
594 if len(a) != (i+1)*10:
595 raise ValueError, ('length of array', i, 'screwed up')
596 _check_sort(a)
597
598 print 'test passed!', TID, 'threads created in all'
599
600if __name__ == '__main__':
601 test()
602
603# end of module
sys/src/cmd/python/Demo/threads/telnet.py+114−0
@@ -0,0 +1,114 @@
1# Minimal interface to the Internet telnet protocol.
2#
3# *** modified to use threads ***
4#
5# It refuses all telnet options and does not recognize any of the other
6# telnet commands, but can still be used to connect in line-by-line mode.
7# It's also useful to play with a number of other services,
8# like time, finger, smtp and even ftp.
9#
10# Usage: telnet host [port]
11#
12# The port may be a service name or a decimal port number;
13# it defaults to 'telnet'.
14
15
16import sys, os, time
17from socket import *
18import thread
19
20BUFSIZE = 8*1024
21
22# Telnet protocol characters
23
24IAC = chr(255) # Interpret as command
25DONT = chr(254)
26DO = chr(253)
27WONT = chr(252)
28WILL = chr(251)
29
30def main():
31 if len(sys.argv) < 2:
32 sys.stderr.write('usage: telnet hostname [port]\n')
33 sys.exit(2)
34 host = sys.argv[1]
35 try:
36 hostaddr = gethostbyname(host)
37 except error:
38 sys.stderr.write(sys.argv[1] + ': bad host name\n')
39 sys.exit(2)
40 #
41 if len(sys.argv) > 2:
42 servname = sys.argv[2]
43 else:
44 servname = 'telnet'
45 #
46 if '0' <= servname[:1] <= '9':
47 port = eval(servname)
48 else:
49 try:
50 port = getservbyname(servname, 'tcp')
51 except error:
52 sys.stderr.write(servname + ': bad tcp service name\n')
53 sys.exit(2)
54 #
55 s = socket(AF_INET, SOCK_STREAM)
56 #
57 try:
58 s.connect((host, port))
59 except error, msg:
60 sys.stderr.write('connect failed: %r\n' % (msg,))
61 sys.exit(1)
62 #
63 thread.start_new(child, (s,))
64 parent(s)
65
66def parent(s):
67 # read socket, write stdout
68 iac = 0 # Interpret next char as command
69 opt = '' # Interpret next char as option
70 while 1:
71 data, dummy = s.recvfrom(BUFSIZE)
72 if not data:
73 # EOF -- exit
74 sys.stderr.write( '(Closed by remote host)\n')
75 sys.exit(1)
76 cleandata = ''
77 for c in data:
78 if opt:
79 print ord(c)
80## print '(replying: %r)' % (opt+c,)
81 s.send(opt + c)
82 opt = ''
83 elif iac:
84 iac = 0
85 if c == IAC:
86 cleandata = cleandata + c
87 elif c in (DO, DONT):
88 if c == DO: print '(DO)',
89 else: print '(DONT)',
90 opt = IAC + WONT
91 elif c in (WILL, WONT):
92 if c == WILL: print '(WILL)',
93 else: print '(WONT)',
94 opt = IAC + DONT
95 else:
96 print '(command)', ord(c)
97 elif c == IAC:
98 iac = 1
99 print '(IAC)',
100 else:
101 cleandata = cleandata + c
102 sys.stdout.write(cleandata)
103 sys.stdout.flush()
104## print 'Out:', repr(cleandata)
105
106def child(s):
107 # read stdin, write socket
108 while 1:
109 line = sys.stdin.readline()
110## print 'Got:', repr(line)
111 if not line: break
112 s.send(line)
113
114main()
sys/src/cmd/python/Demo/tix/INSTALL.txt+89−0
@@ -0,0 +1,89 @@
1$Id: INSTALL.txt 24230 2001-11-11 14:07:37Z loewis $
2
3Installing Tix.py
4----------------
5
60) To use Tix.py, you need Tcl/Tk (V8.3.3), Tix (V8.1.1) and Python (V2.1.1).
7 Tix.py has been written and tested on a Intel Pentium running RH Linux 5.2
8 and Mandrake Linux 7.0 and Windows with the above mentioned packages.
9
10 Older versions, e.g. Tix 4.1 and Tk 8.0, might also work.
11
12 There is nothing OS-specific in Tix.py itself so it should work on
13 any machine with Tix and Python installed. You can get Tcl and Tk
14 from http://dev.scriptics.com and Tix from http://tix.sourceforge.net.
15
161) Build and install Tcl/Tk 8.3. Build and install Tix 8.1.
17 Ensure that Tix is properly installed by running tixwish and executing
18 the demo programs. Under Unix, use the --enable-shared configure option
19 for all three. We recommend tcl8.3.3 for this release of Tix.py.
20
212a) If you have a distribution like ActiveState with a tcl subdirectory
22 of $PYTHONHOME, which contains the directories tcl8.3 and tk8.3,
23 make a directory tix8.1 as well. Recursively copy the files from
24 <tix>/library to $PYTHONHOME/lib/tix8.1, and copy the dynamic library
25 (tix8183.dll or libtix8.1.8.3.so) to the same place as the tcl dynamic
26 libraries ($PYTHONHOME/Dlls or lib/python-2.1/lib-dynload). In this
27 case you are all installed, and you can skip to the end.
28
292b) Modify Modules/Setup.dist and setup.py to change the version of the
30 tix library from tix4.1.8.0 to tix8.1.8.3
31 These modified files can be used for Tkinter with or without Tix.
32
333) The default is to build dynamically, and use the Tcl 'package require'.
34 To build statically, modify the Modules/Setup file to link in the Tix
35 library according to the comments in the file. On Linux this looks like:
36
37# *** Always uncomment this (leave the leading underscore in!):
38_tkinter _tkinter.c tkappinit.c -DWITH_APPINIT \
39# *** Uncomment and edit to reflect where your Tcl/Tk libraries are:
40 -L/usr/local/lib \
41# *** Uncomment and edit to reflect where your Tcl/Tk headers are:
42 -I/usr/local/include \
43# *** Uncomment and edit to reflect where your X11 header files are:
44 -I/usr/X11R6/include \
45# *** Or uncomment this for Solaris:
46# -I/usr/openwin/include \
47# *** Uncomment and edit for BLT extension only:
48# -DWITH_BLT -I/usr/local/blt/blt8.0-unoff/include -lBLT8.0 \
49# *** Uncomment and edit for PIL (TkImaging) extension only:
50# (See http://www.pythonware.com/products/pil/ for more info)
51# -DWITH_PIL -I../Extensions/Imaging/libImaging tkImaging.c \
52# *** Uncomment and edit for TOGL extension only:
53# -DWITH_TOGL togl.c \
54# *** Uncomment and edit for Tix extension only:
55 -DWITH_TIX -ltix8.1.8.3 \
56# *** Uncomment and edit to reflect your Tcl/Tk versions:
57 -ltk8.3 -ltcl8.3 \
58# *** Uncomment and edit to reflect where your X11 libraries are:
59 -L/usr/X11R6/lib \
60# *** Or uncomment this for Solaris:
61# -L/usr/openwin/lib \
62# *** Uncomment these for TOGL extension only:
63# -lGL -lGLU -lXext -lXmu \
64# *** Uncomment for AIX:
65# -lld \
66# *** Always uncomment this; X11 libraries to link with:
67 -lX11
68
694) Rebuild Python and reinstall.
70
71You should now have a working Tix implementation in Python. To see if all
72is as it should be, run the 'tixwidgets.py' script in the Demo/tix directory.
73Under X windows, do
74 /usr/local/bin/python Demo/tix/tixwidgets.py
75
76If this does not work, you may need to tell python where to find
77the Tcl, Tk and Tix library files. This is done by setting the
78TCL_LIBRARY, TK_LIBRARY and TIX_LIBRARY environment variables. Try this:
79
80 env TCL_LIBRARY=/usr/local/lib/tcl8.3 \
81 TK_LIBRARY=/usr/local/lib/tk8.3 \
82 TIX_LIBRARY=/usr/local/lib/tix8.1 \
83 /usr/local/bin/python Demo/tix/tixwidgets.py
84
85
86If you find any bugs or have suggestions for improvement, please report them
87via http://tix.sourceforge.net
88
89
sys/src/cmd/python/Demo/tix/README.txt+19−0
@@ -0,0 +1,19 @@
1About Tix.py
2-----------
3
4Tix.py is based on an idea of Jean-Marc Lugrin (lugrin@ms.com) who wrote
5pytix (another Python-Tix marriage). Tix widgets are an attractive and
6useful extension to Tk. See http://tix.sourceforge.net
7for more details about Tix and how to get it.
8
9Features:
10 1) It is almost complete.
11 2) Tix widgets are represented by classes in Python. Sub-widgets
12 are members of the mega-widget class. For example, if a
13 particular TixWidget (e.g. ScrolledText) has an embedded widget
14 (Text in this case), it is possible to call the methods of the
15 child directly.
16 3) The members of the class are created automatically. In the case
17 of widgets like ButtonBox, the members are added dynamically.
18
19
sys/src/cmd/python/Demo/tix/bitmaps/about.xpm+50−0
@@ -0,0 +1,50 @@
1/* XPM */
2static char * about_xpm[] = {
3"50 40 7 1",
4" s None c None",
5". c black",
6"X c white",
7"o c gray70",
8"O c navy",
9"+ c red",
10"@ c yellow",
11" ",
12" ",
13" ",
14" ................................. ",
15" ..XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXoo. ",
16" .XooooooooooooooooooooooooooooooXo. ",
17" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXooXo. ",
18" ..oooooooooooooooooooooooooooooooXo. ",
19" ...............................XoXo. ",
20" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
21" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
22" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
23" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
24" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo.++++ ",
25" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo+++ ",
26" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.Xo+++++ ",
27" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.Xo++++++ ",
28" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.Xo+++ + ",
29" .OOOOO@@@@@OOOOOOOOOOOOOOOOOOO.Xo++. ",
30" .OOOOOOO@OOOOO@OOOOOOOOOOOOOOO.XoXo. ",
31" .OOOOOOO@OOOOOOOOOOOOOOOOOOOOO.XoXo. ",
32" .OOOOOOO@OOOO@@OOO@OOO@OOOOOOO.XoXo. ",
33" .OOOOOOO@OOOOO@OOOO@O@OOOOOOOO.XoXo. ",
34" .OOOOOOO@OOOOO@OOOOO@OOOOOOOOO.XoXo. ",
35" .OOOOOOO@OOOOO@OOOOO@OOOOOOOOO.XoXo. ",
36" .OOOOOOO@OOOOO@OOOO@O@OOOOOOOO.XoXo. ",
37" .OOOOOOO@OOOO@@@OO@OOO@OOOOOOO.XoXo. ",
38" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
39" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
40" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
41" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
42" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
43" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
44" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.Xo.. ",
45" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.Xo ",
46" OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.X. ",
47" ............................. ",
48" ",
49" ",
50" "};
sys/src/cmd/python/Demo/tix/bitmaps/bold.xbm+6−0
@@ -0,0 +1,6 @@
1#define bold_width 16
2#define bold_height 16
3static unsigned char bold_bits[] = {
4 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xfc, 0x0f, 0x18, 0x1c, 0x18, 0x18,
5 0x18, 0x18, 0x18, 0x1c, 0xf8, 0x0f, 0xf8, 0x0f, 0x18, 0x18, 0x18, 0x30,
6 0x18, 0x30, 0x18, 0x38, 0xfc, 0x3f, 0xfc, 0x1f};
sys/src/cmd/python/Demo/tix/bitmaps/capital.xbm+6−0
@@ -0,0 +1,6 @@
1#define capital_width 16
2#define capital_height 16
3static unsigned char capital_bits[] = {
4 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x08, 0x30, 0x0c, 0x30, 0x06,
5 0x30, 0x03, 0xb0, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x01, 0xb0, 0x03,
6 0x30, 0x07, 0x30, 0x0e, 0x30, 0x1c, 0x00, 0x00};
sys/src/cmd/python/Demo/tix/bitmaps/centerj.xbm+6−0
@@ -0,0 +1,6 @@
1#define centerj_width 16
2#define centerj_height 16
3static unsigned char centerj_bits[] = {
4 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3e, 0x00, 0x00, 0xc0, 0x0d,
5 0x00, 0x00, 0x58, 0x77, 0x00, 0x00, 0xb0, 0x3b, 0x00, 0x00, 0xdc, 0xf7,
6 0x00, 0x00, 0xf0, 0x3e, 0x00, 0x00, 0xd8, 0x7e};
sys/src/cmd/python/Demo/tix/bitmaps/combobox.xbm+14−0
@@ -0,0 +1,14 @@
1#define combobox_width 32
2#define combobox_height 32
3static unsigned char combobox_bits[] = {
4 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5 0xfc, 0xff, 0xff, 0x3e, 0x04, 0x00, 0x80, 0x2a, 0x04, 0x00, 0x80, 0x2a,
6 0x04, 0x00, 0x80, 0x2a, 0x04, 0x00, 0x80, 0x2b, 0xfc, 0xff, 0xff, 0x3e,
7 0x08, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x3e, 0x08, 0x00, 0x00, 0x2a,
8 0x28, 0x49, 0x00, 0x2a, 0x08, 0x00, 0x00, 0x3e, 0x08, 0x00, 0x00, 0x22,
9 0x08, 0x00, 0x00, 0x22, 0x28, 0x49, 0x12, 0x22, 0x08, 0x00, 0x00, 0x22,
10 0x08, 0x00, 0x00, 0x22, 0x08, 0x00, 0x00, 0x22, 0x28, 0x49, 0x02, 0x22,
11 0x08, 0x00, 0x00, 0x3e, 0x08, 0x00, 0x00, 0x2a, 0x08, 0x00, 0x00, 0x2a,
12 0xf8, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
14 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
sys/src/cmd/python/Demo/tix/bitmaps/combobox.xpm+49−0
@@ -0,0 +1,49 @@
1/* XPM */
2static char * combobox_xpm[] = {
3"50 40 6 1",
4" s None c None",
5". c black",
6"X c white",
7"o c #FFFF80808080",
8"O c gray70",
9"+ c #808000008080",
10" ",
11" ",
12" ",
13" .................................... XXXXXXX ",
14" .ooooooooooooooooooooooooooooooooooX X . . ",
15" .ooooooooooooooooooooooooooooooooooX X . . ",
16" .oooo.oooooooooooooooooooooooooooooX X . . ",
17" .oo.o..oo.o.oo.o.ooooooooooooooooooX X . . ",
18" .o..o.o.o.oo.oo.oo.ooooooooooooooooX X ... . ",
19" .oo.oo.oo.o.oo.ooo.ooooooooooooooooX X . . ",
20" .ooooooooooooooooooooooooooooooooooX X . ",
21" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X...... ",
22" ",
23" ",
24" ",
25" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
26" X............................................ ",
27" X.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX.OOOOX. ",
28" X.O+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX.OX OX. ",
29" X.O++OOO+OO+++OOOOOOOOOOOOOOOOOOOOOOOX.X ..X. ",
30" X.O+O+O+OOO+O+OOOOOOOOOOOOOOOOOOOOOOOX.OOOOX. ",
31" X.O++OOO+OO+++OOOOOOOOOOOOOOOOOOOOOOOX.OOOOX. ",
32" X.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX.XXXXX. ",
33" X.O.....X..........................OOX.X .X. ",
34" X.OX...XXX.X.XX.XX.................OOX.X .X. ",
35" X.OX.X..X..X.XX..XX.X..............OOX.X .X. ",
36" X.O.X...X..X.X...X..X..............OOX.X .X. ",
37" X.OOOOOOOOOOOOOOOOOOOOOOOO+OOOOOOOOOOX.X .X. ",
38" X.OOOOOOOOO+OOO+OOOOO+OOOO+OOOOOOOOOOX.X .X. ",
39" X.O+++OO+OO+O+OO++O++OO+OO+OOOOOOOOOOX.X...X. ",
40" X.OO+OO++OO+O+OO+OOO+OO+O++OOOOOOOOOOX.OOOOX. ",
41" X.OOOOOOOO+OOOOO++OO+OOOOOOOOOOOOOOOOX.OOOOX. ",
42" X.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX.X .X. ",
43" X.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX.O .OX. ",
44" X.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX.OOOOX. ",
45" X.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XXXXX. ",
46" X............................................ ",
47" ",
48" ",
49" "};
sys/src/cmd/python/Demo/tix/bitmaps/drivea.xbm+14−0
@@ -0,0 +1,14 @@
1#define drivea_width 32
2#define drivea_height 32
3static unsigned char drivea_bits[] = {
4 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7 0xf8, 0xff, 0xff, 0x1f, 0x08, 0x00, 0x00, 0x18, 0xa8, 0xaa, 0xaa, 0x1a,
8 0x48, 0x55, 0xd5, 0x1d, 0xa8, 0xaa, 0xaa, 0x1b, 0x48, 0x55, 0x55, 0x1d,
9 0xa8, 0xfa, 0xaf, 0x1a, 0xc8, 0xff, 0xff, 0x1d, 0xa8, 0xfa, 0xaf, 0x1a,
10 0x48, 0x55, 0x55, 0x1d, 0xa8, 0xaa, 0xaa, 0x1a, 0x48, 0x55, 0x55, 0x1d,
11 0xa8, 0xaa, 0xaa, 0x1a, 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f,
12 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
14 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
sys/src/cmd/python/Demo/tix/bitmaps/drivea.xpm+43−0
@@ -0,0 +1,43 @@
1/* XPM */
2static char * drivea_xpm[] = {
3/* width height ncolors chars_per_pixel */
4"32 32 5 1",
5/* colors */
6" s None c None",
7". c #000000000000",
8"X c white",
9"o c #c000c000c000",
10"O c #800080008000",
11/* pixels */
12" ",
13" ",
14" ",
15" ",
16" ",
17" ",
18" ",
19" ",
20" ",
21" .......................... ",
22" .XXXXXXXXXXXXXXXXXXXXXXXo. ",
23" .XooooooooooooooooooooooO. ",
24" .Xooooooooooooooooo..oooO. ",
25" .Xooooooooooooooooo..oooO. ",
26" .XooooooooooooooooooooooO. ",
27" .Xoooooooo.......oooooooO. ",
28" .Xoo...................oO. ",
29" .Xoooooooo.......oooooooO. ",
30" .XooooooooooooooooooooooO. ",
31" .XooooooooooooooooooooooO. ",
32" .XooooooooooooooooooooooO. ",
33" .XooooooooooooooooooooooO. ",
34" .oOOOOOOOOOOOOOOOOOOOOOOO. ",
35" .......................... ",
36" ",
37" ",
38" ",
39" ",
40" ",
41" ",
42" ",
43" "};
sys/src/cmd/python/Demo/tix/bitmaps/exit.xpm+48−0
@@ -0,0 +1,48 @@
1/* XPM */
2static char * exit_xpm[] = {
3"50 40 5 1",
4" s None c None",
5". c black",
6"X c white",
7"o c #000080800000",
8"O c yellow",
9" ",
10" ",
11" ",
12" ",
13" ",
14" ",
15" ",
16" ",
17" ",
18" ....................................... ",
19" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ",
20" .XoooooooooooooooooooooooooooooooooooX. ",
21" .XoooooooooooooooooooooooooooooooooooX. ",
22" .XoooooooooooooooooooooooOoooooooooooX. ",
23" .XoooooooooooooooooooooooOOooooooooooX. ",
24" .XoooooooooooooooooooooooOOOoooooooooX. ",
25" .XoooooOOOOOOOOOOOOOOOOOOOOOOooooooooX. ",
26" .XoooooOOOOOOOOOOOOOOOOOOOOOOOoooooooX. ",
27" .XoooooOOOOOOOOOOOOOOOOOOOOOOOOooooooX. ",
28" .XoooooOOOOOOOOOOOOOOOOOOOOOOOOOoooooX. ",
29" .XoooooOOOOOOOOOOOOOOOOOOOOOOOOooooooX. ",
30" .XoooooOOOOOOOOOOOOOOOOOOOOOOOoooooooX. ",
31" .XoooooOOOOOOOOOOOOOOOOOOOOOOooooooooX. ",
32" .XoooooooooooooooooooooooOOOoooooooooX. ",
33" .XoooooooooooooooooooooooOOooooooooooX. ",
34" .XoooooooooooooooooooooooOoooooooooooX. ",
35" .XoooooooooooooooooooooooooooooooooooX. ",
36" .XoooooooooooooooooooooooooooooooooooX. ",
37" .XoooooooooooooooooooooooooooooooooooX. ",
38" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ",
39" ....................................... ",
40" ",
41" ",
42" ",
43" ",
44" ",
45" ",
46" ",
47" ",
48" "};
sys/src/cmd/python/Demo/tix/bitmaps/filebox.xbm+14−0
@@ -0,0 +1,14 @@
1#define filebox_width 32
2#define filebox_height 32
3static unsigned char filebox_bits[] = {
4 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x3f, 0x04, 0x00, 0x00, 0x20,
6 0xe4, 0xff, 0xff, 0x27, 0x24, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x24,
7 0xe4, 0xff, 0xff, 0x27, 0x04, 0x00, 0x00, 0x20, 0xe4, 0x7f, 0xfe, 0x27,
8 0x24, 0x50, 0x02, 0x25, 0x24, 0x40, 0x02, 0x24, 0x24, 0x50, 0x02, 0x25,
9 0x24, 0x40, 0x02, 0x24, 0x24, 0x50, 0x02, 0x25, 0x24, 0x40, 0x02, 0x24,
10 0x24, 0x50, 0x02, 0x25, 0xe4, 0x7f, 0xfe, 0x27, 0x04, 0x00, 0x00, 0x20,
11 0xe4, 0xff, 0xff, 0x27, 0x24, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x24,
12 0xe4, 0xff, 0xff, 0x27, 0x04, 0x00, 0x00, 0x20, 0xfc, 0xff, 0xff, 0x3f,
13 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
14 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
sys/src/cmd/python/Demo/tix/bitmaps/filebox.xpm+49−0
@@ -0,0 +1,49 @@
1/* XPM */
2static char * filebox_xpm[] = {
3"50 40 6 1",
4" s None c None",
5". c white",
6"X c gray80",
7"o c black",
8"O c #FFFF80808080",
9"+ c gray70",
10" ",
11" ",
12" ",
13" ............................................ ",
14" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
15" .XXooXooXoXooXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
16" .XXooXooXoXooXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
17" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
18" .XXooooooooooooooooooooooooooooooooooooo.XXo ",
19" .XXoOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XXo ",
20" .XXoOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XXo ",
21" .XX......................................XXo ",
22" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
23" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
24" .XXoooooooooooooooo.XXXXoooooooooooooooo.XXo ",
25" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
26" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
27" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
28" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
29" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
30" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
31" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
32" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
33" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
34" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
35" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
36" .XX.................XXXX.................XXo ",
37" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
38" .XXooXooXoXooXoXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
39" .XXooXooXoXooXoXooXXXXXXXXXXXXXXXXXXXXXXXXXo ",
40" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
41" .XXoooooooooooooooooooooooooooooooooooooo.Xo ",
42" .XXoOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.Xo ",
43" .XXoOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.Xo ",
44" .XX.......................................Xo ",
45" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
46" .ooooooooooooooooooooooooooooooooooooooooooo ",
47" ",
48" ",
49" "};
sys/src/cmd/python/Demo/tix/bitmaps/italic.xbm+6−0
@@ -0,0 +1,6 @@
1#define italic_width 16
2#define italic_height 16
3static unsigned char italic_bits[] = {
4 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x80, 0x3f, 0x00, 0x06, 0x00, 0x06,
5 0x00, 0x03, 0x00, 0x03, 0x80, 0x01, 0x80, 0x01, 0xc0, 0x00, 0xc0, 0x00,
6 0x60, 0x00, 0x60, 0x00, 0xfc, 0x01, 0xfc, 0x01};
sys/src/cmd/python/Demo/tix/bitmaps/justify.xbm+6−0
@@ -0,0 +1,6 @@
1#define justify_width 16
2#define justify_height 16
3static unsigned char justify_bits[] = {
4 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xdb, 0x00, 0x00, 0x7c, 0xdb,
5 0x00, 0x00, 0xbc, 0xf7, 0x00, 0x00, 0xdc, 0xde, 0x00, 0x00, 0x6c, 0xdf,
6 0x00, 0x00, 0x6c, 0xef, 0x00, 0x00, 0xdc, 0xdf};
sys/src/cmd/python/Demo/tix/bitmaps/leftj.xbm+6−0
@@ -0,0 +1,6 @@
1#define leftj_width 16
2#define leftj_height 16
3static unsigned char leftj_bits[] = {
4 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x6d, 0x00, 0x00, 0xdc, 0x01,
5 0x00, 0x00, 0xec, 0x0e, 0x00, 0x00, 0xfc, 0x7e, 0x00, 0x00, 0xdc, 0x03,
6 0x00, 0x00, 0x6c, 0x3b, 0x00, 0x00, 0x6c, 0x1f};
sys/src/cmd/python/Demo/tix/bitmaps/netw.xbm+14−0
@@ -0,0 +1,14 @@
1#define netw_width 32
2#define netw_height 32
3static unsigned char netw_bits[] = {
4 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x02, 0x40,
5 0x00, 0x00, 0xfa, 0x5f, 0x00, 0x00, 0x0a, 0x50, 0x00, 0x00, 0x0a, 0x52,
6 0x00, 0x00, 0x0a, 0x52, 0x00, 0x00, 0x8a, 0x51, 0x00, 0x00, 0x0a, 0x50,
7 0x00, 0x00, 0x4a, 0x50, 0x00, 0x00, 0x0a, 0x50, 0x00, 0x00, 0x0a, 0x50,
8 0x00, 0x00, 0xfa, 0x5f, 0x00, 0x00, 0x02, 0x40, 0xfe, 0x7f, 0x52, 0x55,
9 0x02, 0x40, 0xaa, 0x6a, 0xfa, 0x5f, 0xfe, 0x7f, 0x0a, 0x50, 0xfe, 0x7f,
10 0x0a, 0x52, 0x80, 0x00, 0x0a, 0x52, 0x80, 0x00, 0x8a, 0x51, 0x80, 0x00,
11 0x0a, 0x50, 0x80, 0x00, 0x4a, 0x50, 0x80, 0x00, 0x0a, 0x50, 0xe0, 0x03,
12 0x0a, 0x50, 0x20, 0x02, 0xfa, 0xdf, 0x3f, 0x03, 0x02, 0x40, 0xa0, 0x02,
13 0x52, 0x55, 0xe0, 0x03, 0xaa, 0x6a, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00,
14 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
sys/src/cmd/python/Demo/tix/bitmaps/netw.xpm+45−0
@@ -0,0 +1,45 @@
1/* XPM */
2static char * netw_xpm[] = {
3/* width height ncolors chars_per_pixel */
4"32 32 7 1",
5/* colors */
6" s None c None",
7". c #000000000000",
8"X c white",
9"o c #c000c000c000",
10"O c #404040",
11"+ c blue",
12"@ c red",
13/* pixels */
14" ",
15" .............. ",
16" .XXXXXXXXXXXX. ",
17" .XooooooooooO. ",
18" .Xo.......XoO. ",
19" .Xo.++++o+XoO. ",
20" .Xo.++++o+XoO. ",
21" .Xo.++oo++XoO. ",
22" .Xo.++++++XoO. ",
23" .Xo.+o++++XoO. ",
24" .Xo.++++++XoO. ",
25" .Xo.XXXXXXXoO. ",
26" .XooooooooooO. ",
27" .Xo@ooo....oO. ",
28" .............. .XooooooooooO. ",
29" .XXXXXXXXXXXX. .XooooooooooO. ",
30" .XooooooooooO. .OOOOOOOOOOOO. ",
31" .Xo.......XoO. .............. ",
32" .Xo.++++o+XoO. @ ",
33" .Xo.++++o+XoO. @ ",
34" .Xo.++oo++XoO. @ ",
35" .Xo.++++++XoO. @ ",
36" .Xo.+o++++XoO. @ ",
37" .Xo.++++++XoO. ..... ",
38" .Xo.XXXXXXXoO. .XXX. ",
39" .XooooooooooO.@@@@@@.X O. ",
40" .Xo@ooo....oO. .OOO. ",
41" .XooooooooooO. ..... ",
42" .XooooooooooO. ",
43" .OOOOOOOOOOOO. ",
44" .............. ",
45" "};
sys/src/cmd/python/Demo/tix/bitmaps/optmenu.xpm+48−0
@@ -0,0 +1,48 @@
1/* XPM */
2static char * optmenu_xpm[] = {
3"50 40 5 1",
4" s None c None",
5". c white",
6"X c gray80",
7"o c gray50",
8"O c black",
9" ",
10" ",
11" .............................. ",
12" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
13" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
14" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
15" .XXXOXOXXOXXOXXXXOOXXXXXXXXXXo ",
16" .XXXOXOXXOXOXXXOXXOXXXXXXXXXXo ",
17" .XXXXOXXOXXOXXXOXXXOXXXXXXXXXo ",
18" .XXXXOXXXOXXOOXXOXOXXXXXXXXXXo ",
19" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
20" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo.............o ",
21" .............................o o ",
22" ..XXXOXXXXXOXXXXXXXXOXXXXXXXOo o ",
23" ..XXOXOXOXXOXOXXXOXXOXXXXXXXOo ...... o ",
24" ..XXXOXXXOXXOXXXOXXXOXXXXXXXOo . o o ",
25" ..XXOXXXOXXXOXOXXOXXOXXXXXXXOo . o o ",
26" ..XXXXXXXXXXXXXXXXXXXXXXXXXXOo .ooooo o ",
27" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOo o ",
28" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo o ",
29" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXooooooooooooooo ",
30" .XXXXOXXXXXOXXXXXXXXXXXXXXXXXo ",
31" .XXXOXXXXXXXXXOXXXXXXXXXXXXXXo ",
32" .XXXXOXXOXXOXOXOXXXXXXXXXXXXXo ",
33" .XXXXXOXXOXOXXXXXXXXXXXXXXXXXo ",
34" .XXXXXXXXXXXXXOXXXXXXXXXXXXXXo ",
35" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
36" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
37" .XXXOXOXXXXXXXOXOXXXXXOXXXXXXo ",
38" .XXXXXOXOXOXXOXXXXXOXXOXXXXXXo ",
39" .XXXXOXXOXOXOXXXOXOXOXXOXXXXXo ",
40" .XXXOXXXXOXXOXXXOXXOXXXXOXXXXo ",
41" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
42" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
43" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
44" oooooooooooooooooooooooooooooo ",
45" ",
46" ",
47" ",
48" "};
sys/src/cmd/python/Demo/tix/bitmaps/rightj.xbm+6−0
@@ -0,0 +1,6 @@
1#define rightj_width 16
2#define rightj_height 16
3static unsigned char rightj_bits[] = {
4 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xdb, 0x00, 0x00, 0x70, 0xdb,
5 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0xd8, 0xde, 0x00, 0x00, 0xc0, 0xdd,
6 0x00, 0x00, 0xa0, 0xef, 0x00, 0x00, 0xd8, 0xde};
sys/src/cmd/python/Demo/tix/bitmaps/select.xpm+52−0
@@ -0,0 +1,52 @@
1/* XPM */
2static char * select_xpm[] = {
3"50 40 9 1",
4" s None c None",
5". c black",
6"X c gray95",
7"o c gray50",
8"O c gray70",
9"+ c navy",
10"@ c #000080800000",
11"# c #808000000000",
12"$ c white",
13" ",
14" ",
15" ",
16" ",
17" ",
18" ",
19" ",
20" ",
21" ",
22" .............................................. ",
23" .XXXXXXXXXXooooooooooooXXXXXXXXXXXoXXXXXXXXXX. ",
24" .X ooOOOOOOOOOOXX oX o. ",
25" .X ooOOOOOOOOOOXX oX o. ",
26" .X ++++ ooOOOOOOOOOOXX ... oX @ o. ",
27" .X +++++ ooOOOOOOOOOOXX . . oX @@@ o. ",
28" .X +++ + ooOOOOOOOOOOXX . . oX @ @ o. ",
29" .X + + ooOO#####OOOXX . . oX @ @ o. ",
30" .X + + ooOO#OOO##OOXX . oX @ @ o. ",
31" .X + + ooO##OOOO##OXX . oX @ @ o. ",
32" .X ++ ++ ooO###OOO#OOXX . oX @ @ o. ",
33" .X +++++++ ooO#######OOXX . oX @ @ o. ",
34" .X + + ooO##O#OO#OOXX . oX @ @ o. ",
35" .X + ++ ooO##OOOOO#OXX . . oX @ @ o. ",
36" .X + + ooOO#OOOOO#OXX . . oX @ @@ o. ",
37" .X + ++ ooOO#OOOOO#OXX .... oX @@@@@ o. ",
38" .X ooOO######OOXX oX o. ",
39" .X ooOOOOOOOOOOXX $oX o. ",
40" .XoooooooooooXXXXXXXXXXXoooooooooooXooooooooo. ",
41" .............................................. ",
42" ",
43" ",
44" ",
45" ",
46" ",
47" ",
48" ",
49" ",
50" ",
51" ",
52" "};
sys/src/cmd/python/Demo/tix/bitmaps/tix.gif+0−0

Binary file not shown.

sys/src/cmd/python/Demo/tix/bitmaps/underline.xbm+6−0
@@ -0,0 +1,6 @@
1#define underline_width 16
2#define underline_height 16
3static unsigned char underline_bits[] = {
4 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1c, 0x38, 0x1c,
5 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x70, 0x0e,
6 0xf0, 0x0f, 0xe0, 0x07, 0x00, 0x00, 0xf8, 0x1f};
sys/src/cmd/python/Demo/tix/grid.py+28−0
@@ -0,0 +1,28 @@
1###
2import Tix as tk
3from pprint import pprint
4
5r= tk.Tk()
6r.title("test")
7
8l=tk.Label(r, name="a_label")
9l.pack()
10
11class MyGrid(tk.Grid):
12 def __init__(self, *args, **kwargs):
13 kwargs['editnotify']= self.editnotify
14 tk.Grid.__init__(self, *args, **kwargs)
15 def editnotify(self, x, y):
16 return True
17
18g = MyGrid(r, name="a_grid",
19selectunit="cell")
20g.pack(fill=tk.BOTH)
21for x in xrange(5):
22 for y in xrange(5):
23 g.set(x,y,text=str((x,y)))
24
25c = tk.Button(r, text="Close", command=r.destroy)
26c.pack()
27
28tk.mainloop()
sys/src/cmd/python/Demo/tix/samples/Balloon.py+68−0
@@ -0,0 +1,68 @@
1# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
2#
3# $Id: Balloon.py 36560 2004-07-18 06:16:08Z tim_one $
4#
5# Tix Demostration Program
6#
7# This sample program is structured in such a way so that it can be
8# executed from the Tix demo program "tixwidgets.py": it must have a
9# procedure called "RunSample". It should also have the "if" statment
10# at the end of this file so that it can be run as a standalone
11# program.
12
13# This file demonstrates the use of the tixBalloon widget, which provides
14# a interesting way to give help tips about elements in your user interface.
15# Your can display the help message in a "balloon" and a status bar widget.
16#
17
18import Tix
19
20TCL_ALL_EVENTS = 0
21
22def RunSample (root):
23 balloon = DemoBalloon(root)
24 balloon.mainloop()
25 balloon.destroy()
26
27class DemoBalloon:
28 def __init__(self, w):
29 self.root = w
30 self.exit = -1
31
32 z = w.winfo_toplevel()
33 z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
34
35 status = Tix.Label(w, width=40, relief=Tix.SUNKEN, bd=1)
36 status.pack(side=Tix.BOTTOM, fill=Tix.Y, padx=2, pady=1)
37
38 # Create two mysterious widgets that need balloon help
39 button1 = Tix.Button(w, text='Something Unexpected',
40 command=self.quitcmd)
41 button2 = Tix.Button(w, text='Something Else Unexpected')
42 button2['command'] = lambda w=button2: w.destroy()
43 button1.pack(side=Tix.TOP, expand=1)
44 button2.pack(side=Tix.TOP, expand=1)
45
46 # Create the balloon widget and associate it with the widgets that we want
47 # to provide tips for:
48 b = Tix.Balloon(w, statusbar=status)
49
50 b.bind_widget(button1, balloonmsg='Close Window',
51 statusmsg='Press this button to close this window')
52 b.bind_widget(button2, balloonmsg='Self-destruct button',
53 statusmsg='Press this button and it will destroy itself')
54
55 def quitcmd (self):
56 self.exit = 0
57
58 def mainloop(self):
59 foundEvent = 1
60 while self.exit < 0 and foundEvent > 0:
61 foundEvent = self.root.tk.dooneevent(TCL_ALL_EVENTS)
62
63 def destroy (self):
64 self.root.destroy()
65
66if __name__ == '__main__':
67 root = Tix.Tk()
68 RunSample(root)
sys/src/cmd/python/Demo/tix/samples/BtnBox.py+44−0
@@ -0,0 +1,44 @@
1# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
2#
3# $Id: BtnBox.py 36560 2004-07-18 06:16:08Z tim_one $
4#
5# Tix Demostration Program
6#
7# This sample program is structured in such a way so that it can be
8# executed from the Tix demo program "tixwidgets.py": it must have a
9# procedure called "RunSample". It should also have the "if" statment
10# at the end of this file so that it can be run as a standalone
11# program.
12
13# This file demonstrates the use of the tixButtonBox widget, which is a
14# group of TK buttons. You can use it to manage the buttons in a dialog box,
15# for example.
16#
17
18import Tix
19
20def RunSample(w):
21 # Create the label on the top of the dialog box
22 #
23 top = Tix.Label(w, padx=20, pady=10, bd=1, relief=Tix.RAISED,
24 anchor=Tix.CENTER, text='This dialog box is\n a demonstration of the\n tixButtonBox widget')
25
26 # Create the button box and add a few buttons in it. Set the
27 # -width of all the buttons to the same value so that they
28 # appear in the same size.
29 #
30 # Note that the -text, -underline, -command and -width options are all
31 # standard options of the button widgets.
32 #
33 box = Tix.ButtonBox(w, orientation=Tix.HORIZONTAL)
34 box.add('ok', text='OK', underline=0, width=5,
35 command=lambda w=w: w.destroy())
36 box.add('close', text='Cancel', underline=0, width=5,
37 command=lambda w=w: w.destroy())
38 box.pack(side=Tix.BOTTOM, fill=Tix.X)
39 top.pack(side=Tix.TOP, fill=Tix.BOTH, expand=1)
40
41if __name__ == '__main__':
42 root = Tix.Tk()
43 RunSample(root)
44 root.mainloop()
sys/src/cmd/python/Demo/tix/samples/CmpImg.py+196−0
@@ -0,0 +1,196 @@
1# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
2#
3# $Id: CmpImg.py 36560 2004-07-18 06:16:08Z tim_one $
4#
5# Tix Demostration Program
6#
7# This sample program is structured in such a way so that it can be
8# executed from the Tix demo program "tixwidgets.py": it must have a
9# procedure called "RunSample". It should also have the "if" statment
10# at the end of this file so that it can be run as a standalone
11# program.
12
13# This file demonstrates the use of the compound images: it uses compound
14# images to display a text string together with a pixmap inside
15# buttons
16#
17
18import Tix
19
20network_pixmap = """/* XPM */
21static char * netw_xpm[] = {
22/* width height ncolors chars_per_pixel */
23"32 32 7 1",
24/* colors */
25" s None c None",
26". c #000000000000",
27"X c white",
28"o c #c000c000c000",
29"O c #404040",
30"+ c blue",
31"@ c red",
32/* pixels */
33" ",
34" .............. ",
35" .XXXXXXXXXXXX. ",
36" .XooooooooooO. ",
37" .Xo.......XoO. ",
38" .Xo.++++o+XoO. ",
39" .Xo.++++o+XoO. ",
40" .Xo.++oo++XoO. ",
41" .Xo.++++++XoO. ",
42" .Xo.+o++++XoO. ",
43" .Xo.++++++XoO. ",
44" .Xo.XXXXXXXoO. ",
45" .XooooooooooO. ",
46" .Xo@ooo....oO. ",
47" .............. .XooooooooooO. ",
48" .XXXXXXXXXXXX. .XooooooooooO. ",
49" .XooooooooooO. .OOOOOOOOOOOO. ",
50" .Xo.......XoO. .............. ",
51" .Xo.++++o+XoO. @ ",
52" .Xo.++++o+XoO. @ ",
53" .Xo.++oo++XoO. @ ",
54" .Xo.++++++XoO. @ ",
55" .Xo.+o++++XoO. @ ",
56" .Xo.++++++XoO. ..... ",
57" .Xo.XXXXXXXoO. .XXX. ",
58" .XooooooooooO.@@@@@@.X O. ",
59" .Xo@ooo....oO. .OOO. ",
60" .XooooooooooO. ..... ",
61" .XooooooooooO. ",
62" .OOOOOOOOOOOO. ",
63" .............. ",
64" "};
65"""
66
67hard_disk_pixmap = """/* XPM */
68static char * drivea_xpm[] = {
69/* width height ncolors chars_per_pixel */
70"32 32 5 1",
71/* colors */
72" s None c None",
73". c #000000000000",
74"X c white",
75"o c #c000c000c000",
76"O c #800080008000",
77/* pixels */
78" ",
79" ",
80" ",
81" ",
82" ",
83" ",
84" ",
85" ",
86" ",
87" .......................... ",
88" .XXXXXXXXXXXXXXXXXXXXXXXo. ",
89" .XooooooooooooooooooooooO. ",
90" .Xooooooooooooooooo..oooO. ",
91" .Xooooooooooooooooo..oooO. ",
92" .XooooooooooooooooooooooO. ",
93" .Xoooooooo.......oooooooO. ",
94" .Xoo...................oO. ",
95" .Xoooooooo.......oooooooO. ",
96" .XooooooooooooooooooooooO. ",
97" .XooooooooooooooooooooooO. ",
98" .XooooooooooooooooooooooO. ",
99" .XooooooooooooooooooooooO. ",
100" .oOOOOOOOOOOOOOOOOOOOOOOO. ",
101" .......................... ",
102" ",
103" ",
104" ",
105" ",
106" ",
107" ",
108" ",
109" "};
110"""
111
112network_bitmap = """
113#define netw_width 32
114#define netw_height 32
115static unsigned char netw_bits[] = {
116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x02, 0x40,
117 0x00, 0x00, 0xfa, 0x5f, 0x00, 0x00, 0x0a, 0x50, 0x00, 0x00, 0x0a, 0x52,
118 0x00, 0x00, 0x0a, 0x52, 0x00, 0x00, 0x8a, 0x51, 0x00, 0x00, 0x0a, 0x50,
119 0x00, 0x00, 0x4a, 0x50, 0x00, 0x00, 0x0a, 0x50, 0x00, 0x00, 0x0a, 0x50,
120 0x00, 0x00, 0xfa, 0x5f, 0x00, 0x00, 0x02, 0x40, 0xfe, 0x7f, 0x52, 0x55,
121 0x02, 0x40, 0xaa, 0x6a, 0xfa, 0x5f, 0xfe, 0x7f, 0x0a, 0x50, 0xfe, 0x7f,
122 0x0a, 0x52, 0x80, 0x00, 0x0a, 0x52, 0x80, 0x00, 0x8a, 0x51, 0x80, 0x00,
123 0x0a, 0x50, 0x80, 0x00, 0x4a, 0x50, 0x80, 0x00, 0x0a, 0x50, 0xe0, 0x03,
124 0x0a, 0x50, 0x20, 0x02, 0xfa, 0xdf, 0x3f, 0x03, 0x02, 0x40, 0xa0, 0x02,
125 0x52, 0x55, 0xe0, 0x03, 0xaa, 0x6a, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00,
126 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
127"""
128
129hard_disk_bitmap = """
130#define drivea_width 32
131#define drivea_height 32
132static unsigned char drivea_bits[] = {
133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
136 0xf8, 0xff, 0xff, 0x1f, 0x08, 0x00, 0x00, 0x18, 0xa8, 0xaa, 0xaa, 0x1a,
137 0x48, 0x55, 0xd5, 0x1d, 0xa8, 0xaa, 0xaa, 0x1b, 0x48, 0x55, 0x55, 0x1d,
138 0xa8, 0xfa, 0xaf, 0x1a, 0xc8, 0xff, 0xff, 0x1d, 0xa8, 0xfa, 0xaf, 0x1a,
139 0x48, 0x55, 0x55, 0x1d, 0xa8, 0xaa, 0xaa, 0x1a, 0x48, 0x55, 0x55, 0x1d,
140 0xa8, 0xaa, 0xaa, 0x1a, 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f,
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
144"""
145
146def RunSample(w):
147 w.img0 = Tix.Image('pixmap', data=network_pixmap)
148 if not w.img0:
149 w.img0 = Tix.Image('bitmap', data=network_bitmap)
150 w.img1 = Tix.Image('pixmap', data=hard_disk_pixmap)
151 if not w.img0:
152 w.img1 = Tix.Image('bitmap', data=hard_disk_bitmap)
153
154 hdd = Tix.Button(w, padx=4, pady=1, width=120)
155 net = Tix.Button(w, padx=4, pady=1, width=120)
156
157 # Create the first image: we create a line, then put a string,
158 # a space and a image into this line, from left to right.
159 # The result: we have a one-line image that consists of three
160 # individual items
161 #
162 # The tk.calls should be methods in Tix ...
163 w.hdd_img = Tix.Image('compound', window=hdd)
164 w.hdd_img.tk.call(str(w.hdd_img), 'add', 'line')
165 w.hdd_img.tk.call(str(w.hdd_img), 'add', 'text', '-text', 'Hard Disk',
166 '-underline', '0')
167 w.hdd_img.tk.call(str(w.hdd_img), 'add', 'space', '-width', '7')
168 w.hdd_img.tk.call(str(w.hdd_img), 'add', 'image', '-image', w.img1)
169
170 # Put this image into the first button
171 #
172 hdd['image'] = w.hdd_img
173
174 # Next button
175 w.net_img = Tix.Image('compound', window=net)
176 w.net_img.tk.call(str(w.net_img), 'add', 'line')
177 w.net_img.tk.call(str(w.net_img), 'add', 'text', '-text', 'Network',
178 '-underline', '0')
179 w.net_img.tk.call(str(w.net_img), 'add', 'space', '-width', '7')
180 w.net_img.tk.call(str(w.net_img), 'add', 'image', '-image', w.img0)
181
182 # Put this image into the first button
183 #
184 net['image'] = w.net_img
185
186 close = Tix.Button(w, pady=1, text='Close',
187 command=lambda w=w: w.destroy())
188
189 hdd.pack(side=Tix.LEFT, padx=10, pady=10, fill=Tix.Y, expand=1)
190 net.pack(side=Tix.LEFT, padx=10, pady=10, fill=Tix.Y, expand=1)
191 close.pack(side=Tix.LEFT, padx=10, pady=10, fill=Tix.Y, expand=1)
192
193if __name__ == '__main__':
194 root = Tix.Tk()
195 RunSample(root)
196 root.mainloop()
sys/src/cmd/python/Demo/tix/samples/ComboBox.py+102−0
@@ -0,0 +1,102 @@
1# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
2#
3# $Id: ComboBox.py 36560 2004-07-18 06:16:08Z tim_one $
4#
5# Tix Demostration Program
6#
7# This sample program is structured in such a way so that it can be
8# executed from the Tix demo program "tixwidgets.py": it must have a
9# procedure called "RunSample". It should also have the "if" statment
10# at the end of this file so that it can be run as a standalone
11# program.
12
13# This file demonstrates the use of the tixComboBox widget, which is close
14# to the MS Window Combo Box control.
15#
16import Tix
17
18def RunSample(w):
19 global demo_month, demo_year
20
21 top = Tix.Frame(w, bd=1, relief=Tix.RAISED)
22
23 demo_month = Tix.StringVar()
24 demo_year = Tix.StringVar()
25
26 # $w.top.a is a drop-down combo box. It is not editable -- who wants
27 # to invent new months?
28 #
29 # [Hint] The -options switch sets the options of the subwidgets.
30 # [Hint] We set the label.width subwidget option of both comboboxes to
31 # be 10 so that their labels appear to be aligned.
32 #
33 a = Tix.ComboBox(top, label="Month: ", dropdown=1,
34 command=select_month, editable=0, variable=demo_month,
35 options='listbox.height 6 label.width 10 label.anchor e')
36
37 # $w.top.b is a non-drop-down combo box. It is not editable: we provide
38 # four choices for the user, but he can enter an alternative year if he
39 # wants to.
40 #
41 # [Hint] Use the padY and anchor options of the label subwidget to
42 # align the label with the entry subwidget.
43 # [Hint] Notice that you should use padY (the NAME of the option) and not
44 # pady (the SWITCH of the option).
45 #
46 b = Tix.ComboBox(top, label="Year: ", dropdown=0,
47 command=select_year, editable=1, variable=demo_year,
48 options='listbox.height 4 label.padY 5 label.width 10 label.anchor ne')
49
50 a.pack(side=Tix.TOP, anchor=Tix.W)
51 b.pack(side=Tix.TOP, anchor=Tix.W)
52
53 a.insert(Tix.END, 'January')
54 a.insert(Tix.END, 'February')
55 a.insert(Tix.END, 'March')
56 a.insert(Tix.END, 'April')
57 a.insert(Tix.END, 'May')
58 a.insert(Tix.END, 'June')
59 a.insert(Tix.END, 'July')
60 a.insert(Tix.END, 'August')
61 a.insert(Tix.END, 'September')
62 a.insert(Tix.END, 'October')
63 a.insert(Tix.END, 'November')
64 a.insert(Tix.END, 'December')
65
66 b.insert(Tix.END, '1992')
67 b.insert(Tix.END, '1993')
68 b.insert(Tix.END, '1994')
69 b.insert(Tix.END, '1995')
70 b.insert(Tix.END, '1996')
71
72 # Use "tixSetSilent" to set the values of the combo box if you
73 # don't want your -command procedures (cbx:select_month and
74 # cbx:select_year) to be called.
75 #
76 a.set_silent('January')
77 b.set_silent('1995')
78
79 box = Tix.ButtonBox(w, orientation=Tix.HORIZONTAL)
80 box.add('ok', text='Ok', underline=0, width=6,
81 command=lambda w=w: ok_command(w))
82 box.add('cancel', text='Cancel', underline=0, width=6,
83 command=lambda w=w: w.destroy())
84 box.pack(side=Tix.BOTTOM, fill=Tix.X)
85 top.pack(side=Tix.TOP, fill=Tix.BOTH, expand=1)
86
87def select_month(event=None):
88 # tixDemo:Status "Month = %s" % demo_month.get()
89 pass
90
91def select_year(event=None):
92 # tixDemo:Status "Year = %s" % demo_year.get()
93 pass
94
95def ok_command(w):
96 # tixDemo:Status "Month = %s, Year= %s" % (demo_month.get(), demo_year.get())
97 w.destroy()
98
99if __name__ == '__main__':
100 root = Tix.Tk()
101 RunSample(root)
102 root.mainloop()
sys/src/cmd/python/Demo/tix/samples/Control.py+122−0
@@ -0,0 +1,122 @@
1# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
2#
3# $Id: Control.py 36560 2004-07-18 06:16:08Z tim_one $
4#
5# Tix Demostration Program
6#
7# This sample program is structured in such a way so that it can be
8# executed from the Tix demo program "tixwidgets.py": it must have a
9# procedure called "RunSample". It should also have the "if" statment
10# at the end of this file so that it can be run as a standalone
11# program.
12
13# This file demonstrates the use of the tixControl widget -- it is an
14# entry widget with up/down arrow buttons. You can use the arrow buttons
15# to adjust the value inside the entry widget.
16#
17# This example program uses three Control widgets. One lets you select
18# integer values; one lets you select floating point values and the last
19# one lets you select a few names.
20
21import Tix
22
23TCL_ALL_EVENTS = 0
24
25def RunSample (root):
26 control = DemoControl(root)
27 control.mainloop()
28 control.destroy()
29
30class DemoControl:
31 def __init__(self, w):
32 self.root = w
33 self.exit = -1
34
35 global demo_maker, demo_thrust, demo_num_engines
36
37 demo_maker = Tix.StringVar()
38 demo_thrust = Tix.DoubleVar()
39 demo_num_engines = Tix.IntVar()
40 demo_maker.set('P&W')
41 demo_thrust.set(20000.0)
42 demo_num_engines.set(2)
43
44 top = Tix.Frame(w, bd=1, relief=Tix.RAISED)
45
46 # $w.top.a allows only integer values
47 #
48 # [Hint] The -options switch sets the options of the subwidgets.
49 # [Hint] We set the label.width subwidget option of the Controls to
50 # be 16 so that their labels appear to be aligned.
51 #
52 a = Tix.Control(top, label='Number of Engines: ', integer=1,
53 variable=demo_num_engines, min=1, max=4,
54 options='entry.width 10 label.width 20 label.anchor e')
55
56 b = Tix.Control(top, label='Thrust: ', integer=0,
57 min='10000.0', max='60000.0', step=500,
58 variable=demo_thrust,
59 options='entry.width 10 label.width 20 label.anchor e')
60
61 c = Tix.Control(top, label='Engine Maker: ', value='P&W',
62 variable=demo_maker,
63 options='entry.width 10 label.width 20 label.anchor e')
64
65 # We can't define these in the init because the widget 'c' doesn't
66 # exist yet and we need to reference it
67 c['incrcmd'] = lambda w=c: adjust_maker(w, 1)
68 c['decrcmd'] = lambda w=c: adjust_maker(w, -1)
69 c['validatecmd'] = lambda w=c: validate_maker(w)
70
71 a.pack(side=Tix.TOP, anchor=Tix.W)
72 b.pack(side=Tix.TOP, anchor=Tix.W)
73 c.pack(side=Tix.TOP, anchor=Tix.W)
74
75 box = Tix.ButtonBox(w, orientation=Tix.HORIZONTAL)
76 box.add('ok', text='Ok', underline=0, width=6,
77 command=self.okcmd)
78 box.add('cancel', text='Cancel', underline=0, width=6,
79 command=self.quitcmd)
80 box.pack(side=Tix.BOTTOM, fill=Tix.X)
81 top.pack(side=Tix.TOP, fill=Tix.BOTH, expand=1)
82
83 def okcmd (self):
84 # tixDemo:Status "Selected %d of %s engines each of thrust %d", (demo_num_engines.get(), demo_maker.get(), demo_thrust.get())
85 self.quitcmd()
86
87 def quitcmd (self):
88 self.exit = 0
89
90 def mainloop(self):
91 while self.exit < 0:
92 self.root.tk.dooneevent(TCL_ALL_EVENTS)
93
94 def destroy (self):
95 self.root.destroy()
96
97maker_list = ['P&W', 'GE', 'Rolls Royce']
98
99def adjust_maker(w, inc):
100 i = maker_list.index(demo_maker.get())
101 i = i + inc
102 if i >= len(maker_list):
103 i = 0
104 elif i < 0:
105 i = len(maker_list) - 1
106
107 # In Tcl/Tix we should return the string maker_list[i]. We can't
108 # do that in Tkinter so we set the global variable. (This works).
109 demo_maker.set(maker_list[i])
110
111def validate_maker(w):
112 try:
113 i = maker_list.index(demo_maker.get())
114 except ValueError:
115 # Works here though. Why ? Beats me.
116 return maker_list[0]
117 # Works here though. Why ? Beats me.
118 return maker_list[i]
119
120if __name__ == '__main__':
121 root = Tix.Tk()
122 RunSample(root)
sys/src/cmd/python/Demo/tix/samples/DirList.py+131−0
@@ -0,0 +1,131 @@
1# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
2#
3# $Id: DirList.py 36560 2004-07-18 06:16:08Z tim_one $
4#
5# Tix Demostration Program
6#
7# This sample program is structured in such a way so that it can be
8# executed from the Tix demo program "tixwidgets.py": it must have a
9# procedure called "RunSample". It should also have the "if" statment
10# at the end of this file so that it can be run as a standalone
11# program using tixwish.
12
13# This file demonstrates the use of the tixDirList widget -- you can
14# use it for the user to select a directory. For example, an installation
15# program can use the tixDirList widget to ask the user to select the
16# installation directory for an application.
17#
18
19import Tix, os, copy
20from Tkconstants import *
21
22TCL_ALL_EVENTS = 0
23
24def RunSample (root):
25 dirlist = DemoDirList(root)
26 dirlist.mainloop()
27 dirlist.destroy()
28
29class DemoDirList:
30 def __init__(self, w):
31 self.root = w
32 self.exit = -1
33
34 z = w.winfo_toplevel()
35 z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
36
37 # Create the tixDirList and the tixLabelEntry widgets on the on the top
38 # of the dialog box
39
40 # bg = root.tk.eval('tix option get bg')
41 # adding bg=bg crashes Windows pythonw tk8.3.3 Python 2.1.0
42
43 top = Tix.Frame( w, relief=RAISED, bd=1)
44
45 # Create the DirList widget. By default it will show the current
46 # directory
47 #
48 #
49 top.dir = Tix.DirList(top)
50 top.dir.hlist['width'] = 40
51
52 # When the user presses the ".." button, the selected directory
53 # is "transferred" into the entry widget
54 #
55 top.btn = Tix.Button(top, text = " >> ", pady = 0)
56
57 # We use a LabelEntry to hold the installation directory. The user
58 # can choose from the DirList widget, or he can type in the directory
59 # manually
60 #
61 top.ent = Tix.LabelEntry(top, label="Installation Directory:",
62 labelside = 'top',
63 options = '''
64 entry.width 40
65 label.anchor w
66 ''')
67
68 font = self.root.tk.eval('tix option get fixed_font')
69 # font = self.root.master.tix_option_get('fixed_font')
70 top.ent.entry['font'] = font
71
72 self.dlist_dir = copy.copy(os.curdir)
73 # This should work setting the entry's textvariable
74 top.ent.entry['textvariable'] = self.dlist_dir
75 top.btn['command'] = lambda dir=top.dir, ent=top.ent, self=self: \
76 self.copy_name(dir,ent)
77
78 # top.ent.entry.insert(0,'tix'+repr(self))
79 top.ent.entry.bind('<Return>', lambda self=self: self.okcmd () )
80
81 top.pack( expand='yes', fill='both', side=TOP)
82 top.dir.pack( expand=1, fill=BOTH, padx=4, pady=4, side=LEFT)
83 top.btn.pack( anchor='s', padx=4, pady=4, side=LEFT)
84 top.ent.pack( expand=1, fill=X, anchor='s', padx=4, pady=4, side=LEFT)
85
86 # Use a ButtonBox to hold the buttons.
87 #
88 box = Tix.ButtonBox (w, orientation='horizontal')
89 box.add ('ok', text='Ok', underline=0, width=6,
90 command = lambda self=self: self.okcmd () )
91 box.add ('cancel', text='Cancel', underline=0, width=6,
92 command = lambda self=self: self.quitcmd () )
93
94 box.pack( anchor='s', fill='x', side=BOTTOM)
95
96 def copy_name (self, dir, ent):
97 # This should work as it is the entry's textvariable
98 self.dlist_dir = dir.cget('value')
99 # but it isn't so I'll do it manually
100 ent.entry.delete(0,'end')
101 ent.entry.insert(0, self.dlist_dir)
102
103 def okcmd (self):
104 # tixDemo:Status "You have selected the directory" + self.dlist_dir
105 self.quitcmd()
106
107 def quitcmd (self):
108 self.exit = 0
109
110 def mainloop(self):
111 while self.exit < 0:
112 self.root.tk.dooneevent(TCL_ALL_EVENTS)
113
114 def destroy (self):
115 self.root.destroy()
116
117# This "if" statement makes it possible to run this script file inside or
118# outside of the main demo program "tixwidgets.py".
119#
120if __name__== '__main__' :
121 import tkMessageBox, traceback
122
123 try:
124 root=Tix.Tk()
125 RunSample(root)
126 except:
127 t, v, tb = sys.exc_info()
128 text = "Error running the demo script:\n"
129 for line in traceback.format_exception(t,v,tb):
130 text = text + line + '\n'
131 d = tkMessageBox.showerror ( 'Tix Demo Error', text)
sys/src/cmd/python/Demo/tix/samples/DirTree.py+117−0
@@ -0,0 +1,117 @@
1# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
2#
3# $Id: DirTree.py 36560 2004-07-18 06:16:08Z tim_one $
4#
5# Tix Demostration Program
6#
7# This sample program is structured in such a way so that it can be
8# executed from the Tix demo program "tixwidgets.py": it must have a
9# procedure called "RunSample". It should also have the "if" statment
10# at the end of this file so that it can be run as a standalone
11# program using tixwish.
12
13# This file demonstrates the use of the tixDirTree widget -- you can
14# use it for the user to select a directory. For example, an installation
15# program can use the tixDirTree widget to ask the user to select the
16# installation directory for an application.
17#
18
19import Tix, os, copy
20from Tkconstants import *
21
22TCL_ALL_EVENTS = 0
23
24def RunSample (root):
25 dirtree = DemoDirTree(root)
26 dirtree.mainloop()
27 dirtree.destroy()
28
29class DemoDirTree:
30 def __init__(self, w):
31 self.root = w
32 self.exit = -1
33
34 z = w.winfo_toplevel()
35 z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
36
37 # Create the tixDirTree and the tixLabelEntry widgets on the on the top
38 # of the dialog box
39
40 # bg = root.tk.eval('tix option get bg')
41 # adding bg=bg crashes Windows pythonw tk8.3.3 Python 2.1.0
42
43 top = Tix.Frame( w, relief=RAISED, bd=1)
44
45 # Create the DirTree widget. By default it will show the current
46 # directory
47 #
48 #
49 top.dir = Tix.DirTree(top)
50 top.dir.hlist['width'] = 40
51
52 # When the user presses the ".." button, the selected directory
53 # is "transferred" into the entry widget
54 #
55 top.btn = Tix.Button(top, text = " >> ", pady = 0)
56
57 # We use a LabelEntry to hold the installation directory. The user
58 # can choose from the DirTree widget, or he can type in the directory
59 # manually
60 #
61 top.ent = Tix.LabelEntry(top, label="Installation Directory:",
62 labelside = 'top',
63 options = '''
64 entry.width 40
65 label.anchor w
66 ''')
67
68 self.dlist_dir = copy.copy(os.curdir)
69 top.ent.entry['textvariable'] = self.dlist_dir
70 top.btn['command'] = lambda dir=top.dir, ent=top.ent, self=self: \
71 self.copy_name(dir,ent)
72
73 top.ent.entry.bind('<Return>', lambda self=self: self.okcmd () )
74
75 top.pack( expand='yes', fill='both', side=TOP)
76 top.dir.pack( expand=1, fill=BOTH, padx=4, pady=4, side=LEFT)
77 top.btn.pack( anchor='s', padx=4, pady=4, side=LEFT)
78 top.ent.pack( expand=1, fill=X, anchor='s', padx=4, pady=4, side=LEFT)
79
80 # Use a ButtonBox to hold the buttons.
81 #
82 box = Tix.ButtonBox (w, orientation='horizontal')
83 box.add ('ok', text='Ok', underline=0, width=6,
84 command = lambda self=self: self.okcmd () )
85 box.add ('cancel', text='Cancel', underline=0, width=6,
86 command = lambda self=self: self.quitcmd () )
87
88 box.pack( anchor='s', fill='x', side=BOTTOM)
89
90 def copy_name (self, dir, ent):
91 # This should work as it is the entry's textvariable
92 self.dlist_dir = dir.cget('value')
93 # but it isn't so I'll do it manually
94 ent.entry.delete(0,'end')
95 ent.entry.insert(0, self.dlist_dir)
96
97 def okcmd (self):
98 # tixDemo:Status "You have selected the directory" + self.dlist_dir
99 self.quitcmd()
100
101 def quitcmd (self):
102 # tixDemo:Status "You have selected the directory" + self.dlist_dir
103 self.exit = 0
104
105 def mainloop(self):
106 while self.exit < 0:
107 self.root.tk.dooneevent(TCL_ALL_EVENTS)
108
109 def destroy (self):
110 self.root.destroy()
111
112# This "if" statement makes it possible to run this script file inside or
113# outside of the main demo program "tixwidgets.py".
114#
115if __name__== '__main__' :
116 root=Tix.Tk()
117 RunSample(root)
sys/src/cmd/python/Demo/tix/samples/NoteBook.py+119−0
@@ -0,0 +1,119 @@
1# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
2#
3# $Id: NoteBook.py 36560 2004-07-18 06:16:08Z tim_one $
4#
5# Tix Demostration Program
6#
7# This sample program is structured in such a way so that it can be
8# executed from the Tix demo program "tixwidgets.py": it must have a
9# procedure called "RunSample". It should also have the "if" statment
10# at the end of this file so that it can be run as a standalone
11# program.
12
13# This file demonstrates the use of the tixNoteBook widget, which allows
14# you to lay out your interface using a "notebook" metaphore
15#
16import Tix
17
18def RunSample(w):
19 global root
20 root = w
21
22 # We use these options to set the sizes of the subwidgets inside the
23 # notebook, so that they are well-aligned on the screen.
24 prefix = Tix.OptionName(w)
25 if prefix:
26 prefix = '*'+prefix
27 else:
28 prefix = ''
29 w.option_add(prefix+'*TixControl*entry.width', 10)
30 w.option_add(prefix+'*TixControl*label.width', 18)
31 w.option_add(prefix+'*TixControl*label.anchor', Tix.E)
32 w.option_add(prefix+'*TixNoteBook*tagPadX', 8)
33
34 # Create the notebook widget and set its backpagecolor to gray.
35 # Note that the -backpagecolor option belongs to the "nbframe"
36 # subwidget.
37 nb = Tix.NoteBook(w, name='nb', ipadx=6, ipady=6)
38 nb['bg'] = 'gray'
39 nb.nbframe['backpagecolor'] = 'gray'
40
41 # Create the two tabs on the notebook. The -underline option
42 # puts a underline on the first character of the labels of the tabs.
43 # Keyboard accelerators will be defined automatically according
44 # to the underlined character.
45 nb.add('hard_disk', label="Hard Disk", underline=0)
46 nb.add('network', label="Network", underline=0)
47
48 nb.pack(expand=1, fill=Tix.BOTH, padx=5, pady=5 ,side=Tix.TOP)
49
50 #----------------------------------------
51 # Create the first page
52 #----------------------------------------
53 # Create two frames: one for the common buttons, one for the
54 # other widgets
55 #
56 tab=nb.hard_disk
57 f = Tix.Frame(tab)
58 common = Tix.Frame(tab)
59
60 f.pack(side=Tix.LEFT, padx=2, pady=2, fill=Tix.BOTH, expand=1)
61 common.pack(side=Tix.RIGHT, padx=2, fill=Tix.Y)
62
63 a = Tix.Control(f, value=12, label='Access time: ')
64 w = Tix.Control(f, value=400, label='Write Throughput: ')
65 r = Tix.Control(f, value=400, label='Read Throughput: ')
66 c = Tix.Control(f, value=1021, label='Capacity: ')
67
68 a.pack(side=Tix.TOP, padx=20, pady=2)
69 w.pack(side=Tix.TOP, padx=20, pady=2)
70 r.pack(side=Tix.TOP, padx=20, pady=2)
71 c.pack(side=Tix.TOP, padx=20, pady=2)
72
73 # Create the common buttons
74 createCommonButtons(common)
75
76 #----------------------------------------
77 # Create the second page
78 #----------------------------------------
79
80 tab = nb.network
81
82 f = Tix.Frame(tab)
83 common = Tix.Frame(tab)
84
85 f.pack(side=Tix.LEFT, padx=2, pady=2, fill=Tix.BOTH, expand=1)
86 common.pack(side=Tix.RIGHT, padx=2, fill=Tix.Y)
87
88 a = Tix.Control(f, value=12, label='Access time: ')
89 w = Tix.Control(f, value=400, label='Write Throughput: ')
90 r = Tix.Control(f, value=400, label='Read Throughput: ')
91 c = Tix.Control(f, value=1021, label='Capacity: ')
92 u = Tix.Control(f, value=10, label='Users: ')
93
94 a.pack(side=Tix.TOP, padx=20, pady=2)
95 w.pack(side=Tix.TOP, padx=20, pady=2)
96 r.pack(side=Tix.TOP, padx=20, pady=2)
97 c.pack(side=Tix.TOP, padx=20, pady=2)
98 u.pack(side=Tix.TOP, padx=20, pady=2)
99
100 createCommonButtons(common)
101
102def doDestroy():
103 global root
104 root.destroy()
105
106def createCommonButtons(master):
107 ok = Tix.Button(master, name='ok', text='OK', width=6,
108 command=doDestroy)
109 cancel = Tix.Button(master, name='cancel',
110 text='Cancel', width=6,
111 command=doDestroy)
112
113 ok.pack(side=Tix.TOP, padx=2, pady=2)
114 cancel.pack(side=Tix.TOP, padx=2, pady=2)
115
116if __name__ == '__main__':
117 root = Tix.Tk()
118 RunSample(root)
119 root.mainloop()
sys/src/cmd/python/Demo/tix/samples/OptMenu.py+68−0
@@ -0,0 +1,68 @@
1# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
2#
3# $Id: OptMenu.py 36560 2004-07-18 06:16:08Z tim_one $
4#
5# Tix Demostration Program
6#
7# This sample program is structured in such a way so that it can be
8# executed from the Tix demo program "tixwidgets.py": it must have a
9# procedure called "RunSample". It should also have the "if" statment
10# at the end of this file so that it can be run as a standalone
11# program.
12
13# This file demonstrates the use of the tixOptionMenu widget -- you can
14# use it for the user to choose from a fixed set of options
15#
16import Tix
17
18options = {'text':'Plain Text', 'post':'PostScript', 'html':'HTML',
19 'tex':'LaTeX', 'rtf':'Rich Text Format'}
20
21def RunSample(w):
22 global demo_opt_from, demo_opt_to
23
24 demo_opt_from = Tix.StringVar()
25 demo_opt_to = Tix.StringVar()
26
27 top = Tix.Frame(w, bd=1, relief=Tix.RAISED)
28
29 from_file = Tix.OptionMenu(top, label="From File Format : ",
30 variable=demo_opt_from,
31 options = 'label.width 19 label.anchor e menubutton.width 15')
32
33 to_file = Tix.OptionMenu(top, label="To File Format : ",
34 variable=demo_opt_to,
35 options='label.width 19 label.anchor e menubutton.width 15')
36
37 # Add the available options to the two OptionMenu widgets
38 #
39 # [Hint] You have to add the options first before you set the
40 # global variables "demo_opt_from" and "demo_opt_to". Otherwise
41 # the OptionMenu widget will complain about "unknown options"!
42 #
43 for opt in options.keys():
44 from_file.add_command(opt, label=options[opt])
45 to_file.add_command(opt, label=options[opt])
46
47 demo_opt_from.set('html')
48 demo_opt_to.set('post')
49
50 from_file.pack(side=Tix.TOP, anchor=Tix.W, pady=3, padx=6)
51 to_file.pack(side=Tix.TOP, anchor=Tix.W, pady=3, padx=6)
52
53 box = Tix.ButtonBox(w, orientation=Tix.HORIZONTAL)
54 box.add('ok', text='Ok', underline=0, width=6,
55 command=lambda w=w: ok_command(w))
56 box.add('cancel', text='Cancel', underline=0, width=6,
57 command=lambda w=w: w.destroy())
58 box.pack(side=Tix.BOTTOM, fill=Tix.X)
59 top.pack(side=Tix.TOP, fill=Tix.BOTH, expand=1)
60
61def ok_command(w):
62 # tixDemo:Status "Convert file from %s to %s" % ( demo_opt_from.get(), demo_opt_to.get())
63 w.destroy()
64
65if __name__ == '__main__':
66 root = Tix.Tk()
67 RunSample(root)
68 root.mainloop()
sys/src/cmd/python/Demo/tix/samples/PanedWin.py+98−0
@@ -0,0 +1,98 @@
1# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
2#
3# $Id: PanedWin.py 36560 2004-07-18 06:16:08Z tim_one $
4#
5# Tix Demostration Program
6#
7# This sample program is structured in such a way so that it can be
8# executed from the Tix demo program "tixwidgets.py": it must have a
9# procedure called "RunSample". It should also have the "if" statment
10# at the end of this file so that it can be run as a standalone
11# program.
12
13# This file demonstrates the use of the tixPanedWindow widget. This program
14# is a dummy news reader: the user can adjust the sizes of the list
15# of artical names and the size of the text widget that shows the body
16# of the article.
17
18import Tix
19
20TCL_ALL_EVENTS = 0
21
22def RunSample (root):
23 panedwin = DemoPanedwin(root)
24 panedwin.mainloop()
25 panedwin.destroy()
26
27class DemoPanedwin:
28 def __init__(self, w):
29 self.root = w
30 self.exit = -1
31
32 z = w.winfo_toplevel()
33 z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
34
35 group = Tix.LabelEntry(w, label='Newsgroup:', options='entry.width 25')
36 group.entry.insert(0,'comp.lang.python')
37 pane = Tix.PanedWindow(w, orientation='vertical')
38
39 p1 = pane.add('list', min=70, size=100)
40 p2 = pane.add('text', min=70)
41 list = Tix.ScrolledListBox(p1)
42 list.listbox['width'] = 80
43 list.listbox['height'] = 5
44 text = Tix.ScrolledText(p2)
45 text.text['width'] = 80
46 text.text['height'] = 20
47
48 list.listbox.insert(Tix.END, " 12324 Re: Tkinter is good for your health")
49 list.listbox.insert(Tix.END, "+ 12325 Re: Tkinter is good for your health")
50 list.listbox.insert(Tix.END, "+ 12326 Re: Tix is even better for your health (Was: Tkinter is good...)")
51 list.listbox.insert(Tix.END, " 12327 Re: Tix is even better for your health (Was: Tkinter is good...)")
52 list.listbox.insert(Tix.END, "+ 12328 Re: Tix is even better for your health (Was: Tkinter is good...)")
53 list.listbox.insert(Tix.END, " 12329 Re: Tix is even better for your health (Was: Tkinter is good...)")
54 list.listbox.insert(Tix.END, "+ 12330 Re: Tix is even better for your health (Was: Tkinter is good...)")
55
56 text.text['bg'] = list.listbox['bg']
57 text.text['wrap'] = 'none'
58 text.text.insert(Tix.END, """
59 Mon, 19 Jun 1995 11:39:52 comp.lang.python Thread 34 of 220
60 Lines 353 A new way to put text and bitmaps together iNo responses
61 ioi@blue.seas.upenn.edu Ioi K. Lam at University of Pennsylvania
62
63 Hi,
64
65 I have implemented a new image type called "compound". It allows you
66 to glue together a bunch of bitmaps, images and text strings together
67 to form a bigger image. Then you can use this image with widgets that
68 support the -image option. For example, you can display a text string string
69 together with a bitmap, at the same time, inside a TK button widget.
70 """)
71 text.text['state'] = 'disabled'
72
73 list.pack(expand=1, fill=Tix.BOTH, padx=4, pady=6)
74 text.pack(expand=1, fill=Tix.BOTH, padx=4, pady=6)
75
76 group.pack(side=Tix.TOP, padx=3, pady=3, fill=Tix.BOTH)
77 pane.pack(side=Tix.TOP, padx=3, pady=3, fill=Tix.BOTH, expand=1)
78
79 box = Tix.ButtonBox(w, orientation=Tix.HORIZONTAL)
80 box.add('ok', text='Ok', underline=0, width=6,
81 command=self.quitcmd)
82 box.add('cancel', text='Cancel', underline=0, width=6,
83 command=self.quitcmd)
84 box.pack(side=Tix.BOTTOM, fill=Tix.X)
85
86 def quitcmd (self):
87 self.exit = 0
88
89 def mainloop(self):
90 while self.exit < 0:
91 self.root.tk.dooneevent(TCL_ALL_EVENTS)
92
93 def destroy (self):
94 self.root.destroy()
95
96if __name__ == '__main__':
97 root = Tix.Tk()
98 RunSample(root)
sys/src/cmd/python/Demo/tix/samples/PopMenu.py+57−0
@@ -0,0 +1,57 @@
1# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
2#
3# $Id: PopMenu.py 36560 2004-07-18 06:16:08Z tim_one $
4#
5# Tix Demostration Program
6#
7# This sample program is structured in such a way so that it can be
8# executed from the Tix demo program "tixwidgets.py": it must have a
9# procedure called "RunSample". It should also have the "if" statment
10# at the end of this file so that it can be run as a standalone
11# program using tixwish.
12
13# This file demonstrates the use of the tixPopupMenu widget.
14#
15import Tix
16
17def RunSample(w):
18 # We create the frame and the button, then we'll bind the PopupMenu
19 # to both widgets. The result is, when you press the right mouse
20 # button over $w.top or $w.top.but, the PopupMenu will come up.
21 #
22 top = Tix.Frame(w, relief=Tix.RAISED, bd=1)
23 but = Tix.Button(top, text='Press the right mouse button over this button or its surrounding area')
24 but.pack(expand=1, fill=Tix.BOTH, padx=50, pady=50)
25
26 p = Tix.PopupMenu(top, title='Popup Test')
27 p.bind_widget(top)
28 p.bind_widget(but)
29
30 # Set the entries inside the PopupMenu widget.
31 # [Hint] You have to manipulate the "menu" subwidget.
32 # $w.top.p itself is NOT a menu widget.
33 # [Hint] Watch carefully how the sub-menu is created
34 #
35 p.menu.add_command(label='Desktop', underline=0)
36 p.menu.add_command(label='Select', underline=0)
37 p.menu.add_command(label='Find', underline=0)
38 p.menu.add_command(label='System', underline=1)
39 p.menu.add_command(label='Help', underline=0)
40 m1 = Tix.Menu(p.menu)
41 m1.add_command(label='Hello')
42 p.menu.add_cascade(label='More', menu=m1)
43
44 but.pack(side=Tix.TOP, padx=40, pady=50)
45
46 box = Tix.ButtonBox(w, orientation=Tix.HORIZONTAL)
47 box.add('ok', text='Ok', underline=0, width=6,
48 command=lambda w=w: w.destroy())
49 box.add('cancel', text='Cancel', underline=0, width=6,
50 command=lambda w=w: w.destroy())
51 box.pack(side=Tix.BOTTOM, fill=Tix.X)
52 top.pack(side=Tix.TOP, fill=Tix.BOTH, expand=1)
53
54if __name__ == '__main__':
55 root = Tix.Tk()
56 RunSample(root)
57 root.mainloop()
sys/src/cmd/python/Demo/tix/samples/SHList1.py+131−0
@@ -0,0 +1,131 @@
1# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
2#
3# $Id: SHList1.py 36560 2004-07-18 06:16:08Z tim_one $
4#
5# Tix Demostration Program
6#
7# This sample program is structured in such a way so that it can be
8# executed from the Tix demo program "tixwidgets.py": it must have a
9# procedure called "RunSample". It should also have the "if" statment
10# at the end of this file so that it can be run as a standalone
11# program using tixwish.
12
13# This file demonstrates the use of the tixScrolledHList widget.
14#
15
16import Tix
17
18TCL_ALL_EVENTS = 0
19
20def RunSample (root):
21 shlist = DemoSHList(root)
22 shlist.mainloop()
23 shlist.destroy()
24
25class DemoSHList:
26 def __init__(self, w):
27 self.root = w
28 self.exit = -1
29
30 z = w.winfo_toplevel()
31 z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
32
33 # We create the frame and the ScrolledHList widget
34 # at the top of the dialog box
35 #
36 top = Tix.Frame( w, relief=Tix.RAISED, bd=1)
37
38 # Put a simple hierachy into the HList (two levels). Use colors and
39 # separator widgets (frames) to make the list look fancy
40 #
41 top.a = Tix.ScrolledHList(top)
42 top.a.pack( expand=1, fill=Tix.BOTH, padx=10, pady=10, side=Tix.TOP)
43
44 # This is our little relational database
45 #
46 bosses = [
47 ('jeff', 'Jeff Waxman'),
48 ('john', 'John Lee'),
49 ('peter', 'Peter Kenson')
50 ]
51
52 employees = [
53 ('alex', 'john', 'Alex Kellman'),
54 ('alan', 'john', 'Alan Adams'),
55 ('andy', 'peter', 'Andreas Crawford'),
56 ('doug', 'jeff', 'Douglas Bloom'),
57 ('jon', 'peter', 'Jon Baraki'),
58 ('chris', 'jeff', 'Chris Geoffrey'),
59 ('chuck', 'jeff', 'Chuck McLean')
60 ]
61
62 hlist=top.a.hlist
63
64 # Let configure the appearance of the HList subwidget
65 #
66 hlist.config( separator='.', width=25, drawbranch=0, indent=10)
67
68 count=0
69 for boss,name in bosses :
70 if count :
71 f=Tix.Frame(hlist, name='sep%d' % count, height=2, width=150,
72 bd=2, relief=Tix.SUNKEN )
73
74 hlist.add_child( itemtype=Tix.WINDOW,
75 window=f, state=Tix.DISABLED )
76
77 hlist.add(boss, itemtype=Tix.TEXT, text=name)
78 count = count+1
79
80
81 for person,boss,name in employees :
82 # '.' is the separator character we chose above
83 #
84 key= boss + '.' + person
85 # ^^^^ ^^^^^^
86 # parent entryPath / child's name
87
88 hlist.add( key, text=name )
89
90 # [Hint] Make sure the keys (e.g. 'boss.person') you choose
91 # are unique names. If you cannot be sure of this (because of
92 # the structure of your database, e.g.) you can use the
93 # "add_child" command instead:
94 #
95 # hlist.addchild( boss, text=name)
96 # ^^^^
97 # parent entryPath
98
99
100 # Use a ButtonBox to hold the buttons.
101 #
102 box= Tix.ButtonBox(top, orientation=Tix.HORIZONTAL )
103 box.add( 'ok', text='Ok', underline=0, width=6,
104 command = self.okcmd)
105
106 box.add( 'cancel', text='Cancel', underline=0, width=6,
107 command = self.quitcmd)
108
109 box.pack( side=Tix.BOTTOM, fill=Tix.X)
110 top.pack( side=Tix.TOP, fill=Tix.BOTH, expand=1 )
111
112 def okcmd (self):
113 self.quitcmd()
114
115 def quitcmd (self):
116 self.exit = 0
117
118 def mainloop(self):
119 while self.exit < 0:
120 self.root.tk.dooneevent(TCL_ALL_EVENTS)
121
122 def destroy (self):
123 self.root.destroy()
124
125
126# This "if" statement makes it possible to run this script file inside or
127# outside of the main demo program "tixwidgets.py".
128#
129if __name__== '__main__' :
130 root=Tix.Tk()
131 RunSample(root)
sys/src/cmd/python/Demo/tix/samples/SHList2.py+168−0
@@ -0,0 +1,168 @@
1# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
2#
3# $Id: SHList2.py 36560 2004-07-18 06:16:08Z tim_one $
4#
5# Tix Demostration Program
6#
7# This sample program is structured in such a way so that it can be
8# executed from the Tix demo program "tixwidget": it must have a
9# procedure called "RunSample". It should also have the "if" statment
10# at the end of this file so that it can be run as a standalone
11# program using tixwish.
12
13# This file demonstrates how to use multiple columns and multiple styles
14# in the tixHList widget
15#
16# In a tixHList widget, you can have one ore more columns.
17#
18
19import Tix
20
21TCL_ALL_EVENTS = 0
22
23def RunSample (root):
24 shlist = DemoSHList(root)
25 shlist.mainloop()
26 shlist.destroy()
27
28class DemoSHList:
29 def __init__(self, w):
30 self.root = w
31 self.exit = -1
32
33 z = w.winfo_toplevel()
34 z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
35
36 # We create the frame and the ScrolledHList widget
37 # at the top of the dialog box
38 #
39 top = Tix.Frame( w, relief=Tix.RAISED, bd=1)
40
41 # Put a simple hierachy into the HList (two levels). Use colors and
42 # separator widgets (frames) to make the list look fancy
43 #
44 top.a = Tix.ScrolledHList(top, options='hlist.columns 3 hlist.header 1' )
45 top.a.pack( expand=1, fill=Tix.BOTH, padx=10, pady=10, side=Tix.TOP)
46
47 hlist=top.a.hlist
48
49 # Create the title for the HList widget
50 # >> Notice that we have set the hlist.header subwidget option to true
51 # so that the header is displayed
52 #
53
54 boldfont=hlist.tk.call('tix','option','get','bold_font')
55
56 # First some styles for the headers
57 style={}
58 style['header'] = Tix.DisplayStyle(Tix.TEXT, refwindow=hlist,
59 anchor=Tix.CENTER, padx=8, pady=2, font = boldfont )
60
61 hlist.header_create(0, itemtype=Tix.TEXT, text='Name',
62 style=style['header'])
63 hlist.header_create(1, itemtype=Tix.TEXT, text='Position',
64 style=style['header'])
65
66 # Notice that we use 3 columns in the hlist widget. This way when the user
67 # expands the windows wide, the right side of the header doesn't look
68 # chopped off. The following line ensures that the 3 column header is
69 # not shown unless the hlist window is wider than its contents.
70 #
71 hlist.column_width(2,0)
72
73 # This is our little relational database
74 #
75 boss = ('doe', 'John Doe', 'Director')
76
77 managers = [
78 ('jeff', 'Jeff Waxman', 'Manager'),
79 ('john', 'John Lee', 'Manager'),
80 ('peter', 'Peter Kenson', 'Manager')
81 ]
82
83 employees = [
84 ('alex', 'john', 'Alex Kellman', 'Clerk'),
85 ('alan', 'john', 'Alan Adams', 'Clerk'),
86 ('andy', 'peter', 'Andreas Crawford', 'Salesman'),
87 ('doug', 'jeff', 'Douglas Bloom', 'Clerk'),
88 ('jon', 'peter', 'Jon Baraki', 'Salesman'),
89 ('chris', 'jeff', 'Chris Geoffrey', 'Clerk'),
90 ('chuck', 'jeff', 'Chuck McLean', 'Cleaner')
91 ]
92
93 style['mgr_name'] = Tix.DisplayStyle(Tix.TEXT, refwindow=hlist)
94
95 style['mgr_posn'] = Tix.DisplayStyle(Tix.TEXT, padx=8, refwindow=hlist)
96
97 style['empl_name'] = Tix.DisplayStyle(Tix.TEXT, refwindow=hlist)
98
99 style['empl_posn'] = Tix.DisplayStyle(Tix.TEXT, padx=8, refwindow=hlist)
100
101 # Let configure the appearance of the HList subwidget
102 #
103 hlist.config(separator='.', width=25, drawbranch=0, indent=10)
104 hlist.column_width(0, chars=20)
105
106 # Create the boss
107 #
108 hlist.add ('.', itemtype=Tix.TEXT, text=boss[1],
109 style=style['mgr_name'])
110 hlist.item_create('.', 1, itemtype=Tix.TEXT, text=boss[2],
111 style=style['mgr_posn'])
112
113 # Create the managers
114 #
115
116 for key,name,posn in managers :
117 e= '.'+ key
118 hlist.add(e, itemtype=Tix.TEXT, text=name,
119 style=style['mgr_name'])
120 hlist.item_create(e, 1, itemtype=Tix.TEXT, text=posn,
121 style=style['mgr_posn'])
122
123
124 for key,mgr,name,posn in employees :
125 # "." is the separator character we chose above
126
127 entrypath = '.' + mgr + '.' + key
128
129 # ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
130 # parent entryPath / child's name
131
132 hlist.add(entrypath, text=name, style=style['empl_name'])
133 hlist.item_create(entrypath, 1, itemtype=Tix.TEXT,
134 text = posn, style = style['empl_posn'] )
135
136
137 # Use a ButtonBox to hold the buttons.
138 #
139 box= Tix.ButtonBox(top, orientation=Tix.HORIZONTAL )
140 box.add( 'ok', text='Ok', underline=0, width=6,
141 command = self.okcmd )
142
143 box.add( 'cancel', text='Cancel', underline=0, width=6,
144 command = self.quitcmd )
145
146 box.pack( side=Tix.BOTTOM, fill=Tix.X)
147 top.pack( side=Tix.TOP, fill=Tix.BOTH, expand=1 )
148
149 def okcmd (self):
150 self.quitcmd()
151
152 def quitcmd (self):
153 self.exit = 0
154
155 def mainloop(self):
156 while self.exit < 0:
157 self.root.tk.dooneevent(TCL_ALL_EVENTS)
158
159 def destroy (self):
160 self.root.destroy()
161
162
163# This "if" statement makes it possible to run this script file inside or
164# outside of the main demo program "tixwidgets.py".
165#
166if __name__== '__main__' :
167 root=Tix.Tk()
168 RunSample(root)
sys/src/cmd/python/Demo/tix/samples/Tree.py+80−0
@@ -0,0 +1,80 @@
1# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
2#
3# $Id: Tree.py 36560 2004-07-18 06:16:08Z tim_one $
4#
5# Tix Demostration Program
6#
7# This sample program is structured in such a way so that it can be
8# executed from the Tix demo program "tixwidgets.py": it must have a
9# procedure called "RunSample". It should also have the "if" statment
10# at the end of this file so that it can be run as a standalone
11# program.
12
13# This file demonstrates how to use the TixTree widget to display
14# dynamic hierachical data (the files in the Unix file system)
15#
16
17import Tix, os
18
19def RunSample(w):
20 top = Tix.Frame(w, relief=Tix.RAISED, bd=1)
21 tree = Tix.Tree(top, options='separator "/"')
22 tree.pack(expand=1, fill=Tix.BOTH, padx=10, pady=10, side=Tix.LEFT)
23 tree['opencmd'] = lambda dir=None, w=tree: opendir(w, dir)
24
25 # The / directory is added in the "open" mode. The user can open it
26 # and then browse its subdirectories ...
27 adddir(tree, "/")
28
29 box = Tix.ButtonBox(w, orientation=Tix.HORIZONTAL)
30 box.add('ok', text='Ok', underline=0, command=w.destroy, width=6)
31 box.add('cancel', text='Cancel', underline=0, command=w.destroy, width=6)
32 box.pack(side=Tix.BOTTOM, fill=Tix.X)
33 top.pack(side=Tix.TOP, fill=Tix.BOTH, expand=1)
34
35def adddir(tree, dir):
36 if dir == '/':
37 text = '/'
38 else:
39 text = os.path.basename(dir)
40 tree.hlist.add(dir, itemtype=Tix.IMAGETEXT, text=text,
41 image=tree.tk.call('tix', 'getimage', 'folder'))
42 try:
43 os.listdir(dir)
44 tree.setmode(dir, 'open')
45 except os.error:
46 # No read permission ?
47 pass
48
49# This function is called whenever the user presses the (+) indicator or
50# double clicks on a directory whose mode is "open". It loads the files
51# inside that directory into the Tree widget.
52#
53# Note we didn't specify the closecmd option for the Tree widget, so it
54# performs the default action when the user presses the (-) indicator or
55# double clicks on a directory whose mode is "close": hide all of its child
56# entries
57def opendir(tree, dir):
58 entries = tree.hlist.info_children(dir)
59 if entries:
60 # We have already loaded this directory. Let's just
61 # show all the child entries
62 #
63 # Note: since we load the directory only once, it will not be
64 # refreshed if the you add or remove files from this
65 # directory.
66 #
67 for entry in entries:
68 tree.hlist.show_entry(entry)
69 files = os.listdir(dir)
70 for file in files:
71 if os.path.isdir(dir + '/' + file):
72 adddir(tree, dir + '/' + file)
73 else:
74 tree.hlist.add(dir + '/' + file, itemtype=Tix.IMAGETEXT, text=file,
75 image=tree.tk.call('tix', 'getimage', 'file'))
76
77if __name__ == '__main__':
78 root = Tix.Tk()
79 RunSample(root)
80 root.mainloop()
sys/src/cmd/python/Demo/tix/tixwidgets.py+1003−0
@@ -0,0 +1,1003 @@
1# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
2#
3# $Id: tixwidgets.py 36560 2004-07-18 06:16:08Z tim_one $
4#
5# tixwidgets.py --
6#
7# For Tix, see http://tix.sourceforge.net
8#
9# This is a demo program of some of the Tix widgets available in Python.
10# If you have installed Python & Tix properly, you can execute this as
11#
12# % python tixwidgets.py
13#
14
15import os, os.path, sys, Tix
16from Tkconstants import *
17import traceback, tkMessageBox
18
19TCL_DONT_WAIT = 1<<1
20TCL_WINDOW_EVENTS = 1<<2
21TCL_FILE_EVENTS = 1<<3
22TCL_TIMER_EVENTS = 1<<4
23TCL_IDLE_EVENTS = 1<<5
24TCL_ALL_EVENTS = 0
25
26class Demo:
27 def __init__(self, top):
28 self.root = top
29 self.exit = -1
30
31 self.dir = None # script directory
32 self.balloon = None # balloon widget
33 self.useBalloons = Tix.StringVar()
34 self.useBalloons.set('0')
35 self.statusbar = None # status bar widget
36 self.welmsg = None # Msg widget
37 self.welfont = '' # font name
38 self.welsize = '' # font size
39
40 progname = sys.argv[0]
41 dirname = os.path.dirname(progname)
42 if dirname and dirname != os.curdir:
43 self.dir = dirname
44 index = -1
45 for i in range(len(sys.path)):
46 p = sys.path[i]
47 if p in ("", os.curdir):
48 index = i
49 if index >= 0:
50 sys.path[index] = dirname
51 else:
52 sys.path.insert(0, dirname)
53 else:
54 self.dir = os.getcwd()
55 sys.path.insert(0, self.dir+'/samples')
56
57 def MkMainMenu(self):
58 top = self.root
59 w = Tix.Frame(top, bd=2, relief=RAISED)
60 file = Tix.Menubutton(w, text='File', underline=0, takefocus=0)
61 help = Tix.Menubutton(w, text='Help', underline=0, takefocus=0)
62 file.pack(side=LEFT)
63 help.pack(side=RIGHT)
64 fm = Tix.Menu(file, tearoff=0)
65 file['menu'] = fm
66 hm = Tix.Menu(help, tearoff=0)
67 help['menu'] = hm
68
69 fm.add_command(label='Exit', underline=1,
70 command = lambda self=self: self.quitcmd () )
71 hm.add_checkbutton(label='BalloonHelp', underline=0, command=ToggleHelp,
72 variable=self.useBalloons)
73 # The trace variable option doesn't seem to work, instead I use 'command'
74 #apply(w.tk.call, ('trace', 'variable', self.useBalloons, 'w',
75 # ToggleHelp))
76
77 return w
78
79 def MkMainNotebook(self):
80 top = self.root
81 w = Tix.NoteBook(top, ipadx=5, ipady=5, options="""
82 tagPadX 6
83 tagPadY 4
84 borderWidth 2
85 """)
86 # This may be required if there is no *Background option
87 top['bg'] = w['bg']
88
89 w.add('wel', label='Welcome', underline=0,
90 createcmd=lambda w=w, name='wel': MkWelcome(w, name))
91 w.add('cho', label='Choosers', underline=0,
92 createcmd=lambda w=w, name='cho': MkChoosers(w, name))
93 w.add('scr', label='Scrolled Widgets', underline=0,
94 createcmd=lambda w=w, name='scr': MkScroll(w, name))
95 w.add('mgr', label='Manager Widgets', underline=0,
96 createcmd=lambda w=w, name='mgr': MkManager(w, name))
97 w.add('dir', label='Directory List', underline=0,
98 createcmd=lambda w=w, name='dir': MkDirList(w, name))
99 w.add('exp', label='Run Sample Programs', underline=0,
100 createcmd=lambda w=w, name='exp': MkSample(w, name))
101 return w
102
103 def MkMainStatus(self):
104 global demo
105 top = self.root
106
107 w = Tix.Frame(top, relief=Tix.RAISED, bd=1)
108 demo.statusbar = Tix.Label(w, relief=Tix.SUNKEN, bd=1)
109 demo.statusbar.form(padx=3, pady=3, left=0, right='%70')
110 return w
111
112 def build(self):
113 root = self.root
114 z = root.winfo_toplevel()
115 z.wm_title('Tix Widget Demonstration')
116 if z.winfo_screenwidth() <= 800:
117 z.geometry('790x590+10+10')
118 else:
119 z.geometry('890x640+10+10')
120 demo.balloon = Tix.Balloon(root)
121 frame1 = self.MkMainMenu()
122 frame2 = self.MkMainNotebook()
123 frame3 = self.MkMainStatus()
124 frame1.pack(side=TOP, fill=X)
125 frame3.pack(side=BOTTOM, fill=X)
126 frame2.pack(side=TOP, expand=1, fill=BOTH, padx=4, pady=4)
127 demo.balloon['statusbar'] = demo.statusbar
128 z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
129
130 # To show Tcl errors - uncomment this to see the listbox bug.
131 # Tkinter defines a Tcl tkerror procedure that in effect
132 # silences all background Tcl error reporting.
133 # root.tk.eval('if {[info commands tkerror] != ""} {rename tkerror pytkerror}')
134 def quitcmd (self):
135 """Quit our mainloop. It is up to you to call root.destroy() after."""
136 self.exit = 0
137
138 def loop(self):
139 """This is an explict replacement for _tkinter mainloop()
140 It lets you catch keyboard interrupts easier, and avoids
141 the 20 msec. dead sleep() which burns a constant CPU."""
142 while self.exit < 0:
143 # There are 2 whiles here. The outer one lets you continue
144 # after a ^C interrupt.
145 try:
146 # This is the replacement for _tkinter mainloop()
147 # It blocks waiting for the next Tcl event using select.
148 while self.exit < 0:
149 self.root.tk.dooneevent(TCL_ALL_EVENTS)
150 except SystemExit:
151 # Tkinter uses SystemExit to exit
152 #print 'Exit'
153 self.exit = 1
154 return
155 except KeyboardInterrupt:
156 if tkMessageBox.askquestion ('Interrupt', 'Really Quit?') == 'yes':
157 # self.tk.eval('exit')
158 self.exit = 1
159 return
160 continue
161 except:
162 # Otherwise it's some other error - be nice and say why
163 t, v, tb = sys.exc_info()
164 text = ""
165 for line in traceback.format_exception(t,v,tb):
166 text += line + '\n'
167 try: tkMessageBox.showerror ('Error', text)
168 except: pass
169 self.exit = 1
170 raise SystemExit, 1
171
172 def destroy (self):
173 self.root.destroy()
174
175def RunMain(root):
176 global demo
177
178 demo = Demo(root)
179
180 demo.build()
181 demo.loop()
182 demo.destroy()
183
184# Tabs
185def MkWelcome(nb, name):
186 w = nb.page(name)
187 bar = MkWelcomeBar(w)
188 text = MkWelcomeText(w)
189 bar.pack(side=TOP, fill=X, padx=2, pady=2)
190 text.pack(side=TOP, fill=BOTH, expand=1)
191
192def MkWelcomeBar(top):
193 global demo
194
195 w = Tix.Frame(top, bd=2, relief=Tix.GROOVE)
196 b1 = Tix.ComboBox(w, command=lambda w=top: MainTextFont(w))
197 b2 = Tix.ComboBox(w, command=lambda w=top: MainTextFont(w))
198 b1.entry['width'] = 15
199 b1.slistbox.listbox['height'] = 3
200 b2.entry['width'] = 4
201 b2.slistbox.listbox['height'] = 3
202
203 demo.welfont = b1
204 demo.welsize = b2
205
206 b1.insert(Tix.END, 'Courier')
207 b1.insert(Tix.END, 'Helvetica')
208 b1.insert(Tix.END, 'Lucida')
209 b1.insert(Tix.END, 'Times Roman')
210
211 b2.insert(Tix.END, '8')
212 b2.insert(Tix.END, '10')
213 b2.insert(Tix.END, '12')
214 b2.insert(Tix.END, '14')
215 b2.insert(Tix.END, '18')
216
217 b1.pick(1)
218 b2.pick(3)
219
220 b1.pack(side=Tix.LEFT, padx=4, pady=4)
221 b2.pack(side=Tix.LEFT, padx=4, pady=4)
222
223 demo.balloon.bind_widget(b1, msg='Choose\na font',
224 statusmsg='Choose a font for this page')
225 demo.balloon.bind_widget(b2, msg='Point size',
226 statusmsg='Choose the font size for this page')
227 return w
228
229def MkWelcomeText(top):
230 global demo
231
232 w = Tix.ScrolledWindow(top, scrollbar='auto')
233 win = w.window
234 text = 'Welcome to TIX in Python'
235 title = Tix.Label(win,
236 bd=0, width=30, anchor=Tix.N, text=text)
237 msg = Tix.Message(win,
238 bd=0, width=400, anchor=Tix.N,
239 text='Tix is a set of mega-widgets based on TK. This program \
240demonstrates the widgets in the Tix widget set. You can choose the pages \
241in this window to look at the corresponding widgets. \n\n\
242To quit this program, choose the "File | Exit" command.\n\n\
243For more information, see http://tix.sourceforge.net.')
244 title.pack(expand=1, fill=Tix.BOTH, padx=10, pady=10)
245 msg.pack(expand=1, fill=Tix.BOTH, padx=10, pady=10)
246 demo.welmsg = msg
247 return w
248
249def MainTextFont(w):
250 global demo
251
252 if not demo.welmsg:
253 return
254 font = demo.welfont['value']
255 point = demo.welsize['value']
256 if font == 'Times Roman':
257 font = 'times'
258 fontstr = '%s %s' % (font, point)
259 demo.welmsg['font'] = fontstr
260
261def ToggleHelp():
262 if demo.useBalloons.get() == '1':
263 demo.balloon['state'] = 'both'
264 else:
265 demo.balloon['state'] = 'none'
266
267def MkChoosers(nb, name):
268 w = nb.page(name)
269 options = "label.padX 4"
270
271 til = Tix.LabelFrame(w, label='Chooser Widgets', options=options)
272 cbx = Tix.LabelFrame(w, label='tixComboBox', options=options)
273 ctl = Tix.LabelFrame(w, label='tixControl', options=options)
274 sel = Tix.LabelFrame(w, label='tixSelect', options=options)
275 opt = Tix.LabelFrame(w, label='tixOptionMenu', options=options)
276 fil = Tix.LabelFrame(w, label='tixFileEntry', options=options)
277 fbx = Tix.LabelFrame(w, label='tixFileSelectBox', options=options)
278 tbr = Tix.LabelFrame(w, label='Tool Bar', options=options)
279
280 MkTitle(til.frame)
281 MkCombo(cbx.frame)
282 MkControl(ctl.frame)
283 MkSelect(sel.frame)
284 MkOptMenu(opt.frame)
285 MkFileEnt(fil.frame)
286 MkFileBox(fbx.frame)
287 MkToolBar(tbr.frame)
288
289 # First column: comBox and selector
290 cbx.form(top=0, left=0, right='%33')
291 sel.form(left=0, right='&'+str(cbx), top=cbx)
292 opt.form(left=0, right='&'+str(cbx), top=sel, bottom=-1)
293
294 # Second column: title .. etc
295 til.form(left=cbx, top=0,right='%66')
296 ctl.form(left=cbx, right='&'+str(til), top=til)
297 fil.form(left=cbx, right='&'+str(til), top=ctl)
298 tbr.form(left=cbx, right='&'+str(til), top=fil, bottom=-1)
299
300 #
301 # Third column: file selection
302 fbx.form(right=-1, top=0, left='%66')
303
304def MkCombo(w):
305 options="label.width %d label.anchor %s entry.width %d" % (10, Tix.E, 14)
306
307 static = Tix.ComboBox(w, label='Static', editable=0, options=options)
308 editable = Tix.ComboBox(w, label='Editable', editable=1, options=options)
309 history = Tix.ComboBox(w, label='History', editable=1, history=1,
310 anchor=Tix.E, options=options)
311 static.insert(Tix.END, 'January')
312 static.insert(Tix.END, 'February')
313 static.insert(Tix.END, 'March')
314 static.insert(Tix.END, 'April')
315 static.insert(Tix.END, 'May')
316 static.insert(Tix.END, 'June')
317 static.insert(Tix.END, 'July')
318 static.insert(Tix.END, 'August')
319 static.insert(Tix.END, 'September')
320 static.insert(Tix.END, 'October')
321 static.insert(Tix.END, 'November')
322 static.insert(Tix.END, 'December')
323
324 editable.insert(Tix.END, 'Angola')
325 editable.insert(Tix.END, 'Bangladesh')
326 editable.insert(Tix.END, 'China')
327 editable.insert(Tix.END, 'Denmark')
328 editable.insert(Tix.END, 'Ecuador')
329
330 history.insert(Tix.END, '/usr/bin/ksh')
331 history.insert(Tix.END, '/usr/local/lib/python')
332 history.insert(Tix.END, '/var/adm')
333
334 static.pack(side=Tix.TOP, padx=5, pady=3)
335 editable.pack(side=Tix.TOP, padx=5, pady=3)
336 history.pack(side=Tix.TOP, padx=5, pady=3)
337
338states = ['Bengal', 'Delhi', 'Karnataka', 'Tamil Nadu']
339
340def spin_cmd(w, inc):
341 idx = states.index(demo_spintxt.get()) + inc
342 if idx < 0:
343 idx = len(states) - 1
344 elif idx >= len(states):
345 idx = 0
346# following doesn't work.
347# return states[idx]
348 demo_spintxt.set(states[idx]) # this works
349
350def spin_validate(w):
351 global states, demo_spintxt
352
353 try:
354 i = states.index(demo_spintxt.get())
355 except ValueError:
356 return states[0]
357 return states[i]
358 # why this procedure works as opposed to the previous one beats me.
359
360def MkControl(w):
361 global demo_spintxt
362
363 options="label.width %d label.anchor %s entry.width %d" % (10, Tix.E, 13)
364
365 demo_spintxt = Tix.StringVar()
366 demo_spintxt.set(states[0])
367 simple = Tix.Control(w, label='Numbers', options=options)
368 spintxt = Tix.Control(w, label='States', variable=demo_spintxt,
369 options=options)
370 spintxt['incrcmd'] = lambda w=spintxt: spin_cmd(w, 1)
371 spintxt['decrcmd'] = lambda w=spintxt: spin_cmd(w, -1)
372 spintxt['validatecmd'] = lambda w=spintxt: spin_validate(w)
373
374 simple.pack(side=Tix.TOP, padx=5, pady=3)
375 spintxt.pack(side=Tix.TOP, padx=5, pady=3)
376
377def MkSelect(w):
378 options = "label.anchor %s" % Tix.CENTER
379
380 sel1 = Tix.Select(w, label='Mere Mortals', allowzero=1, radio=1,
381 orientation=Tix.VERTICAL,
382 labelside=Tix.TOP,
383 options=options)
384 sel2 = Tix.Select(w, label='Geeks', allowzero=1, radio=0,
385 orientation=Tix.VERTICAL,
386 labelside= Tix.TOP,
387 options=options)
388
389 sel1.add('eat', text='Eat')
390 sel1.add('work', text='Work')
391 sel1.add('play', text='Play')
392 sel1.add('party', text='Party')
393 sel1.add('sleep', text='Sleep')
394
395 sel2.add('eat', text='Eat')
396 sel2.add('prog1', text='Program')
397 sel2.add('prog2', text='Program')
398 sel2.add('prog3', text='Program')
399 sel2.add('sleep', text='Sleep')
400
401 sel1.pack(side=Tix.LEFT, padx=5, pady=3, fill=Tix.X)
402 sel2.pack(side=Tix.LEFT, padx=5, pady=3, fill=Tix.X)
403
404def MkOptMenu(w):
405 options='menubutton.width 15 label.anchor %s' % Tix.E
406
407 m = Tix.OptionMenu(w, label='File Format : ', options=options)
408 m.add_command('text', label='Plain Text')
409 m.add_command('post', label='PostScript')
410 m.add_command('format', label='Formatted Text')
411 m.add_command('html', label='HTML')
412 m.add_command('sep')
413 m.add_command('tex', label='LaTeX')
414 m.add_command('rtf', label='Rich Text Format')
415
416 m.pack(fill=Tix.X, padx=5, pady=3)
417
418def MkFileEnt(w):
419 msg = Tix.Message(w,
420 relief=Tix.FLAT, width=240, anchor=Tix.N,
421 text='Press the "open file" icon button and a TixFileSelectDialog will popup.')
422 ent = Tix.FileEntry(w, label='Select a file : ')
423 msg.pack(side=Tix.TOP, expand=1, fill=Tix.BOTH, padx=3, pady=3)
424 ent.pack(side=Tix.TOP, fill=Tix.X, padx=3, pady=3)
425
426def MkFileBox(w):
427 """The FileSelectBox is a Motif-style box with various enhancements.
428 For example, you can adjust the size of the two listboxes
429 and your past selections are recorded.
430 """
431 msg = Tix.Message(w,
432 relief=Tix.FLAT, width=240, anchor=Tix.N,
433 text='The Tix FileSelectBox is a Motif-style box with various enhancements. For example, you can adjust the size of the two listboxes and your past selections are recorded.')
434 box = Tix.FileSelectBox(w)
435 msg.pack(side=Tix.TOP, expand=1, fill=Tix.BOTH, padx=3, pady=3)
436 box.pack(side=Tix.TOP, fill=Tix.X, padx=3, pady=3)
437
438def MkToolBar(w):
439 """The Select widget is also good for arranging buttons in a tool bar.
440 """
441 global demo
442
443 options='frame.borderWidth 1'

560 more lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/README+10−0

This diff is large: its 11 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/AttrDialog.py+452−0

This diff is large: its 453 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/ManPage.py+220−0

This diff is large: its 221 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/MimeViewer.py+143−0

This diff is large: its 144 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/ShellWindow.py+151−0

This diff is large: its 152 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/brownian.py+50−0

This diff is large: its 51 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/canvasevents.py+244−0

This diff is large: its 245 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/dialog.py+109−0

This diff is large: its 110 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/electrons.py+91−0

This diff is large: its 92 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/hanoi.py+154−0

This diff is large: its 155 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/hello.py+17−0

This diff is large: its 18 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/imagedraw.py+23−0

This diff is large: its 24 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/imageview.py+12−0

This diff is large: its 13 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/kill.py+98−0

This diff is large: its 99 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/listtree.py+37−0

This diff is large: its 38 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/mbox.py+285−0

This diff is large: its 286 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/newmenubardemo.py+47−0

This diff is large: its 48 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/optionmenu.py+27−0

This diff is large: its 28 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/paint.py+60−0

This diff is large: its 61 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/rmt.py+159−0

This diff is large: its 160 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/solitaire.py+637−0

This diff is large: its 638 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/sortvisu.py+634−0

This diff is large: its 635 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/ss1.py+845−0

This diff is large: its 846 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/svkill.py+128−0

This diff is large: its 129 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/switch.py+55−0

This diff is large: its 56 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/tkman.py+267−0

This diff is large: its 268 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/guido/wish.py+27−0

This diff is large: its 28 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/00-HELLO-WORLD.py+27−0

This diff is large: its 28 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/README+30−0

This diff is large: its 31 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/animation-simple.py+35−0

This diff is large: its 36 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/animation-w-velocity-ctrl.py+44−0

This diff is large: its 45 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/bind-w-mult-calls-p-type.py+44−0

This diff is large: its 45 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/canvas-demo-simple.py+28−0

This diff is large: its 29 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/canvas-gridding.py+61−0

This diff is large: its 62 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/canvas-moving-or-creating.py+62−0

This diff is large: its 63 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/canvas-moving-w-mouse.py+55−0

This diff is large: its 56 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/canvas-mult-item-sel.py+78−0

This diff is large: its 79 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/canvas-reading-tag-info.py+49−0

This diff is large: its 50 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/canvas-w-widget-draw-el.py+36−0

This diff is large: its 37 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/canvas-with-scrollbars.py+60−0

This diff is large: its 61 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/dialog-box.py+64−0

This diff is large: its 65 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/entry-simple.py+24−0

This diff is large: its 25 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/entry-with-shared-variable.py+46−0

This diff is large: its 47 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/killing-window-w-wm.py+42−0

This diff is large: its 43 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/menu-all-types-of-entries.py+244−0

This diff is large: its 245 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/menu-simple.py+112−0

This diff is large: its 113 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/not-what-you-might-think-1.py+28−0

This diff is large: its 29 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/not-what-you-might-think-2.py+30−0

This diff is large: its 31 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/packer-and-placer-together.py+41−0

This diff is large: its 42 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/packer-simple.py+32−0

This diff is large: its 33 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/placer-simple.py+39−0

This diff is large: its 40 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/pong-demo-1.py+54−0

This diff is large: its 55 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/printing-coords-of-items.py+61−0

This diff is large: its 62 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/radiobutton-simple.py+62−0

This diff is large: its 63 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/rubber-band-box-demo-1.py+58−0

This diff is large: its 59 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/rubber-line-demo-1.py+51−0

This diff is large: its 52 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/slider-demo-1.py+36−0

This diff is large: its 37 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/subclass-existing-widgets.py+28−0

This diff is large: its 29 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/two-radio-groups.py+110−0

This diff is large: its 111 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/window-creation-more.py+35−0

This diff is large: its 36 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/window-creation-simple.py+31−0

This diff is large: its 32 lines aren’t shown here.

sys/src/cmd/python/Demo/tkinter/matt/window-creation-w-location.py+45−0

This diff is large: its 46 lines aren’t shown here.

sys/src/cmd/python/Demo/xml/elem_count.py+36−0

This diff is large: its 37 lines aren’t shown here.

sys/src/cmd/python/Demo/xml/roundtrip.py+45−0

This diff is large: its 46 lines aren’t shown here.

sys/src/cmd/python/Demo/xml/rss2html.py+91−0

This diff is large: its 92 lines aren’t shown here.

sys/src/cmd/python/Demo/zlib/minigzip.py+133−0

This diff is large: its 134 lines aren’t shown here.

sys/src/cmd/python/Demo/zlib/zlibdemo.py+48−0

This diff is large: its 49 lines aren’t shown here.

sys/src/cmd/python/Demo/zlib/zlibdemo.py.gz+0−0

Binary file not shown.

sys/src/cmd/python/Doc/ACKS+202−0

This diff is large: its 203 lines aren’t shown here.

sys/src/cmd/python/Doc/Makefile+736−0

This diff is large: its 737 lines aren’t shown here.

sys/src/cmd/python/Doc/Makefile.deps+386−0

This diff is large: its 387 lines aren’t shown here.

sys/src/cmd/python/Doc/README+246−0

This diff is large: its 247 lines aren’t shown here.

sys/src/cmd/python/Doc/TODO+74−0

This diff is large: its 75 lines aren’t shown here.

sys/src/cmd/python/Doc/api/abstract.tex+1057−0

This diff is large: its 1058 lines aren’t shown here.

sys/src/cmd/python/Doc/api/api.tex+60−0

This diff is large: its 61 lines aren’t shown here.

sys/src/cmd/python/Doc/api/concrete.tex+3203−0

This diff is large: its 3204 lines aren’t shown here.

sys/src/cmd/python/Doc/api/exceptions.tex+442−0

This diff is large: its 443 lines aren’t shown here.

sys/src/cmd/python/Doc/api/init.tex+884−0

This diff is large: its 885 lines aren’t shown here.

sys/src/cmd/python/Doc/api/intro.tex+627−0

This diff is large: its 628 lines aren’t shown here.

sys/src/cmd/python/Doc/api/memory.tex+204−0

This diff is large: its 205 lines aren’t shown here.

sys/src/cmd/python/Doc/api/newtypes.tex+1780−0

This diff is large: its 1781 lines aren’t shown here.

sys/src/cmd/python/Doc/api/refcounting.tex+69−0

This diff is large: its 70 lines aren’t shown here.

sys/src/cmd/python/Doc/api/refcounts.dat+1756−0

This diff is large: its 1757 lines aren’t shown here.

sys/src/cmd/python/Doc/api/utilities.tex+1023−0

This diff is large: its 1024 lines aren’t shown here.

sys/src/cmd/python/Doc/api/veryhigh.tex+287−0

This diff is large: its 288 lines aren’t shown here.

sys/src/cmd/python/Doc/commontex/boilerplate.tex+9−0

This diff is large: its 10 lines aren’t shown here.

sys/src/cmd/python/Doc/commontex/copyright.tex+14−0

This diff is large: its 15 lines aren’t shown here.

sys/src/cmd/python/Doc/commontex/license.tex+673−0

This diff is large: its 674 lines aren’t shown here.

sys/src/cmd/python/Doc/commontex/reportingbugs.tex+61−0

This diff is large: its 62 lines aren’t shown here.

sys/src/cmd/python/Doc/commontex/typestruct.h+76−0

This diff is large: its 77 lines aren’t shown here.

sys/src/cmd/python/Doc/dist/dist.tex+3795−0

This diff is large: its 3796 lines aren’t shown here.

sys/src/cmd/python/Doc/dist/sysconfig.tex+113−0

This diff is large: its 114 lines aren’t shown here.

sys/src/cmd/python/Doc/doc/doc.tex+2129−0

This diff is large: its 2130 lines aren’t shown here.

sys/src/cmd/python/Doc/ext/building.tex+143−0

This diff is large: its 144 lines aren’t shown here.

sys/src/cmd/python/Doc/ext/embedding.tex+316−0

This diff is large: its 317 lines aren’t shown here.

sys/src/cmd/python/Doc/ext/ext.tex+67−0

This diff is large: its 68 lines aren’t shown here.

sys/src/cmd/python/Doc/ext/extending.tex+1390−0

This diff is large: its 1391 lines aren’t shown here.

sys/src/cmd/python/Doc/ext/newtypes.tex+1765−0

This diff is large: its 1766 lines aren’t shown here.

sys/src/cmd/python/Doc/ext/noddy.c+54−0

This diff is large: its 55 lines aren’t shown here.

sys/src/cmd/python/Doc/ext/noddy2.c+190−0

This diff is large: its 191 lines aren’t shown here.

sys/src/cmd/python/Doc/ext/noddy3.c+243−0

This diff is large: its 244 lines aren’t shown here.

sys/src/cmd/python/Doc/ext/noddy4.c+224−0

This diff is large: its 225 lines aren’t shown here.

sys/src/cmd/python/Doc/ext/run-func.c+68−0

This diff is large: its 69 lines aren’t shown here.

sys/src/cmd/python/Doc/ext/setup.py+8−0

This diff is large: its 9 lines aren’t shown here.

sys/src/cmd/python/Doc/ext/shoddy.c+91−0

This diff is large: its 92 lines aren’t shown here.

sys/src/cmd/python/Doc/ext/test.py+213−0

This diff is large: its 214 lines aren’t shown here.

sys/src/cmd/python/Doc/ext/windows.tex+320−0

This diff is large: its 321 lines aren’t shown here.

sys/src/cmd/python/Doc/howto/Makefile+84−0

This diff is large: its 85 lines aren’t shown here.

sys/src/cmd/python/Doc/howto/TODO+13−0

This diff is large: its 14 lines aren’t shown here.

sys/src/cmd/python/Doc/howto/advocacy.tex+411−0

This diff is large: its 412 lines aren’t shown here.

sys/src/cmd/python/Doc/howto/curses.tex+485−0

This diff is large: its 486 lines aren’t shown here.

sys/src/cmd/python/Doc/howto/doanddont.tex+344−0

This diff is large: its 345 lines aren’t shown here.

sys/src/cmd/python/Doc/howto/regex.tex+1463−0

This diff is large: its 1464 lines aren’t shown here.

sys/src/cmd/python/Doc/howto/sockets.tex+465−0

This diff is large: its 466 lines aren’t shown here.

sys/src/cmd/python/Doc/howto/unicode.rst+766−0

This diff is large: its 767 lines aren’t shown here.

sys/src/cmd/python/Doc/howto/urllib2.rst+598−0

This diff is large: its 599 lines aren’t shown here.

sys/src/cmd/python/Doc/html/about.dat+24−0

This diff is large: its 25 lines aren’t shown here.

sys/src/cmd/python/Doc/html/about.html+84−0

This diff is large: its 85 lines aren’t shown here.

sys/src/cmd/python/Doc/html/icons/blank.gif+0−0

Binary file not shown.

sys/src/cmd/python/Doc/html/icons/blank.png+0−0

Binary file not shown.

sys/src/cmd/python/Doc/html/icons/contents.gif+0−0

Binary file not shown.

sys/src/cmd/python/Doc/html/icons/contents.png+0−0

Binary file not shown.

sys/src/cmd/python/Doc/html/icons/index.gif+0−0

Binary file not shown.

sys/src/cmd/python/Doc/html/icons/index.png+0−0

Binary file not shown.

sys/src/cmd/python/Doc/html/icons/modules.gif+0−0

Binary file not shown.

sys/src/cmd/python/Doc/html/icons/modules.png+0−0

Binary file not shown.

sys/src/cmd/python/Doc/html/icons/next.gif+0−0

Binary file not shown.

sys/src/cmd/python/Doc/html/icons/next.png+0−0

Binary file not shown.

sys/src/cmd/python/Doc/html/icons/previous.gif+0−0

Binary file not shown.

sys/src/cmd/python/Doc/html/icons/previous.png+0−0

Binary file not shown.

sys/src/cmd/python/Doc/html/icons/pyfav.gif+0−0

Binary file not shown.

sys/src/cmd/python/Doc/html/icons/pyfav.png+0−0

Binary file not shown.

sys/src/cmd/python/Doc/html/icons/up.gif+0−0

Binary file not shown.

sys/src/cmd/python/Doc/html/icons/up.png+0−0

Binary file not shown.

sys/src/cmd/python/Doc/html/index.html.in+140−0

This diff is large: its 141 lines aren’t shown here.

sys/src/cmd/python/Doc/html/stdabout.dat+54−0

This diff is large: its 55 lines aren’t shown here.

sys/src/cmd/python/Doc/html/style.css+243−0

This diff is large: its 244 lines aren’t shown here.

sys/src/cmd/python/Doc/info/Makefile+82−0

This diff is large: its 83 lines aren’t shown here.

sys/src/cmd/python/Doc/info/README+21−0

This diff is large: its 22 lines aren’t shown here.

sys/src/cmd/python/Doc/info/python.dir+11−0

This diff is large: its 12 lines aren’t shown here.

sys/src/cmd/python/Doc/inst/inst.tex+1112−0

This diff is large: its 1113 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/archiving.tex+8−0

This diff is large: its 9 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/asttable.tex+283−0

This diff is large: its 284 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/caseless.py+60−0

This diff is large: its 61 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/compiler.tex+354−0

This diff is large: its 355 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/custominterp.tex+13−0

This diff is large: its 14 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/datatypes.tex+10−0

This diff is large: its 11 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/development.tex+13−0

This diff is large: its 14 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/distutils.tex+38−0

This diff is large: its 39 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/email-dir.py+115−0

This diff is large: its 116 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/email-mime.py+32−0

This diff is large: its 33 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/email-simple.py+25−0

This diff is large: its 26 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/email-unpack.py+68−0

This diff is large: its 69 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/email.tex+402−0

This diff is large: its 403 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/emailcharsets.tex+244−0

This diff is large: its 245 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/emailencoders.tex+47−0

This diff is large: its 48 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/emailexc.tex+87−0

This diff is large: its 88 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/emailgenerator.tex+133−0

This diff is large: its 134 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/emailheaders.tex+178−0

This diff is large: its 179 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/emailiter.tex+65−0

This diff is large: its 66 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/emailmessage.tex+561−0

This diff is large: its 562 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/emailmimebase.tex+186−0

This diff is large: its 187 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/emailparser.tex+208−0

This diff is large: its 209 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/emailutil.tex+157−0

This diff is large: its 158 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/fileformats.tex+7−0

This diff is large: its 8 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/filesys.tex+18−0

This diff is large: its 19 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/frameworks.tex+10−0

This diff is large: its 11 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/i18n.tex+11−0

This diff is large: its 12 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/internet.tex+13−0

This diff is large: its 14 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/ipc.tex+14−0

This diff is large: its 15 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/language.tex+10−0

This diff is large: its 11 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/lib.tex+487−0

This diff is large: its 488 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libaifc.tex+202−0

This diff is large: its 203 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libal.tex+181−0

This diff is large: its 182 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/liballos.tex+9−0

This diff is large: its 10 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libamoeba.tex+132−0

This diff is large: its 133 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libanydbm.tex+85−0

This diff is large: its 86 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libarray.tex+241−0

This diff is large: its 242 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libascii.tex+175−0

This diff is large: its 176 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libast.tex+57−0

This diff is large: its 58 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libasynchat.tex+254−0

This diff is large: its 255 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libasyncore.tex+260−0

This diff is large: its 261 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libatexit.tex+94−0

This diff is large: its 95 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libaudioop.tex+259−0

This diff is large: its 260 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libbase64.tex+169−0

This diff is large: its 170 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libbasehttp.tex+245−0

This diff is large: its 246 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libbastion.tex+57−0

This diff is large: its 58 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libbinascii.tex+147−0

This diff is large: its 148 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libbinhex.tex+55−0

This diff is large: its 56 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libbisect.tex+84−0

This diff is large: its 85 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libbltin.tex+44−0

This diff is large: its 45 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libbsddb.tex+208−0

This diff is large: its 209 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libbz2.tex+174−0

This diff is large: its 175 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcalendar.tex+304−0

This diff is large: its 305 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcd.tex+304−0

This diff is large: its 305 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcfgparser.tex+313−0

This diff is large: its 314 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcgi.tex+602−0

This diff is large: its 603 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcgihttp.tex+70−0

This diff is large: its 71 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcgitb.tex+67−0

This diff is large: its 68 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libchunk.tex+111−0

This diff is large: its 112 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcmath.tex+142−0

This diff is large: its 143 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcmd.tex+198−0

This diff is large: its 199 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcmp.tex+36−0

This diff is large: its 37 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcmpcache.tex+21−0

This diff is large: its 22 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcode.tex+173−0

This diff is large: its 174 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcodecs.tex+1348−0

This diff is large: its 1349 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcodeop.tex+103−0

This diff is large: its 104 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcollections.tex+341−0

This diff is large: its 342 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcolorsys.tex+54−0

This diff is large: its 55 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcommands.tex+62−0

This diff is large: its 63 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcompileall.tex+63−0

This diff is large: its 64 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libconsts.tex+31−0

This diff is large: its 32 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcontextlib.tex+130−0

This diff is large: its 131 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcookie.tex+260−0

This diff is large: its 261 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcookielib.tex+720−0

This diff is large: its 721 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcopy.tex+97−0

This diff is large: its 98 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcopyreg.tex+40−0

This diff is large: its 41 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcrypt.tex+54−0

This diff is large: its 55 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcrypto.tex+19−0

This diff is large: its 20 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcsv.tex+538−0

This diff is large: its 539 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libctypes.tex+2443−0

This diff is large: its 2444 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcurses.tex+1395−0

This diff is large: its 1396 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libcursespanel.tex+96−0

This diff is large: its 97 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libdatetime.tex+1441−0

This diff is large: its 1442 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libdbhash.tex+88−0

This diff is large: its 89 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libdbm.tex+61−0

This diff is large: its 62 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libdecimal.tex+1313−0

This diff is large: its 1314 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libdifflib.tex+704−0

This diff is large: its 705 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libdircache.tex+49−0

This diff is large: its 50 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libdis.tex+706−0

This diff is large: its 707 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libdl.tex+101−0

This diff is large: its 102 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libdoctest.tex+1949−0

This diff is large: its 1950 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libdocxmlrpc.tex+105−0

This diff is large: its 106 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libdumbdbm.tex+63−0

This diff is large: its 64 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libdummythread.tex+22−0

This diff is large: its 23 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libdummythreading.tex+22−0

This diff is large: its 23 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/liberrno.tex+149−0

This diff is large: its 150 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libetree.tex+356−0

This diff is large: its 357 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libexcs.tex+466−0

This diff is large: its 467 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libfcntl.tex+174−0

This diff is large: its 175 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libfilecmp.tex+142−0

This diff is large: its 143 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libfileinput.tex+192−0

This diff is large: its 193 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libfl.tex+507−0

This diff is large: its 508 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libfm.tex+94−0

This diff is large: its 95 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libfnmatch.tex+86−0

This diff is large: its 87 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libformatter.tex+329−0

This diff is large: its 330 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libfpectl.tex+127−0

This diff is large: its 128 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libfpformat.tex+54−0

This diff is large: its 55 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libftplib.tex+288−0

This diff is large: its 289 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libfuncs.tex+1321−0

This diff is large: its 1322 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libfunctools.tex+132−0

This diff is large: its 133 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libfuture.tex+69−0

This diff is large: its 70 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libgc.tex+196−0

This diff is large: its 197 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libgdbm.tex+100−0

This diff is large: its 101 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libgetopt.tex+154−0

This diff is large: its 155 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libgetpass.tex+36−0

This diff is large: its 37 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libgettext.tex+773−0

This diff is large: its 774 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libgl.tex+224−0

This diff is large: its 225 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libglob.tex+51−0

This diff is large: its 52 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libgopherlib.tex+36−0

This diff is large: its 37 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libgrp.tex+49−0

This diff is large: its 50 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libgzip.tex+70−0

This diff is large: its 71 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libhashlib.tex+114−0

This diff is large: its 115 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libheapq.tex+214−0

This diff is large: its 215 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libhmac.tex+54−0

This diff is large: its 55 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libhotshot.tex+137−0

This diff is large: its 138 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libhtmllib.tex+181−0

This diff is large: its 182 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libhtmlparser.tex+169−0

This diff is large: its 170 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libhttplib.tex+434−0

This diff is large: its 435 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libimageop.tex+100−0

This diff is large: its 101 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libimaplib.tex+507−0

This diff is large: its 508 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libimgfile.tex+66−0

This diff is large: its 67 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libimghdr.tex+60−0

This diff is large: its 61 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libimp.tex+291−0

This diff is large: its 292 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libinspect.tex+393−0

This diff is large: its 394 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libintro.tex+53−0

This diff is large: its 54 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libitertools.tex+546−0

This diff is large: its 547 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libjpeg.tex+80−0

This diff is large: its 81 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libkeyword.tex+20−0

This diff is large: its 21 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/liblinecache.tex+50−0

This diff is large: its 51 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/liblocale.tex+527−0

This diff is large: its 528 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/liblogging.tex+1729−0

This diff is large: its 1730 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libmailbox.tex+1444−0

This diff is large: its 1445 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libmailcap.tex+82−0

This diff is large: its 83 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libmain.tex+16−0

This diff is large: its 17 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libmarshal.tex+117−0

This diff is large: its 118 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libmath.tex+209−0

This diff is large: its 210 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libmd5.tex+92−0

This diff is large: its 93 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libmhlib.tex+168−0

This diff is large: its 169 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libmimetools.tex+120−0

This diff is large: its 121 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libmimetypes.tex+226−0

This diff is large: its 227 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libmimewriter.tex+80−0

This diff is large: its 81 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libmimify.tex+94−0

This diff is large: its 95 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libmisc.tex+7−0

This diff is large: its 8 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libmm.tex+8−0

This diff is large: its 9 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libmmap.tex+171−0

This diff is large: its 172 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libmodulefinder.tex+51−0

This diff is large: its 52 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libmsilib.tex+485−0

This diff is large: its 486 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libmsvcrt.tex+109−0

This diff is large: its 110 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libmultifile.tex+175−0

This diff is large: its 176 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libmutex.tex+57−0

This diff is large: its 58 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libnetrc.tex+68−0

This diff is large: its 69 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libnew.tex+63−0

This diff is large: its 64 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libni.tex+63−0

This diff is large: its 64 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libnis.tex+63−0

This diff is large: its 64 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libnntplib.tex+355−0

This diff is large: its 356 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libobjs.tex+24−0

This diff is large: its 25 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/liboperator.tex+530−0

This diff is large: its 531 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/liboptparse.tex+1888−0

This diff is large: its 1889 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libos.tex+2006−0

This diff is large: its 2007 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libossaudiodev.tex+401−0

This diff is large: its 402 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libpanel.tex+74−0

This diff is large: its 75 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libparser.tex+711−0

This diff is large: its 712 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libpdb.tex+456−0

This diff is large: its 457 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libpickle.tex+888−0

This diff is large: its 889 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libpickletools.tex+34−0

This diff is large: its 35 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libpipes.tex+84−0

This diff is large: its 85 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libpkgutil.tex+45−0

This diff is large: its 46 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libplatform.tex+221−0

This diff is large: its 222 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libpopen2.tex+189−0

This diff is large: its 190 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libpoplib.tex+181−0

This diff is large: its 182 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libposix.tex+97−0

This diff is large: its 98 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libposixfile.tex+175−0

This diff is large: its 176 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libposixpath.tex+281−0

This diff is large: its 282 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libpprint.tex+210−0

This diff is large: its 211 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libprofile.tex+722−0

This diff is large: its 723 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libpty.tex+44−0

This diff is large: its 45 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libpwd.tex+57−0

This diff is large: its 58 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libpyclbr.tex+102−0

This diff is large: its 103 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libpycompile.tex+53−0

This diff is large: its 54 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libpydoc.tex+67−0

This diff is large: its 68 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libpyexpat.tex+777−0

This diff is large: its 778 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libpython.tex+8−0

This diff is large: its 9 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libqueue.tex+145−0

This diff is large: its 146 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libquopri.tex+61−0

This diff is large: its 62 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/librandom.tex+309−0

This diff is large: its 310 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libre.tex+954−0

This diff is large: its 955 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libreadline.tex+196−0

This diff is large: its 197 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/librepr.tex+133−0

This diff is large: its 134 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libresource.tex+215−0

This diff is large: its 216 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/librestricted.tex+66−0

This diff is large: its 67 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/librexec.tex+275−0

This diff is large: its 276 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/librfc822.tex+336−0

This diff is large: its 337 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/librgbimg.tex+54−0

This diff is large: its 55 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/librlcompleter.tex+65−0

This diff is large: its 66 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/librobotparser.tex+66−0

This diff is large: its 67 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/librunpy.tex+74−0

This diff is large: its 75 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsched.tex+97−0

This diff is large: its 98 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libselect.tex+132−0

This diff is large: its 133 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsets.tex+264−0

This diff is large: its 265 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsgi.tex+7−0

This diff is large: its 8 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsgmllib.tex+271−0

This diff is large: its 272 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsha.tex+83−0

This diff is large: its 84 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libshelve.tex+174−0

This diff is large: its 175 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libshlex.tex+274−0

This diff is large: its 275 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libshutil.tex+151−0

This diff is large: its 152 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsignal.tex+174−0

This diff is large: its 175 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsimplehttp.tex+86−0

This diff is large: its 87 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsimplexmlrpc.tex+228−0

This diff is large: its 229 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsite.tex+88−0

This diff is large: its 89 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsmtpd.tex+63−0

This diff is large: its 64 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsmtplib.tex+295−0

This diff is large: its 296 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsndhdr.tex+41−0

This diff is large: its 42 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsocket.tex+910−0

This diff is large: its 911 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsocksvr.tex+293−0

This diff is large: its 294 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsomeos.tex+10−0

This diff is large: its 11 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libspwd.tex+48−0

This diff is large: its 49 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsqlite3.tex+642−0

This diff is large: its 643 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libstat.tex+157−0

This diff is large: its 158 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libstatvfs.tex+55−0

This diff is large: its 56 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libstdtypes.tex+2095−0

This diff is large: its 2096 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libstdwin.tex+832−0

This diff is large: its 833 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libstring.tex+451−0

This diff is large: its 452 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libstringio.tex+121−0

This diff is large: its 122 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libstringprep.tex+136−0

This diff is large: its 137 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libstrings.tex+10−0

This diff is large: its 11 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libstruct.tex+256−0

This diff is large: its 257 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsubprocess.tex+402−0

This diff is large: its 403 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsun.tex+5−0

This diff is large: its 6 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsunau.tex+218−0

This diff is large: its 219 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsunaudio.tex+146−0

This diff is large: its 147 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsymbol.tex+30−0

This diff is large: its 31 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsys.tex+617−0

This diff is large: its 618 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libsyslog.tex+76−0

This diff is large: its 77 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libtabnanny.tex+62−0

This diff is large: its 63 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libtarfile.tex+497−0

This diff is large: its 498 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libtelnetlib.tex+215−0

This diff is large: its 216 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libtempfile.tex+194−0

This diff is large: its 195 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libtermios.tex+106−0

This diff is large: its 107 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libtest.tex+278−0

This diff is large: its 279 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libtextwrap.tex+181−0

This diff is large: its 182 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libthread.tex+173−0

This diff is large: its 174 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libthreading.tex+716−0

This diff is large: its 717 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libtime.tex+461−0

This diff is large: its 462 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libtimeit.tex+224−0

This diff is large: its 225 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libtoken.tex+44−0

This diff is large: its 45 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libtokenize.tex+119−0

This diff is large: its 120 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libtrace.tex+125−0

This diff is large: its 126 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libtraceback.tex+157−0

This diff is large: its 158 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libtty.tex+34−0

This diff is large: its 35 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libturtle.tex+268−0

This diff is large: its 269 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libtypes.tex+215−0

This diff is large: its 216 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libundoc.tex+113−0

This diff is large: its 114 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libunicodedata.tex+160−0

This diff is large: its 161 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libunittest.tex+974−0

This diff is large: its 975 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libunix.tex+8−0

This diff is large: its 9 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/liburllib.tex+497−0

This diff is large: its 498 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/liburllib2.tex+872−0

This diff is large: its 873 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/liburlparse.tex+253−0

This diff is large: its 254 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libuser.tex+71−0

This diff is large: its 72 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libuserdict.tex+181−0

This diff is large: its 182 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libuu.tex+58−0

This diff is large: its 59 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libuuid.tex+233−0

This diff is large: its 234 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libwarnings.tex+253−0

This diff is large: its 254 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libwave.tex+169−0

This diff is large: its 170 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libweakref.tex+336−0

This diff is large: its 337 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libwebbrowser.tex+173−0

This diff is large: its 174 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libwhichdb.tex+20−0

This diff is large: its 21 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libwinreg.tex+414−0

This diff is large: its 415 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libwinsound.tex+142−0

This diff is large: its 143 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libwsgiref.tex+782−0

This diff is large: its 783 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libxdrlib.tex+251−0

This diff is large: its 252 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libxmllib.tex+287−0

This diff is large: its 288 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libxmlrpclib.tex+383−0

This diff is large: its 384 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libzipfile.tex+309−0

This diff is large: its 310 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libzipimport.tex+133−0

This diff is large: its 134 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/libzlib.tex+197−0

This diff is large: its 198 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/markup.tex+29−0

This diff is large: its 30 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/mimelib.tex+65−0

This diff is large: its 66 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/minidom-example.py+64−0

This diff is large: its 65 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/modules.tex+9−0

This diff is large: its 10 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/netdata.tex+6−0

This diff is large: its 7 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/numeric.tex+13−0

This diff is large: its 14 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/persistence.tex+15−0

This diff is large: its 16 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/required_1.py+20−0

This diff is large: its 21 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/required_2.py+41−0

This diff is large: its 42 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/adapter_datetime.py+14−0

This diff is large: its 15 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/adapter_point_1.py+16−0

This diff is large: its 17 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/adapter_point_2.py+17−0

This diff is large: its 18 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/collation_reverse.py+15−0

This diff is large: its 16 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/complete_statement.py+30−0

This diff is large: its 31 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/connect_db_1.py+3−0

This diff is large: its 4 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/connect_db_2.py+3−0

This diff is large: its 4 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/converter_point.py+47−0

This diff is large: its 48 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/countcursors.py+15−0

This diff is large: its 16 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/createdb.py+28−0

This diff is large: its 29 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/execsql_fetchonerow.py+17−0

This diff is large: its 18 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/execsql_printall_1.py+13−0

This diff is large: its 14 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/execute_1.py+11−0

This diff is large: its 12 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/execute_2.py+12−0

This diff is large: its 13 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/execute_3.py+12−0

This diff is large: its 13 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/executemany_1.py+24−0

This diff is large: its 25 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/executemany_2.py+15−0

This diff is large: its 16 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/executescript.py+24−0

This diff is large: its 25 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/insert_more_people.py+16−0

This diff is large: its 17 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/md5func.py+11−0

This diff is large: its 12 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/mysumaggr.py+20−0

This diff is large: its 21 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/parse_colnames.py+8−0

This diff is large: its 9 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/pysqlite_datetime.py+20−0

This diff is large: its 21 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/row_factory.py+13−0

This diff is large: its 14 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/rowclass.py+12−0

This diff is large: its 13 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/shared_cache.py+6−0

This diff is large: its 7 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/shortcut_methods.py+21−0

This diff is large: its 22 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/simple_tableprinter.py+26−0

This diff is large: its 27 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/sqlite3/text_factory.py+42−0

This diff is large: its 43 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/tkinter.tex+1873−0

This diff is large: its 1874 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/tzinfo-examples.py+139−0

This diff is large: its 140 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/windows.tex+8−0

This diff is large: its 9 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/xmldom.tex+928−0

This diff is large: its 929 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/xmldomminidom.tex+285−0

This diff is large: its 286 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/xmldompulldom.tex+61−0

This diff is large: its 62 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/xmletree.tex+27−0

This diff is large: its 28 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/xmlsax.tex+143−0

This diff is large: its 144 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/xmlsaxhandler.tex+381−0

This diff is large: its 382 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/xmlsaxreader.tex+351−0

This diff is large: its 352 lines aren’t shown here.

sys/src/cmd/python/Doc/lib/xmlsaxutils.tex+81−0

This diff is large: its 82 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/libaepack.tex+82−0

This diff is large: its 83 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/libaetools.tex+83−0

This diff is large: its 84 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/libaetypes.tex+135−0

This diff is large: its 136 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/libautogil.tex+26−0

This diff is large: its 27 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/libcolorpicker.tex+23−0

This diff is large: its 24 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/libframework.tex+314−0

This diff is large: its 315 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/libgensuitemodule.tex+64−0

This diff is large: its 65 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/libmac.tex+29−0

This diff is large: its 30 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/libmacfs.tex+241−0

This diff is large: its 242 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/libmacic.tex+123−0

This diff is large: its 124 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/libmacos.tex+90−0

This diff is large: its 91 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/libmacostools.tex+105−0

This diff is large: its 106 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/libmacui.tex+266−0

This diff is large: its 267 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/libminiae.tex+65−0

This diff is large: its 66 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/libscrap.tex+42−0

This diff is large: its 43 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/mac.tex+89−0

This diff is large: its 90 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/scripting.tex+101−0

This diff is large: its 102 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/toolbox.tex+173−0

This diff is large: its 174 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/undoc.tex+97−0

This diff is large: its 98 lines aren’t shown here.

sys/src/cmd/python/Doc/mac/using.tex+218−0

This diff is large: its 219 lines aren’t shown here.

sys/src/cmd/python/Doc/paper-a4/pypaper.sty+17−0

This diff is large: its 18 lines aren’t shown here.

sys/src/cmd/python/Doc/perl/SynopsisTable.pm+95−0

This diff is large: its 96 lines aren’t shown here.

sys/src/cmd/python/Doc/perl/distutils.perl+21−0

This diff is large: its 22 lines aren’t shown here.

sys/src/cmd/python/Doc/perl/howto.perl+12−0

This diff is large: its 13 lines aren’t shown here.

sys/src/cmd/python/Doc/perl/isilo.perl+12−0

This diff is large: its 13 lines aren’t shown here.

sys/src/cmd/python/Doc/perl/l2hinit.perl+801−0

This diff is large: its 802 lines aren’t shown here.

sys/src/cmd/python/Doc/perl/ltxmarkup.perl+67−0

This diff is large: its 68 lines aren’t shown here.

sys/src/cmd/python/Doc/perl/manual.perl+15−0

This diff is large: its 16 lines aren’t shown here.

sys/src/cmd/python/Doc/perl/python.perl+2172−0

This diff is large: its 2173 lines aren’t shown here.

sys/src/cmd/python/Doc/python-docs.txt+183−0

This diff is large: its 184 lines aren’t shown here.

sys/src/cmd/python/Doc/ref/ref.tex+68−0

This diff is large: its 69 lines aren’t shown here.

sys/src/cmd/python/Doc/ref/ref1.tex+136−0

This diff is large: its 137 lines aren’t shown here.

sys/src/cmd/python/Doc/ref/ref2.tex+731−0

This diff is large: its 732 lines aren’t shown here.

sys/src/cmd/python/Doc/ref/ref3.tex+2225−0

This diff is large: its 2226 lines aren’t shown here.

sys/src/cmd/python/Doc/ref/ref4.tex+219−0

This diff is large: its 220 lines aren’t shown here.

sys/src/cmd/python/Doc/ref/ref5.tex+1325−0

This diff is large: its 1326 lines aren’t shown here.

sys/src/cmd/python/Doc/ref/ref6.tex+928−0

This diff is large: its 929 lines aren’t shown here.

sys/src/cmd/python/Doc/ref/ref7.tex+544−0

This diff is large: its 545 lines aren’t shown here.

sys/src/cmd/python/Doc/ref/ref8.tex+112−0

This diff is large: its 113 lines aren’t shown here.

sys/src/cmd/python/Doc/ref/reswords.py+23−0

This diff is large: its 24 lines aren’t shown here.

sys/src/cmd/python/Doc/templates/howto.tex+112−0

This diff is large: its 113 lines aren’t shown here.

sys/src/cmd/python/Doc/templates/manual.tex+89−0

This diff is large: its 90 lines aren’t shown here.

sys/src/cmd/python/Doc/templates/module.tex+170−0

This diff is large: its 171 lines aren’t shown here.

sys/src/cmd/python/Doc/templates/whatsnewXY.tex+149−0

This diff is large: its 150 lines aren’t shown here.

sys/src/cmd/python/Doc/tests/math.tex+16−0

This diff is large: its 17 lines aren’t shown here.

sys/src/cmd/python/Doc/texinputs/distutils.sty+33−0

This diff is large: its 34 lines aren’t shown here.

sys/src/cmd/python/Doc/texinputs/fancyhdr.sty+329−0

This diff is large: its 330 lines aren’t shown here.

sys/src/cmd/python/Doc/texinputs/fncychap.sty+433−0

This diff is large: its 434 lines aren’t shown here.

sys/src/cmd/python/Doc/texinputs/howto.cls+109−0

This diff is large: its 110 lines aren’t shown here.

sys/src/cmd/python/Doc/texinputs/ltxmarkup.sty+40−0

This diff is large: its 41 lines aren’t shown here.

sys/src/cmd/python/Doc/texinputs/manual.cls+155−0

This diff is large: its 156 lines aren’t shown here.

sys/src/cmd/python/Doc/texinputs/pypaper.sty+18−0

This diff is large: its 19 lines aren’t shown here.

sys/src/cmd/python/Doc/texinputs/python.ist+11−0

This diff is large: its 12 lines aren’t shown here.

sys/src/cmd/python/Doc/texinputs/python.sty+1327−0

This diff is large: its 1328 lines aren’t shown here.

sys/src/cmd/python/Doc/texinputs/underscore.sty+232−0

This diff is large: its 233 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/anno-api.py+71−0

This diff is large: its 72 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/buildindex.py+388−0

This diff is large: its 389 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/checkargs.pm+112−0

This diff is large: its 113 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/cklatex+26−0

This diff is large: its 27 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/cmpcsyms+157−0

This diff is large: its 158 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/custlib.py+78−0

This diff is large: its 79 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/findcsyms+136−0

This diff is large: its 137 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/findmodrefs+63−0

This diff is large: its 64 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/findsyms+128−0

This diff is large: its 129 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/fix_hack+2−0

This diff is large: its 3 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/fix_libaux.sed+3−0

This diff is large: its 4 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/fixinfo.el+15−0

This diff is large: its 16 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/getpagecounts+97−0

This diff is large: its 98 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/getversioninfo+71−0

This diff is large: its 72 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/html2texi.pl+1750−0

This diff is large: its 1751 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/indfix.py+100−0

This diff is large: its 101 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/keywords.py+19−0

This diff is large: its 20 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/listmodules+183−0

This diff is large: its 184 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/listmodules.py+126−0

This diff is large: its 127 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/makesec.sh+129−0

This diff is large: its 130 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/mkackshtml+66−0

This diff is large: its 67 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/mkhowto+659−0

This diff is large: its 660 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/mkinfo+65−0

This diff is large: its 66 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/mkmodindex+158−0

This diff is large: its 159 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/mkpkglist+85−0

This diff is large: its 86 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/mksourcepkg+164−0

This diff is large: its 165 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/node2label.pl+71−0

This diff is large: its 72 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/prechm.py+519−0

This diff is large: its 520 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/push-docs.sh+138−0

This diff is large: its 139 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/py2texi.el+970−0

This diff is large: its 971 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/refcounts.py+98−0

This diff is large: its 99 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/rewrite.py+54−0

This diff is large: its 55 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/sgmlconv/Makefile+67−0

This diff is large: its 68 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/sgmlconv/README+58−0

This diff is large: its 59 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/sgmlconv/conversion.xml+914−0

This diff is large: its 915 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/sgmlconv/docfixer.py+1073−0

This diff is large: its 1074 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/sgmlconv/esis2sgml.py+264−0

This diff is large: its 265 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/sgmlconv/esistools.py+312−0

This diff is large: its 313 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/sgmlconv/latex2esis.py+565−0

This diff is large: its 566 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/sgmlconv/make.rules+48−0

This diff is large: its 49 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/support.py+202−0

This diff is large: its 203 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/toc2bkm.py+160−0

This diff is large: its 161 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/undoc_symbols.py+94−0

This diff is large: its 95 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/update-docs.sh+31−0

This diff is large: its 32 lines aren’t shown here.

sys/src/cmd/python/Doc/tools/whichlibs+2−0

This diff is large: its 3 lines aren’t shown here.

sys/src/cmd/python/Doc/tut/glossary.tex+352−0

This diff is large: its 353 lines aren’t shown here.

sys/src/cmd/python/Doc/tut/tut.tex+5907−0

This diff is large: its 5908 lines aren’t shown here.

sys/src/cmd/python/Doc/whatsnew/Makefile+3−0

This diff is large: its 4 lines aren’t shown here.

sys/src/cmd/python/Doc/whatsnew/whatsnew20.tex+1337−0

This diff is large: its 1338 lines aren’t shown here.

sys/src/cmd/python/Doc/whatsnew/whatsnew21.tex+868−0

This diff is large: its 869 lines aren’t shown here.

sys/src/cmd/python/Doc/whatsnew/whatsnew22.tex+1466−0

This diff is large: its 1467 lines aren’t shown here.

sys/src/cmd/python/Doc/whatsnew/whatsnew23.tex+2380−0

This diff is large: its 2381 lines aren’t shown here.

sys/src/cmd/python/Doc/whatsnew/whatsnew24.tex+1757−0

This diff is large: its 1758 lines aren’t shown here.

sys/src/cmd/python/Doc/whatsnew/whatsnew25.tex+2530−0

This diff is large: its 2531 lines aren’t shown here.

sys/src/cmd/python/Extra/dummy.c+6−0

This diff is large: its 7 lines aren’t shown here.

sys/src/cmd/python/Extra/mercurial/base85.c+155−0

This diff is large: its 156 lines aren’t shown here.

sys/src/cmd/python/Extra/mercurial/bdiff.c+401−0

This diff is large: its 402 lines aren’t shown here.

sys/src/cmd/python/Extra/mercurial/diffhelpers.c+156−0

This diff is large: its 157 lines aren’t shown here.

sys/src/cmd/python/Extra/mercurial/mpatch.c+444−0

This diff is large: its 445 lines aren’t shown here.

sys/src/cmd/python/Extra/mercurial/osutil.c+534−0

This diff is large: its 535 lines aren’t shown here.

sys/src/cmd/python/Extra/mercurial/parsers.c+435−0

This diff is large: its 436 lines aren’t shown here.

sys/src/cmd/python/Extra/mkfile+16−0

This diff is large: its 17 lines aren’t shown here.

sys/src/cmd/python/Grammar/Grammar+148−0

This diff is large: its 149 lines aren’t shown here.

sys/src/cmd/python/Include/Python-ast.h+501−0

This diff is large: its 502 lines aren’t shown here.

sys/src/cmd/python/Include/Python.h+173−0

This diff is large: its 174 lines aren’t shown here.

sys/src/cmd/python/Include/abstract.h+1276−0

This diff is large: its 1277 lines aren’t shown here.

sys/src/cmd/python/Include/asdl.h+45−0

This diff is large: its 46 lines aren’t shown here.

sys/src/cmd/python/Include/ast.h+13−0

This diff is large: its 14 lines aren’t shown here.

sys/src/cmd/python/Include/bitset.h+32−0

This diff is large: its 33 lines aren’t shown here.

sys/src/cmd/python/Include/boolobject.h+36−0

This diff is large: its 37 lines aren’t shown here.

sys/src/cmd/python/Include/bufferobject.h+33−0

This diff is large: its 34 lines aren’t shown here.

sys/src/cmd/python/Include/cStringIO.h+70−0

This diff is large: its 71 lines aren’t shown here.

sys/src/cmd/python/Include/cellobject.h+28−0

This diff is large: its 29 lines aren’t shown here.

sys/src/cmd/python/Include/ceval.h+157−0

This diff is large: its 158 lines aren’t shown here.

sys/src/cmd/python/Include/classobject.h+81−0

This diff is large: its 82 lines aren’t shown here.

sys/src/cmd/python/Include/cobject.h+54−0

This diff is large: its 55 lines aren’t shown here.

sys/src/cmd/python/Include/code.h+94−0

This diff is large: its 95 lines aren’t shown here.

sys/src/cmd/python/Include/codecs.h+167−0

This diff is large: its 168 lines aren’t shown here.

sys/src/cmd/python/Include/compile.h+39−0

This diff is large: its 40 lines aren’t shown here.

sys/src/cmd/python/Include/complexobject.h+58−0

This diff is large: its 59 lines aren’t shown here.

sys/src/cmd/python/Include/datetime.h+245−0

This diff is large: its 246 lines aren’t shown here.

sys/src/cmd/python/Include/descrobject.h+91−0

This diff is large: its 92 lines aren’t shown here.

sys/src/cmd/python/Include/dictobject.h+141−0

This diff is large: its 142 lines aren’t shown here.

sys/src/cmd/python/Include/enumobject.h+17−0

This diff is large: its 18 lines aren’t shown here.

sys/src/cmd/python/Include/errcode.h+36−0

This diff is large: its 37 lines aren’t shown here.

sys/src/cmd/python/Include/eval.h+25−0

This diff is large: its 26 lines aren’t shown here.

sys/src/cmd/python/Include/fileobject.h+63−0

This diff is large: its 64 lines aren’t shown here.

sys/src/cmd/python/Include/floatobject.h+100−0

This diff is large: its 101 lines aren’t shown here.

sys/src/cmd/python/Include/frameobject.h+81−0

This diff is large: its 82 lines aren’t shown here.

sys/src/cmd/python/Include/funcobject.h+76−0

This diff is large: its 77 lines aren’t shown here.

sys/src/cmd/python/Include/genobject.h+37−0

This diff is large: its 38 lines aren’t shown here.

sys/src/cmd/python/Include/graminit.h+84−0

This diff is large: its 85 lines aren’t shown here.

sys/src/cmd/python/Include/grammar.h+93−0

This diff is large: its 94 lines aren’t shown here.

sys/src/cmd/python/Include/import.h+64−0

This diff is large: its 65 lines aren’t shown here.

sys/src/cmd/python/Include/intobject.h+64−0

This diff is large: its 65 lines aren’t shown here.

sys/src/cmd/python/Include/intrcheck.h+15−0

This diff is large: its 16 lines aren’t shown here.

sys/src/cmd/python/Include/iterobject.h+23−0

This diff is large: its 24 lines aren’t shown here.

sys/src/cmd/python/Include/listobject.h+67−0

This diff is large: its 68 lines aren’t shown here.

sys/src/cmd/python/Include/longintrepr.h+63−0

This diff is large: its 64 lines aren’t shown here.

sys/src/cmd/python/Include/longobject.h+114−0

This diff is large: its 115 lines aren’t shown here.

sys/src/cmd/python/Include/marshal.h+25−0

This diff is large: its 26 lines aren’t shown here.

sys/src/cmd/python/Include/metagrammar.h+18−0

This diff is large: its 19 lines aren’t shown here.

sys/src/cmd/python/Include/methodobject.h+91−0

This diff is large: its 92 lines aren’t shown here.

sys/src/cmd/python/Include/modsupport.h+133−0

This diff is large: its 134 lines aren’t shown here.

sys/src/cmd/python/Include/moduleobject.h+24−0

This diff is large: its 25 lines aren’t shown here.

sys/src/cmd/python/Include/node.h+40−0

This diff is large: its 41 lines aren’t shown here.

sys/src/cmd/python/Include/object.h+868−0

This diff is large: its 869 lines aren’t shown here.

sys/src/cmd/python/Include/objimpl.h+336−0

This diff is large: its 337 lines aren’t shown here.

sys/src/cmd/python/Include/opcode.h+152−0

This diff is large: its 153 lines aren’t shown here.

sys/src/cmd/python/Include/osdefs.h+55−0

This diff is large: its 56 lines aren’t shown here.

sys/src/cmd/python/Include/parsetok.h+50−0

This diff is large: its 51 lines aren’t shown here.

sys/src/cmd/python/Include/patchlevel.h+40−0

This diff is large: its 41 lines aren’t shown here.

sys/src/cmd/python/Include/pgen.h+18−0

This diff is large: its 19 lines aren’t shown here.

sys/src/cmd/python/Include/pgenheaders.h+42−0

This diff is large: its 43 lines aren’t shown here.

sys/src/cmd/python/Include/py_curses.h+176−0

This diff is large: its 177 lines aren’t shown here.

sys/src/cmd/python/Include/pyarena.h+62−0

This diff is large: its 63 lines aren’t shown here.

sys/src/cmd/python/Include/pydebug.h+34−0

This diff is large: its 35 lines aren’t shown here.

sys/src/cmd/python/Include/pyerrors.h+334−0

This diff is large: its 335 lines aren’t shown here.

sys/src/cmd/python/Include/pyexpat.h+47−0

This diff is large: its 48 lines aren’t shown here.

sys/src/cmd/python/Include/pyfpe.h+176−0

This diff is large: its 177 lines aren’t shown here.

sys/src/cmd/python/Include/pygetopt.h+17−0

This diff is large: its 18 lines aren’t shown here.

sys/src/cmd/python/Include/pymactoolbox.h+189−0

This diff is large: its 190 lines aren’t shown here.

sys/src/cmd/python/Include/pymem.h+105−0

This diff is large: its 106 lines aren’t shown here.

sys/src/cmd/python/Include/pyport.h+771−0

This diff is large: its 772 lines aren’t shown here.

sys/src/cmd/python/Include/pystate.h+195−0

This diff is large: its 196 lines aren’t shown here.

sys/src/cmd/python/Include/pystrtod.h+18−0

This diff is large: its 19 lines aren’t shown here.

sys/src/cmd/python/Include/pythonrun.h+171−0

This diff is large: its 172 lines aren’t shown here.

sys/src/cmd/python/Include/pythread.h+47−0

This diff is large: its 48 lines aren’t shown here.

sys/src/cmd/python/Include/rangeobject.h+28−0

This diff is large: its 29 lines aren’t shown here.

sys/src/cmd/python/Include/setobject.h+93−0

This diff is large: its 94 lines aren’t shown here.

sys/src/cmd/python/Include/sliceobject.h+43−0

This diff is large: its 44 lines aren’t shown here.

sys/src/cmd/python/Include/stringobject.h+183−0

This diff is large: its 184 lines aren’t shown here.

sys/src/cmd/python/Include/structmember.h+93−0

This diff is large: its 94 lines aren’t shown here.

sys/src/cmd/python/Include/structseq.h+41−0

This diff is large: its 42 lines aren’t shown here.

sys/src/cmd/python/Include/symtable.h+103−0

This diff is large: its 104 lines aren’t shown here.

sys/src/cmd/python/Include/sysmodule.h+30−0

This diff is large: its 31 lines aren’t shown here.

sys/src/cmd/python/Include/timefuncs.h+23−0

This diff is large: its 24 lines aren’t shown here.

sys/src/cmd/python/Include/token.h+83−0

This diff is large: its 84 lines aren’t shown here.

sys/src/cmd/python/Include/traceback.h+30−0

This diff is large: its 31 lines aren’t shown here.

sys/src/cmd/python/Include/tupleobject.h+57−0

This diff is large: its 58 lines aren’t shown here.

sys/src/cmd/python/Include/ucnhash.h+31−0

This diff is large: its 32 lines aren’t shown here.

sys/src/cmd/python/Include/unicodeobject.h+1265−0

This diff is large: its 1266 lines aren’t shown here.

sys/src/cmd/python/Include/weakrefobject.h+75−0

This diff is large: its 76 lines aren’t shown here.

sys/src/cmd/python/LICENSE+270−0

This diff is large: its 271 lines aren’t shown here.

sys/src/cmd/python/Misc/ACKS+698−0

This diff is large: its 699 lines aren’t shown here.

sys/src/cmd/python/Misc/AIX-NOTES+155−0

This diff is large: its 156 lines aren’t shown here.

sys/src/cmd/python/Misc/BeOS-NOTES+43−0

This diff is large: its 44 lines aren’t shown here.

sys/src/cmd/python/Misc/BeOS-setup.py+574−0

This diff is large: its 575 lines aren’t shown here.

sys/src/cmd/python/Misc/NEWS+2782−0

This diff is large: its 2783 lines aren’t shown here.

sys/src/cmd/python/Misc/NEWS.help+73−0

This diff is large: its 74 lines aren’t shown here.

sys/src/cmd/python/Misc/PURIFY.README+97−0

This diff is large: its 98 lines aren’t shown here.

sys/src/cmd/python/Misc/Porting+42−0

This diff is large: its 43 lines aren’t shown here.

sys/src/cmd/python/Misc/README+33−0

This diff is large: its 34 lines aren’t shown here.

sys/src/cmd/python/Misc/README.OpenBSD+38−0

This diff is large: its 39 lines aren’t shown here.

sys/src/cmd/python/Misc/README.coverity+22−0

This diff is large: its 23 lines aren’t shown here.

sys/src/cmd/python/Misc/README.klocwork+30−0

This diff is large: its 31 lines aren’t shown here.

sys/src/cmd/python/Misc/README.valgrind+97−0

This diff is large: its 98 lines aren’t shown here.

sys/src/cmd/python/Misc/RFD+114−0

This diff is large: its 115 lines aren’t shown here.

sys/src/cmd/python/Misc/RPM/README+16−0

This diff is large: its 17 lines aren’t shown here.

sys/src/cmd/python/Misc/RPM/python-2.5.spec+395−0

This diff is large: its 396 lines aren’t shown here.

sys/src/cmd/python/Misc/SpecialBuilds.txt+261−0

This diff is large: its 262 lines aren’t shown here.

sys/src/cmd/python/Misc/Vim/python.vim+147−0

This diff is large: its 148 lines aren’t shown here.

sys/src/cmd/python/Misc/Vim/syntax_test.py+63−0

This diff is large: its 64 lines aren’t shown here.

sys/src/cmd/python/Misc/Vim/vim_syntax.py+226−0

This diff is large: its 227 lines aren’t shown here.

sys/src/cmd/python/Misc/Vim/vimrc+95−0

This diff is large: its 96 lines aren’t shown here.

sys/src/cmd/python/Misc/build.sh+227−0

This diff is large: its 228 lines aren’t shown here.

sys/src/cmd/python/Misc/cheatsheet+2279−0

This diff is large: its 2280 lines aren’t shown here.

sys/src/cmd/python/Misc/developers.txt+141−0

This diff is large: its 142 lines aren’t shown here.

sys/src/cmd/python/Misc/find_recursionlimit.py+87−0

This diff is large: its 88 lines aren’t shown here.

sys/src/cmd/python/Misc/gdbinit+140−0

This diff is large: its 141 lines aren’t shown here.

sys/src/cmd/python/Misc/indent.pro+15−0

This diff is large: its 16 lines aren’t shown here.

sys/src/cmd/python/Misc/pymemcompat.h+85−0

This diff is large: its 86 lines aren’t shown here.

sys/src/cmd/python/Misc/python-config.in+53−0

This diff is large: its 54 lines aren’t shown here.

sys/src/cmd/python/Misc/python-mode.el+3768−0

This diff is large: its 3769 lines aren’t shown here.

sys/src/cmd/python/Misc/python.man+397−0

This diff is large: its 398 lines aren’t shown here.

sys/src/cmd/python/Misc/setuid-prog.c+176−0

This diff is large: its 177 lines aren’t shown here.

sys/src/cmd/python/Misc/valgrind-python.supp+349−0

This diff is large: its 350 lines aren’t shown here.

sys/src/cmd/python/Misc/vgrindefs+10−0

This diff is large: its 11 lines aren’t shown here.

sys/src/cmd/python/Modules/Setup+488−0

This diff is large: its 489 lines aren’t shown here.

sys/src/cmd/python/Modules/Setup.config+13−0

This diff is large: its 14 lines aren’t shown here.

sys/src/cmd/python/Modules/Setup.config.in+13−0

This diff is large: its 14 lines aren’t shown here.

sys/src/cmd/python/Modules/Setup.dist+487−0

This diff is large: its 488 lines aren’t shown here.

sys/src/cmd/python/Modules/Setup.local+1−0

This diff is large: its 2 lines aren’t shown here.

sys/src/cmd/python/Modules/_bisectmodule.c+235−0

This diff is large: its 236 lines aren’t shown here.

sys/src/cmd/python/Modules/_bsddb.c+6047−0

This diff is large: its 6048 lines aren’t shown here.

sys/src/cmd/python/Modules/_codecsmodule.c+934−0

This diff is large: its 935 lines aren’t shown here.

sys/src/cmd/python/Modules/_csv.c+1604−0

This diff is large: its 1605 lines aren’t shown here.

This diff is larger than a page shows: the files after these aren’t listed. Clone the repository to see all of it.