From b0e7130ded9a892e03c10721a60fd8006a65c2da Mon Sep 17 00:00:00 2001 From: "(no author)" <(no author)@6015fed2-1504-0410-9fe1-9d1591cc4771> Date: Fri, 24 Dec 1993 14:51:14 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create tag 'last099'. git-svn-id: http://svn.python.org/projects/python/tags/last099@3631 6015fed2-1504-0410-9fe1-9d1591cc4771 --- Demo/README | 51 - Demo/classes/Complex.py | 85 -- Demo/classes/Dates.py | 233 ---- Demo/classes/Dbm.py | 66 - Demo/classes/README | 14 - Demo/classes/Range.py | 71 - Demo/classes/Rat.py | 97 -- Demo/classes/Rev.py | 89 -- Demo/classes/Vec.py | 64 - Demo/classes/bitvec.py | 332 ----- Demo/classes/class.doc | 110 -- Demo/cwilib/cwilib.py | 213 --- Demo/cwilib/form.py | 170 --- Demo/cwilib/telnetlib.py | 321 ----- Demo/cwilib/vt100.py | 328 ----- Demo/cwilib/vt100win.py | 78 -- Demo/rpc/MANIFEST | 10 - Demo/rpc/README | 23 - Demo/rpc/T.py | 22 - Demo/rpc/mountclient.py | 201 --- Demo/rpc/nfsclient.py | 201 --- Demo/rpc/rnusersclient.py | 98 -- Demo/rpc/rpc.py | 863 ------------ Demo/rpc/test | 23 - Demo/rpc/xdr.py | 201 --- Demo/scripts/README | 38 - Demo/scripts/eqfix.py | 200 --- Demo/scripts/fact.py | 48 - Demo/scripts/freeze.py | 453 ------- Demo/scripts/from.py | 35 - Demo/scripts/lpwatch.py | 110 -- Demo/scripts/makedir.py | 20 - Demo/scripts/markov.py | 116 -- Demo/scripts/mkrcs.py | 61 - Demo/scripts/pi.py | 33 - Demo/scripts/pp.py | 138 -- Demo/scripts/primes.py | 26 - Demo/scripts/update.py | 91 -- Demo/scripts/wh.py | 2 - Demo/sgi/al/README | 15 - Demo/sgi/al/alwatch.py | 33 - Demo/sgi/al/broadcast.py | 27 - Demo/sgi/al/cmpaf.py | 65 - Demo/sgi/al/cmpaf_form.fd | 90 -- Demo/sgi/al/intercom.py | 212 --- Demo/sgi/al/listen.py | 34 - Demo/sgi/al/names.py | 14 - Demo/sgi/al/playaiff.py | 54 - Demo/sgi/al/playback.py | 23 - Demo/sgi/al/playold.py | 51 - Demo/sgi/al/radio.py | 21 - Demo/sgi/al/rec_play.py | 28 - Demo/sgi/al/record.py | 23 - Demo/sgi/al/unicast.py | 26 - Demo/sgi/al/x.py | 12 - Demo/sgi/audio/README | 8 - Demo/sgi/audio/play.py | 75 -- Demo/sgi/audio_stdwin/README | 19 - Demo/sgi/audio_stdwin/jukebox.py | 321 ----- Demo/sgi/audio_stdwin/rec.py | 268 ---- Demo/sgi/audio_stdwin/vumeter.py | 35 - Demo/sgi/cd/CD.doc | 46 - Demo/sgi/cd/README | 28 - Demo/sgi/cd/cdaiff.py | 33 - Demo/sgi/cd/cdwin.py | 104 -- Demo/sgi/cd/listcd.py | 24 - Demo/sgi/cd/playcd.py | 102 -- Demo/sgi/cd/recvcd.py | 36 - Demo/sgi/cd/sendcd.py | 154 --- Demo/sgi/flp/test_cb.fd | 75 -- Demo/sgi/flp/test_cb.py | 61 - Demo/sgi/flp/test_nocb.fd | 75 -- Demo/sgi/flp/test_nocb.py | 45 - Demo/sgi/gl/README | 35 - Demo/sgi/gl/backface.py | 140 -- Demo/sgi/gl/glstdwin/fontchart.py | 34 - Demo/sgi/gl/glstdwin/glstdwdraw.py | 135 -- Demo/sgi/gl/glstdwin/glstdwin.py | 400 ------ Demo/sgi/gl/glstdwin/glstdwmenu.py | 62 - Demo/sgi/gl/glstdwin/glstdwwin.py | 139 -- Demo/sgi/gl/glstdwin/stdwingl.py | 10 - Demo/sgi/gl/glstdwin/tcolor.py | 43 - Demo/sgi/gl/glstdwin/tglsw.py | 70 - Demo/sgi/gl/glstdwin/tmenu.py | 44 - Demo/sgi/gl/kites.py | 194 --- Demo/sgi/gl/kunst.py | 426 ------ Demo/sgi/gl/mclock.doc | 60 - Demo/sgi/gl/mclock.py | 736 ----------- Demo/sgi/gl/mixing.py | 116 -- Demo/sgi/gl/nurbs.py | 171 --- Demo/sgi/gl/zrgb.py | 168 --- Demo/sgi/sv/README | 23 - Demo/sgi/sv/burstcapt.py | 52 - Demo/sgi/sv/contcapt.py | 107 -- Demo/sgi/sv/rgbgrab.py | 81 -- Demo/sgi/sv/simpleinput.py | 22 - Demo/sgi/video/.cvsignore | 2 - Demo/sgi/video/DisplayVideoIn.py | 99 -- Demo/sgi/video/Dsend.py | 188 --- Demo/sgi/video/IN.py | 54 - Demo/sgi/video/LiveVideoIn.py | 139 -- Demo/sgi/video/LiveVideoOut.py | 130 -- Demo/sgi/video/Makefile | 7 - Demo/sgi/video/OldVcopy.py | 148 --- Demo/sgi/video/README | 113 -- Demo/sgi/video/VCR.py | 534 -------- Demo/sgi/video/VFile.py | 1194 ----------------- Demo/sgi/video/VGrabber.py | 80 -- Demo/sgi/video/Vaddcache.py | 80 -- Demo/sgi/video/Vb.py | 963 -------------- Demo/sgi/video/VbForm.fd | 615 --------- Demo/sgi/video/Vcopy.py | 291 ---- Demo/sgi/video/VcrIndex.py | 327 ----- Demo/sgi/video/Vedit.py | 301 ----- Demo/sgi/video/VeditForm.fd | 435 ------ Demo/sgi/video/Vfix.py | 90 -- Demo/sgi/video/Viewer.py | 255 ---- Demo/sgi/video/Vinfo.py | 174 --- Demo/sgi/video/Vmkjpeg.py | 92 -- Demo/sgi/video/Vplay.py | 354 ----- Demo/sgi/video/Vrec.py | 412 ------ Demo/sgi/video/Vrecb.py | 429 ------ Demo/sgi/video/Vrecc.py | 281 ---- Demo/sgi/video/Vreceive.py | 135 -- Demo/sgi/video/Vsend.py | 152 --- Demo/sgi/video/Vstat.py | 23 - Demo/sgi/video/Vtime.py | 117 -- Demo/sgi/video/Vunjpeg.py | 97 -- Demo/sgi/video/aplay.py | 167 --- Demo/sgi/video/cam.py | 129 -- Demo/sgi/video/camcorder.py | 266 ---- Demo/sgi/video/cmif-film.ms | 200 --- Demo/sgi/video/colorsys.py | 106 -- Demo/sgi/video/i2v.c | 80 -- Demo/sgi/video/imgconv.py | 140 -- Demo/sgi/video/makemovie.py | 218 --- Demo/sgi/video/rgb2video.py | 79 -- Demo/sgi/video/senddefs.py | 11 - Demo/sgi/video/squash.c | 130 -- Demo/sgi/video/squash2.c | 72 - Demo/sgi/video/statit.py | 115 -- Demo/sgi/video/svgrab24.c | 97 -- Demo/sgi/video/syncaudio.py | 94 -- Demo/sgi/video/tomono.c | 165 --- Demo/sgi/video/tv.py | 79 -- Demo/sgi/video/v2i.c | 79 -- Demo/sgi/video/vcopy.py | 134 -- Demo/sgi/video/video.doc | 109 -- Demo/sgi/video/video.py | 218 --- Demo/sgi/video/video2rgb.py | 159 --- Demo/sgi/video/vinfo.py | 90 -- Demo/sgi/video/vpregs.py | 28 - Demo/sgi/video/vtime.py | 106 -- Demo/sgi/video/watchcursor.py | 45 - Demo/sockets/ChangeLog | 35 - Demo/sockets/README | 20 - Demo/sockets/broadcast.py | 18 - Demo/sockets/echosvr.py | 31 - Demo/sockets/finger.py | 58 - Demo/sockets/ftp.py | 144 -- Demo/sockets/gopher.py | 347 ----- Demo/sockets/mcast.py | 97 -- Demo/sockets/radio.py | 14 - Demo/sockets/telnet.py | 109 -- Demo/sockets/throughput.py | 93 -- Demo/sockets/udpecho.py | 63 - Demo/stdwin/FormTest.py | 30 - Demo/stdwin/README | 16 - Demo/stdwin/RadioGroups.py | 98 -- Demo/stdwin/TestCSplit.py | 25 - Demo/stdwin/TestDirList.py | 18 - Demo/stdwin/TestFormSplit.py | 27 - Demo/stdwin/TestSched.py | 38 - Demo/stdwin/TestTextEdit.py | 13 - Demo/stdwin/clock.py | 204 --- Demo/stdwin/ibrowse/README | 34 - Demo/stdwin/ibrowse/dir | 62 - Demo/stdwin/ibrowse/ib | 2 - Demo/stdwin/ibrowse/ib.py | 21 - Demo/stdwin/ibrowse/ibrowse | 719 ---------- Demo/stdwin/ibrowse/ibrowse.py | 617 --------- Demo/stdwin/ibrowse/icache.py | 74 -- Demo/stdwin/ibrowse/ifile.py | 328 ----- Demo/stdwin/ibrowse/itags.py | 127 -- Demo/stdwin/jukebox.py | 409 ------ Demo/stdwin/lpwin.py | 198 --- Demo/stdwin/microedit.py | 183 --- Demo/stdwin/miniedit.py | 356 ----- Demo/stdwin/python.py | 448 ------- Demo/stdwin/wdiff.py | 483 ------- Demo/threads/README | 8 - Demo/threads/find.py | 153 --- Demo/threads/telnet.py | 113 -- Demo/threads/wpi.py | 74 -- Doc/.cvsignore | 1 - Doc/Makefile | 68 - Doc/README | 87 -- Doc/ext.tex | 914 ------------- Doc/ext/ext.tex | 914 ------------- Doc/fix.el | 6 - Doc/fix_hack | 1 - Doc/info/texipost.dat | 23 - Doc/info/texipre.dat | 86 -- Doc/lib.tex | 57 - Doc/lib/lib.tex | 57 - Doc/lib/libtemplate.tex | 40 - Doc/libtemplate.tex | 40 - Doc/myformat.sty | 199 --- Doc/partparse.py | 2129 ------------------------------ Doc/qua.tex | 1235 ----------------- Doc/quabib.bib | 139 -- Doc/ref.tex | 73 - Doc/ref/ref.tex | 73 - Doc/ref/ref1.tex | 81 -- Doc/ref/ref2.tex | 349 ----- Doc/ref/ref3.tex | 760 ----------- Doc/ref/ref4.tex | 148 --- Doc/ref/ref5.tex | 689 ---------- Doc/ref/ref6.tex | 507 ------- Doc/ref/ref7.tex | 364 ----- Doc/ref/ref8.tex | 104 -- Doc/ref1.tex | 81 -- Doc/ref2.tex | 349 ----- Doc/ref3.tex | 760 ----------- Doc/ref4.tex | 148 --- Doc/ref5.tex | 689 ---------- Doc/ref6.tex | 507 ------- Doc/ref7.tex | 364 ----- Doc/ref8.tex | 104 -- Doc/templates/module.tex | 40 - Doc/texipost.dat | 23 - Doc/texipre.dat | 86 -- Doc/text2latex.py | 55 - Doc/tools/fix.el | 6 - Doc/tools/fix_hack | 1 - Doc/tools/partparse.py | 2129 ------------------------------ Doc/tools/text2latex.py | 55 - Doc/tut.tex | 2565 ------------------------------------ Doc/tut/tut.tex | 2565 ------------------------------------ Grammar/Makefile | 28 - Include/myproto.h | 44 - Include/mytime.h | 47 - Lib/Queue.py | 120 -- Lib/UserDict.py | 18 - Lib/UserList.py | 39 - Lib/aifc.py | 1002 -------------- Lib/audiodev.py | 205 --- Lib/bdb.py | 306 ----- Lib/bisect.py | 23 - Lib/builtin.py | 3 - Lib/calendar.py | 159 --- Lib/cmd.py | 63 - Lib/cmp.py | 61 - Lib/cmpcache.py | 68 - Lib/codehack.py | 63 - Lib/colorsys.py | 119 -- Lib/commands.py | 56 - Lib/dircache.py | 35 - Lib/dircmp.py | 203 --- Lib/dis.py | 188 --- Lib/dump.py | 63 - Lib/emacs.py | 18 - Lib/fnmatch.py | 56 - Lib/fpformat.py | 138 -- Lib/ftplib.py | 452 ------- Lib/getopt.py | 47 - Lib/glob.py | 51 - Lib/grep.py | 62 - Lib/imghdr.py | 129 -- Lib/importall.py | 34 - Lib/irix5/AL.py | 60 - Lib/irix5/AWARE.py | 54 - Lib/irix5/CD.py | 34 - Lib/irix5/CL.py | 236 ---- Lib/irix5/DEVICE.py | 400 ------ Lib/irix5/FL.py | 289 ---- Lib/irix5/GET.py | 59 - Lib/irix5/GL.py | 393 ------ Lib/irix5/GLWS.py | 12 - Lib/irix5/SV.py | 120 -- Lib/irix5/auds.py | 106 -- Lib/irix5/cddb.py | 158 --- Lib/irix5/cdplayer.py | 89 -- Lib/irix5/flp.doc | 117 -- Lib/irix5/flp.py | 465 ------- Lib/irix5/panel.py | 281 ---- Lib/irix5/panelparser.py | 128 -- Lib/irix5/readcd.doc | 104 -- Lib/irix5/readcd.py | 232 ---- Lib/irix5/torgb.py | 97 -- Lib/lib-old/codehack.py | 63 - Lib/lib-old/dump.py | 63 - Lib/lib-old/grep.py | 62 - Lib/lib-old/newdir.py | 75 -- Lib/lib-old/packmail.py | 88 -- Lib/lib-old/rand.py | 13 - Lib/lib-old/tb.py | 173 --- Lib/lib-old/util.py | 25 - Lib/lib-old/whatsound.py | 270 ---- Lib/lib-stdwin/Abstract.py | 63 - Lib/lib-stdwin/BoxParent.py | 40 - Lib/lib-stdwin/Buttons.py | 411 ------ Lib/lib-stdwin/CSplit.py | 69 - Lib/lib-stdwin/DirList.py | 58 - Lib/lib-stdwin/FormSplit.py | 58 - Lib/lib-stdwin/HVSplit.py | 62 - Lib/lib-stdwin/Histogram.py | 36 - Lib/lib-stdwin/Sliders.py | 174 --- Lib/lib-stdwin/Soundogram.py | 36 - Lib/lib-stdwin/Split.py | 211 --- Lib/lib-stdwin/StripChart.py | 70 - Lib/lib-stdwin/TextEdit.py | 126 -- Lib/lib-stdwin/TransParent.py | 123 -- Lib/lib-stdwin/VUMeter.py | 47 - Lib/lib-stdwin/WindowParent.py | 189 --- Lib/lib-stdwin/WindowSched.py | 58 - Lib/lib-stdwin/anywin.py | 14 - Lib/lib-stdwin/basewin.py | 64 - Lib/lib-stdwin/dirwin.py | 29 - Lib/lib-stdwin/filewin.py | 20 - Lib/lib-stdwin/formatter.py | 207 --- Lib/lib-stdwin/gwin.py | 110 -- Lib/lib-stdwin/listwin.py | 47 - Lib/lib-stdwin/mainloop.py | 256 ---- Lib/lib-stdwin/rect.py | 89 -- Lib/lib-stdwin/srcwin.py | 129 -- Lib/lib-stdwin/stdwinevents.py | 61 - Lib/lib-stdwin/stdwinq.py | 53 - Lib/lib-stdwin/tablewin.py | 236 ---- Lib/lib-stdwin/textwin.py | 117 -- Lib/lib-stdwin/wdb.py | 309 ----- Lib/lib-stdwin/wdbframewin.py | 143 -- Lib/lib-stdwin/wdbsrcwin.py | 100 -- Lib/linecache.py | 90 -- Lib/macpath.py | 126 -- Lib/mimetools.py | 112 -- Lib/multifile.py | 117 -- Lib/mutex.py | 58 - Lib/newdir.py | 75 -- Lib/nntplib.py | 367 ------ Lib/os.py | 70 - Lib/ospath.py | 15 - Lib/packmail.py | 88 -- Lib/pdb.doc | 165 --- Lib/pdb.py | 324 ----- Lib/persist.py | 297 ----- Lib/pipes.py | 301 ----- Lib/plat-irix5/AL.py | 60 - Lib/plat-irix5/AWARE.py | 54 - Lib/plat-irix5/CD.py | 34 - Lib/plat-irix5/CL.py | 236 ---- Lib/plat-irix5/DEVICE.py | 400 ------ Lib/plat-irix5/FL.py | 289 ---- Lib/plat-irix5/GET.py | 59 - Lib/plat-irix5/GL.py | 393 ------ Lib/plat-irix5/GLWS.py | 12 - Lib/plat-irix5/SV.py | 120 -- Lib/plat-irix5/cddb.py | 158 --- Lib/plat-irix5/cdplayer.py | 89 -- Lib/plat-irix5/flp.doc | 117 -- Lib/plat-irix5/flp.py | 465 ------- Lib/plat-irix5/panel.py | 281 ---- Lib/plat-irix5/panelparser.py | 128 -- Lib/plat-irix5/readcd.doc | 104 -- Lib/plat-irix5/readcd.py | 232 ---- Lib/plat-irix5/torgb.py | 97 -- Lib/plat-sunos4/SUNAUDIODEV.py | 38 - Lib/poly.py | 55 - Lib/posixpath.py | 294 ----- Lib/profile.doc | 74 -- Lib/profile.py | 389 ------ Lib/rand.py | 13 - Lib/regex_syntax.py | 41 - Lib/regexp.py | 38 - Lib/regsub.py | 147 --- Lib/repr.py | 82 -- Lib/rfc822.py | 209 --- Lib/sched.py | 100 -- Lib/shutil.py | 69 - Lib/stat.py | 88 -- Lib/statcache.py | 86 -- Lib/stdwin/Abstract.py | 63 - Lib/stdwin/BoxParent.py | 40 - Lib/stdwin/Buttons.py | 411 ------ Lib/stdwin/CSplit.py | 69 - Lib/stdwin/DirList.py | 58 - Lib/stdwin/FormSplit.py | 58 - Lib/stdwin/HVSplit.py | 62 - Lib/stdwin/Histogram.py | 36 - Lib/stdwin/Sliders.py | 174 --- Lib/stdwin/Soundogram.py | 36 - Lib/stdwin/Split.py | 211 --- Lib/stdwin/StripChart.py | 70 - Lib/stdwin/TextEdit.py | 126 -- Lib/stdwin/TransParent.py | 123 -- Lib/stdwin/VUMeter.py | 47 - Lib/stdwin/WindowParent.py | 189 --- Lib/stdwin/WindowSched.py | 58 - Lib/stdwin/anywin.py | 14 - Lib/stdwin/basewin.py | 64 - Lib/stdwin/dirwin.py | 29 - Lib/stdwin/filewin.py | 20 - Lib/stdwin/formatter.py | 207 --- Lib/stdwin/gwin.py | 110 -- Lib/stdwin/listwin.py | 47 - Lib/stdwin/mainloop.py | 256 ---- Lib/stdwin/rect.py | 89 -- Lib/stdwin/srcwin.py | 129 -- Lib/stdwin/stdwinevents.py | 61 - Lib/stdwin/stdwinq.py | 53 - Lib/stdwin/tablewin.py | 236 ---- Lib/stdwin/textwin.py | 117 -- Lib/stdwin/wdb.py | 309 ----- Lib/stdwin/wdbframewin.py | 143 -- Lib/stdwin/wdbsrcwin.py | 100 -- Lib/string.py | 253 ---- Lib/stringold.py | 253 ---- Lib/sunau.py | 472 ------- Lib/sunaudio.py | 46 - Lib/sunos4/SUNAUDIODEV.py | 38 - Lib/symbol.py | 60 - Lib/tb.py | 173 --- Lib/tempfile.py | 59 - Lib/test/autotest.py | 67 - Lib/test/test_b1.py | 180 --- Lib/test/test_b2.py | 192 --- Lib/test/test_builtin.py | 13 - Lib/test/test_exceptions.py | 92 -- Lib/test/test_grammar.py | 405 ------ Lib/test/test_md5.py | 24 - Lib/test/test_opcodes.py | 23 - Lib/test/test_operations.py | 5 - Lib/test/test_select.py | 23 - Lib/test/test_support.py | 41 - Lib/test/test_types.py | 175 --- Lib/test/testall.out | 141 -- Lib/test/testall.py | 32 - Lib/toaiff.py | 101 -- Lib/token.py | 50 - Lib/tokenize.py | 63 - Lib/tzparse.py | 82 -- Lib/util.py | 25 - Lib/whatsound.py | 270 ---- Lib/whrandom.py | 104 -- Lib/zmod.py | 94 -- Mac/Lib/maccache.py | 61 - Makefile.in | 38 - Modules/version.c | 396 ------ Objects/Makefile.in | 68 - Parser/Makefile.in | 75 -- Parser/myreadline.c | 119 -- Python/Makefile.in | 81 -- Python/dup2.c | 31 - Python/getmtime.c | 41 - Python/memmove.c | 51 - Python/mystrtoul.c | 156 --- README | 61 - Tools/scripts/byteyears.py | 57 - Tools/scripts/checkpyc.py | 70 - Tools/scripts/classfix.py | 189 --- Tools/scripts/copytime.py | 25 - Tools/scripts/dutree.doc | 54 - Tools/scripts/dutree.py | 55 - Tools/scripts/eptags.py | 50 - Tools/scripts/findlinksto.py | 29 - Tools/scripts/fixcid.py | 303 ----- Tools/scripts/fixps.py | 32 - Tools/scripts/h2py.py | 49 - Tools/scripts/linktree.py | 76 -- Tools/scripts/lll.py | 25 - Tools/scripts/methfix.py | 174 --- Tools/scripts/mkreal.py | 65 - Tools/scripts/objgraph.py | 215 --- Tools/scripts/pdeps.py | 167 --- Tools/scripts/ptags.py | 50 - Tools/scripts/suff.py | 29 - Tools/scripts/which.py | 53 - Tools/scripts/xxci.py | 118 -- configure | 1347 ------------------- configure.in | 77 -- 480 files changed, 78940 deletions(-) delete mode 100644 Demo/README delete mode 100755 Demo/classes/Complex.py delete mode 100755 Demo/classes/Dates.py delete mode 100755 Demo/classes/Dbm.py delete mode 100644 Demo/classes/README delete mode 100755 Demo/classes/Range.py delete mode 100755 Demo/classes/Rat.py delete mode 100755 Demo/classes/Rev.py delete mode 100755 Demo/classes/Vec.py delete mode 100755 Demo/classes/bitvec.py delete mode 100755 Demo/classes/class.doc delete mode 100755 Demo/cwilib/cwilib.py delete mode 100755 Demo/cwilib/form.py delete mode 100755 Demo/cwilib/telnetlib.py delete mode 100755 Demo/cwilib/vt100.py delete mode 100755 Demo/cwilib/vt100win.py delete mode 100644 Demo/rpc/MANIFEST delete mode 100644 Demo/rpc/README delete mode 100644 Demo/rpc/T.py delete mode 100644 Demo/rpc/mountclient.py delete mode 100644 Demo/rpc/nfsclient.py delete mode 100644 Demo/rpc/rnusersclient.py delete mode 100644 Demo/rpc/rpc.py delete mode 100755 Demo/rpc/test delete mode 100644 Demo/rpc/xdr.py delete mode 100644 Demo/scripts/README delete mode 100755 Demo/scripts/eqfix.py delete mode 100755 Demo/scripts/fact.py delete mode 100755 Demo/scripts/freeze.py delete mode 100755 Demo/scripts/from.py delete mode 100755 Demo/scripts/lpwatch.py delete mode 100755 Demo/scripts/makedir.py delete mode 100755 Demo/scripts/markov.py delete mode 100755 Demo/scripts/mkrcs.py delete mode 100755 Demo/scripts/pi.py delete mode 100755 Demo/scripts/pp.py delete mode 100755 Demo/scripts/primes.py delete mode 100755 Demo/scripts/update.py delete mode 100755 Demo/scripts/wh.py delete mode 100644 Demo/sgi/al/README delete mode 100755 Demo/sgi/al/alwatch.py delete mode 100755 Demo/sgi/al/broadcast.py delete mode 100755 Demo/sgi/al/cmpaf.py delete mode 100755 Demo/sgi/al/cmpaf_form.fd delete mode 100755 Demo/sgi/al/intercom.py delete mode 100755 Demo/sgi/al/listen.py delete mode 100755 Demo/sgi/al/names.py delete mode 100755 Demo/sgi/al/playaiff.py delete mode 100755 Demo/sgi/al/playback.py delete mode 100755 Demo/sgi/al/playold.py delete mode 100755 Demo/sgi/al/radio.py delete mode 100755 Demo/sgi/al/rec_play.py delete mode 100755 Demo/sgi/al/record.py delete mode 100755 Demo/sgi/al/unicast.py delete mode 100755 Demo/sgi/al/x.py delete mode 100644 Demo/sgi/audio/README delete mode 100755 Demo/sgi/audio/play.py delete mode 100644 Demo/sgi/audio_stdwin/README delete mode 100755 Demo/sgi/audio_stdwin/jukebox.py delete mode 100755 Demo/sgi/audio_stdwin/rec.py delete mode 100755 Demo/sgi/audio_stdwin/vumeter.py delete mode 100755 Demo/sgi/cd/CD.doc delete mode 100644 Demo/sgi/cd/README delete mode 100755 Demo/sgi/cd/cdaiff.py delete mode 100755 Demo/sgi/cd/cdwin.py delete mode 100755 Demo/sgi/cd/listcd.py delete mode 100755 Demo/sgi/cd/playcd.py delete mode 100755 Demo/sgi/cd/recvcd.py delete mode 100755 Demo/sgi/cd/sendcd.py delete mode 100755 Demo/sgi/flp/test_cb.fd delete mode 100755 Demo/sgi/flp/test_cb.py delete mode 100755 Demo/sgi/flp/test_nocb.fd delete mode 100755 Demo/sgi/flp/test_nocb.py delete mode 100644 Demo/sgi/gl/README delete mode 100755 Demo/sgi/gl/backface.py delete mode 100644 Demo/sgi/gl/glstdwin/fontchart.py delete mode 100644 Demo/sgi/gl/glstdwin/glstdwdraw.py delete mode 100644 Demo/sgi/gl/glstdwin/glstdwin.py delete mode 100644 Demo/sgi/gl/glstdwin/glstdwmenu.py delete mode 100644 Demo/sgi/gl/glstdwin/glstdwwin.py delete mode 100644 Demo/sgi/gl/glstdwin/stdwingl.py delete mode 100644 Demo/sgi/gl/glstdwin/tcolor.py delete mode 100644 Demo/sgi/gl/glstdwin/tglsw.py delete mode 100644 Demo/sgi/gl/glstdwin/tmenu.py delete mode 100755 Demo/sgi/gl/kites.py delete mode 100755 Demo/sgi/gl/kunst.py delete mode 100755 Demo/sgi/gl/mclock.doc delete mode 100755 Demo/sgi/gl/mclock.py delete mode 100755 Demo/sgi/gl/mixing.py delete mode 100755 Demo/sgi/gl/nurbs.py delete mode 100755 Demo/sgi/gl/zrgb.py delete mode 100644 Demo/sgi/sv/README delete mode 100755 Demo/sgi/sv/burstcapt.py delete mode 100755 Demo/sgi/sv/contcapt.py delete mode 100755 Demo/sgi/sv/rgbgrab.py delete mode 100755 Demo/sgi/sv/simpleinput.py delete mode 100755 Demo/sgi/video/.cvsignore delete mode 100755 Demo/sgi/video/DisplayVideoIn.py delete mode 100755 Demo/sgi/video/Dsend.py delete mode 100755 Demo/sgi/video/IN.py delete mode 100755 Demo/sgi/video/LiveVideoIn.py delete mode 100755 Demo/sgi/video/LiveVideoOut.py delete mode 100755 Demo/sgi/video/Makefile delete mode 100755 Demo/sgi/video/OldVcopy.py delete mode 100644 Demo/sgi/video/README delete mode 100755 Demo/sgi/video/VCR.py delete mode 100755 Demo/sgi/video/VFile.py delete mode 100755 Demo/sgi/video/VGrabber.py delete mode 100755 Demo/sgi/video/Vaddcache.py delete mode 100755 Demo/sgi/video/Vb.py delete mode 100644 Demo/sgi/video/VbForm.fd delete mode 100755 Demo/sgi/video/Vcopy.py delete mode 100755 Demo/sgi/video/VcrIndex.py delete mode 100755 Demo/sgi/video/Vedit.py delete mode 100644 Demo/sgi/video/VeditForm.fd delete mode 100755 Demo/sgi/video/Vfix.py delete mode 100755 Demo/sgi/video/Viewer.py delete mode 100755 Demo/sgi/video/Vinfo.py delete mode 100755 Demo/sgi/video/Vmkjpeg.py delete mode 100755 Demo/sgi/video/Vplay.py delete mode 100755 Demo/sgi/video/Vrec.py delete mode 100755 Demo/sgi/video/Vrecb.py delete mode 100755 Demo/sgi/video/Vrecc.py delete mode 100755 Demo/sgi/video/Vreceive.py delete mode 100755 Demo/sgi/video/Vsend.py delete mode 100755 Demo/sgi/video/Vstat.py delete mode 100755 Demo/sgi/video/Vtime.py delete mode 100755 Demo/sgi/video/Vunjpeg.py delete mode 100755 Demo/sgi/video/aplay.py delete mode 100755 Demo/sgi/video/cam.py delete mode 100755 Demo/sgi/video/camcorder.py delete mode 100755 Demo/sgi/video/cmif-film.ms delete mode 100755 Demo/sgi/video/colorsys.py delete mode 100755 Demo/sgi/video/i2v.c delete mode 100755 Demo/sgi/video/imgconv.py delete mode 100755 Demo/sgi/video/makemovie.py delete mode 100755 Demo/sgi/video/rgb2video.py delete mode 100755 Demo/sgi/video/senddefs.py delete mode 100755 Demo/sgi/video/squash.c delete mode 100755 Demo/sgi/video/squash2.c delete mode 100755 Demo/sgi/video/statit.py delete mode 100755 Demo/sgi/video/svgrab24.c delete mode 100755 Demo/sgi/video/syncaudio.py delete mode 100755 Demo/sgi/video/tomono.c delete mode 100755 Demo/sgi/video/tv.py delete mode 100755 Demo/sgi/video/v2i.c delete mode 100755 Demo/sgi/video/vcopy.py delete mode 100755 Demo/sgi/video/video.doc delete mode 100755 Demo/sgi/video/video.py delete mode 100755 Demo/sgi/video/video2rgb.py delete mode 100755 Demo/sgi/video/vinfo.py delete mode 100755 Demo/sgi/video/vpregs.py delete mode 100755 Demo/sgi/video/vtime.py delete mode 100755 Demo/sgi/video/watchcursor.py delete mode 100755 Demo/sockets/ChangeLog delete mode 100644 Demo/sockets/README delete mode 100755 Demo/sockets/broadcast.py delete mode 100755 Demo/sockets/echosvr.py delete mode 100755 Demo/sockets/finger.py delete mode 100755 Demo/sockets/ftp.py delete mode 100755 Demo/sockets/gopher.py delete mode 100755 Demo/sockets/mcast.py delete mode 100755 Demo/sockets/radio.py delete mode 100755 Demo/sockets/telnet.py delete mode 100755 Demo/sockets/throughput.py delete mode 100755 Demo/sockets/udpecho.py delete mode 100755 Demo/stdwin/FormTest.py delete mode 100644 Demo/stdwin/README delete mode 100755 Demo/stdwin/RadioGroups.py delete mode 100755 Demo/stdwin/TestCSplit.py delete mode 100755 Demo/stdwin/TestDirList.py delete mode 100755 Demo/stdwin/TestFormSplit.py delete mode 100755 Demo/stdwin/TestSched.py delete mode 100755 Demo/stdwin/TestTextEdit.py delete mode 100755 Demo/stdwin/clock.py delete mode 100644 Demo/stdwin/ibrowse/README delete mode 100755 Demo/stdwin/ibrowse/dir delete mode 100755 Demo/stdwin/ibrowse/ib delete mode 100755 Demo/stdwin/ibrowse/ib.py delete mode 100755 Demo/stdwin/ibrowse/ibrowse delete mode 100755 Demo/stdwin/ibrowse/ibrowse.py delete mode 100755 Demo/stdwin/ibrowse/icache.py delete mode 100755 Demo/stdwin/ibrowse/ifile.py delete mode 100755 Demo/stdwin/ibrowse/itags.py delete mode 100755 Demo/stdwin/jukebox.py delete mode 100755 Demo/stdwin/lpwin.py delete mode 100755 Demo/stdwin/microedit.py delete mode 100755 Demo/stdwin/miniedit.py delete mode 100755 Demo/stdwin/python.py delete mode 100755 Demo/stdwin/wdiff.py delete mode 100644 Demo/threads/README delete mode 100644 Demo/threads/find.py delete mode 100644 Demo/threads/telnet.py delete mode 100644 Demo/threads/wpi.py delete mode 100755 Doc/.cvsignore delete mode 100644 Doc/Makefile delete mode 100644 Doc/README delete mode 100644 Doc/ext.tex delete mode 100644 Doc/ext/ext.tex delete mode 100644 Doc/fix.el delete mode 100755 Doc/fix_hack delete mode 100644 Doc/info/texipost.dat delete mode 100644 Doc/info/texipre.dat delete mode 100644 Doc/lib.tex delete mode 100644 Doc/lib/lib.tex delete mode 100644 Doc/lib/libtemplate.tex delete mode 100644 Doc/libtemplate.tex delete mode 100644 Doc/myformat.sty delete mode 100644 Doc/partparse.py delete mode 100644 Doc/qua.tex delete mode 100644 Doc/quabib.bib delete mode 100644 Doc/ref.tex delete mode 100644 Doc/ref/ref.tex delete mode 100644 Doc/ref/ref1.tex delete mode 100644 Doc/ref/ref2.tex delete mode 100644 Doc/ref/ref3.tex delete mode 100644 Doc/ref/ref4.tex delete mode 100644 Doc/ref/ref5.tex delete mode 100644 Doc/ref/ref6.tex delete mode 100644 Doc/ref/ref7.tex delete mode 100644 Doc/ref/ref8.tex delete mode 100644 Doc/ref1.tex delete mode 100644 Doc/ref2.tex delete mode 100644 Doc/ref3.tex delete mode 100644 Doc/ref4.tex delete mode 100644 Doc/ref5.tex delete mode 100644 Doc/ref6.tex delete mode 100644 Doc/ref7.tex delete mode 100644 Doc/ref8.tex delete mode 100644 Doc/templates/module.tex delete mode 100644 Doc/texipost.dat delete mode 100644 Doc/texipre.dat delete mode 100644 Doc/text2latex.py delete mode 100644 Doc/tools/fix.el delete mode 100755 Doc/tools/fix_hack delete mode 100644 Doc/tools/partparse.py delete mode 100644 Doc/tools/text2latex.py delete mode 100644 Doc/tut.tex delete mode 100644 Doc/tut/tut.tex delete mode 100644 Grammar/Makefile delete mode 100644 Include/myproto.h delete mode 100644 Include/mytime.h delete mode 100644 Lib/Queue.py delete mode 100644 Lib/UserDict.py delete mode 100644 Lib/UserList.py delete mode 100644 Lib/aifc.py delete mode 100644 Lib/audiodev.py delete mode 100644 Lib/bdb.py delete mode 100644 Lib/bisect.py delete mode 100755 Lib/builtin.py delete mode 100644 Lib/calendar.py delete mode 100644 Lib/cmd.py delete mode 100644 Lib/cmp.py delete mode 100644 Lib/cmpcache.py delete mode 100644 Lib/codehack.py delete mode 100644 Lib/colorsys.py delete mode 100644 Lib/commands.py delete mode 100644 Lib/dircache.py delete mode 100644 Lib/dircmp.py delete mode 100644 Lib/dis.py delete mode 100644 Lib/dump.py delete mode 100644 Lib/emacs.py delete mode 100644 Lib/fnmatch.py delete mode 100644 Lib/fpformat.py delete mode 100644 Lib/ftplib.py delete mode 100644 Lib/getopt.py delete mode 100644 Lib/glob.py delete mode 100644 Lib/grep.py delete mode 100644 Lib/imghdr.py delete mode 100755 Lib/importall.py delete mode 100755 Lib/irix5/AL.py delete mode 100755 Lib/irix5/AWARE.py delete mode 100755 Lib/irix5/CD.py delete mode 100755 Lib/irix5/CL.py delete mode 100755 Lib/irix5/DEVICE.py delete mode 100755 Lib/irix5/FL.py delete mode 100755 Lib/irix5/GET.py delete mode 100755 Lib/irix5/GL.py delete mode 100755 Lib/irix5/GLWS.py delete mode 100755 Lib/irix5/SV.py delete mode 100755 Lib/irix5/auds.py delete mode 100755 Lib/irix5/cddb.py delete mode 100755 Lib/irix5/cdplayer.py delete mode 100755 Lib/irix5/flp.doc delete mode 100755 Lib/irix5/flp.py delete mode 100755 Lib/irix5/panel.py delete mode 100755 Lib/irix5/panelparser.py delete mode 100755 Lib/irix5/readcd.doc delete mode 100755 Lib/irix5/readcd.py delete mode 100755 Lib/irix5/torgb.py delete mode 100644 Lib/lib-old/codehack.py delete mode 100644 Lib/lib-old/dump.py delete mode 100644 Lib/lib-old/grep.py delete mode 100644 Lib/lib-old/newdir.py delete mode 100644 Lib/lib-old/packmail.py delete mode 100644 Lib/lib-old/rand.py delete mode 100644 Lib/lib-old/tb.py delete mode 100644 Lib/lib-old/util.py delete mode 100644 Lib/lib-old/whatsound.py delete mode 100644 Lib/lib-stdwin/Abstract.py delete mode 100644 Lib/lib-stdwin/BoxParent.py delete mode 100644 Lib/lib-stdwin/Buttons.py delete mode 100644 Lib/lib-stdwin/CSplit.py delete mode 100644 Lib/lib-stdwin/DirList.py delete mode 100644 Lib/lib-stdwin/FormSplit.py delete mode 100644 Lib/lib-stdwin/HVSplit.py delete mode 100644 Lib/lib-stdwin/Histogram.py delete mode 100644 Lib/lib-stdwin/Sliders.py delete mode 100644 Lib/lib-stdwin/Soundogram.py delete mode 100644 Lib/lib-stdwin/Split.py delete mode 100644 Lib/lib-stdwin/StripChart.py delete mode 100644 Lib/lib-stdwin/TextEdit.py delete mode 100644 Lib/lib-stdwin/TransParent.py delete mode 100644 Lib/lib-stdwin/VUMeter.py delete mode 100644 Lib/lib-stdwin/WindowParent.py delete mode 100644 Lib/lib-stdwin/WindowSched.py delete mode 100644 Lib/lib-stdwin/anywin.py delete mode 100644 Lib/lib-stdwin/basewin.py delete mode 100644 Lib/lib-stdwin/dirwin.py delete mode 100644 Lib/lib-stdwin/filewin.py delete mode 100644 Lib/lib-stdwin/formatter.py delete mode 100644 Lib/lib-stdwin/gwin.py delete mode 100644 Lib/lib-stdwin/listwin.py delete mode 100644 Lib/lib-stdwin/mainloop.py delete mode 100644 Lib/lib-stdwin/rect.py delete mode 100644 Lib/lib-stdwin/srcwin.py delete mode 100644 Lib/lib-stdwin/stdwinevents.py delete mode 100644 Lib/lib-stdwin/stdwinq.py delete mode 100644 Lib/lib-stdwin/tablewin.py delete mode 100644 Lib/lib-stdwin/textwin.py delete mode 100644 Lib/lib-stdwin/wdb.py delete mode 100644 Lib/lib-stdwin/wdbframewin.py delete mode 100644 Lib/lib-stdwin/wdbsrcwin.py delete mode 100644 Lib/linecache.py delete mode 100644 Lib/macpath.py delete mode 100644 Lib/mimetools.py delete mode 100644 Lib/multifile.py delete mode 100644 Lib/mutex.py delete mode 100644 Lib/newdir.py delete mode 100644 Lib/nntplib.py delete mode 100644 Lib/os.py delete mode 100644 Lib/ospath.py delete mode 100644 Lib/packmail.py delete mode 100644 Lib/pdb.doc delete mode 100755 Lib/pdb.py delete mode 100755 Lib/persist.py delete mode 100644 Lib/pipes.py delete mode 100755 Lib/plat-irix5/AL.py delete mode 100755 Lib/plat-irix5/AWARE.py delete mode 100755 Lib/plat-irix5/CD.py delete mode 100755 Lib/plat-irix5/CL.py delete mode 100755 Lib/plat-irix5/DEVICE.py delete mode 100755 Lib/plat-irix5/FL.py delete mode 100755 Lib/plat-irix5/GET.py delete mode 100755 Lib/plat-irix5/GL.py delete mode 100755 Lib/plat-irix5/GLWS.py delete mode 100755 Lib/plat-irix5/SV.py delete mode 100755 Lib/plat-irix5/cddb.py delete mode 100755 Lib/plat-irix5/cdplayer.py delete mode 100755 Lib/plat-irix5/flp.doc delete mode 100755 Lib/plat-irix5/flp.py delete mode 100755 Lib/plat-irix5/panel.py delete mode 100755 Lib/plat-irix5/panelparser.py delete mode 100755 Lib/plat-irix5/readcd.doc delete mode 100755 Lib/plat-irix5/readcd.py delete mode 100755 Lib/plat-irix5/torgb.py delete mode 100755 Lib/plat-sunos4/SUNAUDIODEV.py delete mode 100644 Lib/poly.py delete mode 100644 Lib/posixpath.py delete mode 100644 Lib/profile.doc delete mode 100755 Lib/profile.py delete mode 100644 Lib/rand.py delete mode 100644 Lib/regex_syntax.py delete mode 100644 Lib/regexp.py delete mode 100644 Lib/regsub.py delete mode 100644 Lib/repr.py delete mode 100644 Lib/rfc822.py delete mode 100644 Lib/sched.py delete mode 100644 Lib/shutil.py delete mode 100644 Lib/stat.py delete mode 100644 Lib/statcache.py delete mode 100755 Lib/stdwin/Abstract.py delete mode 100755 Lib/stdwin/BoxParent.py delete mode 100755 Lib/stdwin/Buttons.py delete mode 100755 Lib/stdwin/CSplit.py delete mode 100755 Lib/stdwin/DirList.py delete mode 100755 Lib/stdwin/FormSplit.py delete mode 100755 Lib/stdwin/HVSplit.py delete mode 100755 Lib/stdwin/Histogram.py delete mode 100755 Lib/stdwin/Sliders.py delete mode 100755 Lib/stdwin/Soundogram.py delete mode 100755 Lib/stdwin/Split.py delete mode 100755 Lib/stdwin/StripChart.py delete mode 100755 Lib/stdwin/TextEdit.py delete mode 100755 Lib/stdwin/TransParent.py delete mode 100755 Lib/stdwin/VUMeter.py delete mode 100755 Lib/stdwin/WindowParent.py delete mode 100755 Lib/stdwin/WindowSched.py delete mode 100755 Lib/stdwin/anywin.py delete mode 100755 Lib/stdwin/basewin.py delete mode 100755 Lib/stdwin/dirwin.py delete mode 100755 Lib/stdwin/filewin.py delete mode 100755 Lib/stdwin/formatter.py delete mode 100755 Lib/stdwin/gwin.py delete mode 100755 Lib/stdwin/listwin.py delete mode 100755 Lib/stdwin/mainloop.py delete mode 100755 Lib/stdwin/rect.py delete mode 100755 Lib/stdwin/srcwin.py delete mode 100755 Lib/stdwin/stdwinevents.py delete mode 100755 Lib/stdwin/stdwinq.py delete mode 100755 Lib/stdwin/tablewin.py delete mode 100755 Lib/stdwin/textwin.py delete mode 100755 Lib/stdwin/wdb.py delete mode 100755 Lib/stdwin/wdbframewin.py delete mode 100755 Lib/stdwin/wdbsrcwin.py delete mode 100644 Lib/string.py delete mode 100644 Lib/stringold.py delete mode 100644 Lib/sunau.py delete mode 100644 Lib/sunaudio.py delete mode 100755 Lib/sunos4/SUNAUDIODEV.py delete mode 100755 Lib/symbol.py delete mode 100644 Lib/tb.py delete mode 100644 Lib/tempfile.py delete mode 100644 Lib/test/autotest.py delete mode 100644 Lib/test/test_b1.py delete mode 100644 Lib/test/test_b2.py delete mode 100644 Lib/test/test_builtin.py delete mode 100644 Lib/test/test_exceptions.py delete mode 100644 Lib/test/test_grammar.py delete mode 100644 Lib/test/test_md5.py delete mode 100644 Lib/test/test_opcodes.py delete mode 100644 Lib/test/test_operations.py delete mode 100644 Lib/test/test_select.py delete mode 100644 Lib/test/test_support.py delete mode 100644 Lib/test/test_types.py delete mode 100644 Lib/test/testall.out delete mode 100644 Lib/test/testall.py delete mode 100644 Lib/toaiff.py delete mode 100755 Lib/token.py delete mode 100644 Lib/tokenize.py delete mode 100644 Lib/tzparse.py delete mode 100644 Lib/util.py delete mode 100644 Lib/whatsound.py delete mode 100644 Lib/whrandom.py delete mode 100644 Lib/zmod.py delete mode 100644 Mac/Lib/maccache.py delete mode 100644 Makefile.in delete mode 100644 Modules/version.c delete mode 100644 Objects/Makefile.in delete mode 100644 Parser/Makefile.in delete mode 100644 Parser/myreadline.c delete mode 100644 Python/Makefile.in delete mode 100644 Python/dup2.c delete mode 100644 Python/getmtime.c delete mode 100644 Python/memmove.c delete mode 100644 Python/mystrtoul.c delete mode 100644 README delete mode 100755 Tools/scripts/byteyears.py delete mode 100755 Tools/scripts/checkpyc.py delete mode 100755 Tools/scripts/classfix.py delete mode 100755 Tools/scripts/copytime.py delete mode 100644 Tools/scripts/dutree.doc delete mode 100755 Tools/scripts/dutree.py delete mode 100755 Tools/scripts/eptags.py delete mode 100755 Tools/scripts/findlinksto.py delete mode 100755 Tools/scripts/fixcid.py delete mode 100755 Tools/scripts/fixps.py delete mode 100755 Tools/scripts/h2py.py delete mode 100755 Tools/scripts/linktree.py delete mode 100755 Tools/scripts/lll.py delete mode 100755 Tools/scripts/methfix.py delete mode 100755 Tools/scripts/mkreal.py delete mode 100755 Tools/scripts/objgraph.py delete mode 100755 Tools/scripts/pdeps.py delete mode 100755 Tools/scripts/ptags.py delete mode 100755 Tools/scripts/suff.py delete mode 100755 Tools/scripts/which.py delete mode 100755 Tools/scripts/xxci.py delete mode 100755 configure delete mode 100644 configure.in diff --git a/Demo/README b/Demo/README deleted file mode 100644 index a6debe8d22..0000000000 --- a/Demo/README +++ /dev/null @@ -1,51 +0,0 @@ -This directory contains various demonstrations of what you can do with -Python. Most demos are grouped sub(sub*)directories according to -required optional built-in modules or specific platform; there is also -a set of generally useful scripts and there are some more-or-less -complete applications. - -classes Some examples of how to use classes. - -ibrowse An Emacs info file browser (uses stdwin). - See also ../doc (the Python library documentation can - be converted to info format). - -md5test Test program for the optional md5 module. - -rpc A set of classes for building clients and servers for - Sun RPC. - -rsa An RSA public-key cryptosystem (needs mpz and md5). - -scripts Some useful Python scripts that I put in my bin - directory. No optional built-in modules needed. - -sockets Examples for the new built-in module 'socket'. - -sgi Demos that only run on Silicon Graphics machines. - These require at least one of the optional built-in - modules that only make sense for the SGI, such as - 'gl', 'al', and 'sv'. Split in subdirectories - per subject. - -stdwin Demos that use the STDWIN library. Require the 'stdwin' - built-in module. - -threads Demos that use the 'thread' module. (Currently these - only run on SGIs, but this may change in the future.) - -www Browsers for CERN's distributed hypertext system - World-Wide Web (one with a stdwin-based user - interface, one for dumb ttys). Also contains a - primitive gopher client and an ftp client. - See also ../doc (the Python library documentation can - be converted to WWW's "HTML" format). - -WARNING: many scripts are executable and have a first line saying - - #! /usr/local/bin/python - -This is unlikely to give good results unless you've really installed -the latest version python there. Edit the first line before -installing such scripts; to try them out, you can just say "python -foo.py" or enter python interactively and say "import foo". diff --git a/Demo/classes/Complex.py b/Demo/classes/Complex.py deleted file mode 100755 index b7ba2e0f5c..0000000000 --- a/Demo/classes/Complex.py +++ /dev/null @@ -1,85 +0,0 @@ -# Complex numbers - - -from math import sqrt - - -class complex: - - def __init__(self, re, im): - self.re = float(re) - self.im = float(im) - - def __coerce__(self, other): - if type(other) == type(self): - if other.__class__ == self.__class__: - return self, other - else: - raise TypeError, 'cannot coerce to complex' - else: - # The cast to float() may raise an exception! - return self, complex(float(other), 0.0) - - def __repr__(self): - return 'complex' + `self.re, self.im` - - def __cmp__(a, b): - a = a.__abs__() - b = b.__abs__() - return (a > b) - (a < b) - - def __float__(self): - if self.im: - raise ValueError, 'cannot convert complex to float' - return float(self.re) - - def __long__(self): - return long(float(self)) - - def __int__(self): - return int(float(self)) - - def __abs__(self): - # XXX overflow? - return sqrt(self.re*self.re + self.im*self.im) - - def __add__(a, b): - return complex(a.re + b.re, a.im + b.im) - - def __sub__(a, b): - return complex(a.re - b.re, a.im - b.im) - - def __mul__(a, b): - return complex(a.re*b.re - a.im*b.im, a.re*b.im + a.im*b.re) - - def __div__(a, b): - q = (b.re*b.re + b.im*b.im) - re = (a.re*b.re + a.im*b.im) / q - im = (a.im*b.re - b.im*a.re) / q - return complex(re, im) - - def __neg__(self): - return complex(-self.re, -self.im) - - -def test(): - a = complex(2, 0) - b = complex(3, 4) - print a - print b - print a+b - print a-b - print a*b - print a/b - print b+a - print b-a - print b*a - print b/a - i = complex(0, 1) - print i, i*i, i*i*i, i*i*i*i - j = complex(1, 1) - print j, j*j, j*j*j, j*j*j*j - print abs(j), abs(j*j), abs(j*j*j), abs(j*j*j*j) - print i/-i - -test() diff --git a/Demo/classes/Dates.py b/Demo/classes/Dates.py deleted file mode 100755 index 4e8bbf709c..0000000000 --- a/Demo/classes/Dates.py +++ /dev/null @@ -1,233 +0,0 @@ -# Class Date supplies date objects that support date arithmetic. -# -# Date(month,day,year) returns a Date object. An instance prints as, -# e.g., 'Mon 16 Aug 1993'. -# -# Addition, subtraction, comparison operators, min, max, and sorting -# all work as expected for date objects: int+date or date+int returns -# the date `int' days from `date'; date+date raises an exception; -# date-int returns the date `int' days before `date'; date2-date1 returns -# an integer, the number of days from date1 to date2; int-date raises an -# exception; date1 < date2 is true iff date1 occurs before date2 (& -# similarly for other comparisons); min(date1,date2) is the earlier of -# the two dates and max(date1,date2) the later; and date objects can be -# used as dictionary keys. -# -# Date objects support one visible method, date.weekday(). This returns -# the day of the week the date falls on, as a string. -# -# Date objects also have 4 (conceptually) read-only data attributes: -# .month in 1..12 -# .day in 1..31 -# .year int or long int -# .ord the ordinal of the date relative to an arbitrary staring point -# -# The Dates module also supplies function today(), which returns the -# current date as a date object. -# -# Those entranced by calendar trivia will be disappointed, as no attempt -# has been made to accommodate the Julian (etc) system. On the other -# hand, at least this package knows that 2000 is a leap year but 2100 -# isn't, and works fine for years with a hundred decimal digits . - -# Tim Peters tim@ksr.com -# not speaking for Kendall Square Research Corp - -_MONTH_NAMES = [ 'January', 'February', 'March', 'April', 'May', - 'June', 'July', 'August', 'September', 'October', - 'November', 'December' ] - -_DAY_NAMES = [ 'Friday', 'Saturday', 'Sunday', 'Monday', - 'Tuesday', 'Wednesday', 'Thursday' ] - -_DAYS_IN_MONTH = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ] - -_DAYS_BEFORE_MONTH = [] -dbm = 0 -for dim in _DAYS_IN_MONTH: - _DAYS_BEFORE_MONTH.append(dbm) - dbm = dbm + dim -del dbm, dim - -_INT_TYPES = type(1), type(1L) - -def _is_leap( year ): # 1 if leap year, else 0 - if year % 4 != 0: return 0 - if year % 400 == 0: return 1 - return year % 100 != 0 - -def _days_in_year( year ): # number of days in year - return 365 + _is_leap(year) - -def _days_before_year( year ): # number of days before year - return year*365L + (year+3)/4 - (year+99)/100 + (year+399)/400 - -def _days_in_month( month, year ): # number of days in month of year - if month == 2 and _is_leap(year): return 29 - return _DAYS_IN_MONTH[month-1] - -def _days_before_month( month, year ): # number of days in year before month - return _DAYS_BEFORE_MONTH[month-1] + (month > 2 and _is_leap(year)) - -def _date2num( date ): # compute ordinal of date.month,day,year - return _days_before_year( date.year ) + \ - _days_before_month( date.month, date.year ) + \ - date.day - -_DI400Y = _days_before_year( 400 ) # number of days in 400 years - -def _num2date( n ): # return date with ordinal n - if type(n) not in _INT_TYPES: - raise TypeError, 'argument must be integer: ' + `type(n)` - - ans = Date(1,1,1) # arguments irrelevant; just getting a Date obj - ans.ord = n - - n400 = (n-1)/_DI400Y # # of 400-year blocks preceding - year, n = 400 * n400, n - _DI400Y * n400 - more = n / 365 - dby = _days_before_year( more ) - if dby >= n: - more = more - 1 - dby = dby - _days_in_year( more ) - year, n = year + more, int(n - dby) - - try: year = int(year) # chop to int, if it fits - except ValueError: pass - - month = min( n/29 + 1, 12 ) - dbm = _days_before_month( month, year ) - if dbm >= n: - month = month - 1 - dbm = dbm - _days_in_month( month, year ) - - ans.month, ans.day, ans.year = month, n-dbm, year - return ans - -def _num2day( n ): # return weekday name of day with ordinal n - return _DAY_NAMES[ int(n % 7) ] - - -class Date: - def __init__( self, month, day, year ): - if not 1 <= month <= 12: - raise ValueError, 'month must be in 1..12: ' + `month` - dim = _days_in_month( month, year ) - if not 1 <= day <= dim: - raise ValueError, 'day must be in 1..' + `dim` + ': ' + `day` - self.month, self.day, self.year = month, day, year - self.ord = _date2num( self ) - - def __cmp__( self, other ): - return cmp( self.ord, other.ord ) - - # define a hash function so dates can be used as dictionary keys - def __hash__( self ): - return hash( self.ord ) - - # print as, e.g., Mon 16 Aug 1993 - def __repr__( self ): - return '%.3s %2d %.3s ' % ( - self.weekday(), - self.day, - _MONTH_NAMES[self.month-1] ) + `self.year` - - # automatic coercion is a pain for date arithmetic, since e.g. - # date-date and date-int mean different things. So, in order to - # sneak integers past Python's coercion rules without losing the info - # that they're really integers (& not dates!), integers are disguised - # as instances of the derived class _DisguisedInt. That this works - # relies on undocumented behavior of Python's coercion rules. - def __coerce__( self, other ): - if type(other) in _INT_TYPES: - return self, _DisguisedInt(other) - # if another Date, fine - if type(other) is type(self) and other.__class__ is Date: - return self, other - - # Python coerces int+date, but not date+int; in the former case, - # _DisguisedInt.__add__ handles it, so we only need to do - # date+int here - def __add__( self, n ): - if type(n) not in _INT_TYPES: - raise TypeError, 'can\'t add ' + `type(n)` + ' to date' - return _num2date( self.ord + n ) - - # Python coerces all of int-date, date-int and date-date; the first - # case winds up in _DisguisedInt.__sub__, leaving the latter two - # for us - def __sub__( self, other ): - if other.__class__ is _DisguisedInt: # date-int - return _num2date( self.ord - other.ord ) - else: - return self.ord - other.ord # date-date - - def weekday( self ): - return _num2day( self.ord ) - -# see comments before Date.__add__ -class _DisguisedInt( Date ): - def __init__( self, n ): - self.ord = n - - # handle int+date - def __add__( self, other ): - return other.__add__( self.ord ) - - # complain about int-date - def __sub__( self, other ): - raise TypeError, 'Can\'t subtract date from integer' - -def today(): - import time - local = time.localtime(time.time()) - return Date( local[1], local[2], local[0] ) - -DateTestError = 'DateTestError' -def test( firstyear, lastyear ): - a = Date(9,30,1913) - b = Date(9,30,1914) - if `a` != 'Tue 30 Sep 1913': - raise DateTestError, '__repr__ failure' - if (not a < b) or a == b or a > b or b != b or \ - a != 698982 or 698982 != a or \ - (not a > 5) or (not 5 < a): - raise DateTestError, '__cmp__ failure' - if a+365 != b or 365+a != b: - raise DateTestError, '__add__ failure' - if b-a != 365 or b-365 != a: - raise DateTestError, '__sub__ failure' - try: - x = 1 - a - raise DateTestError, 'int-date should have failed' - except TypeError: - pass - try: - x = a + b - raise DateTestError, 'date+date should have failed' - except TypeError: - pass - if a.weekday() != 'Tuesday': - raise DateTestError, 'weekday() failure' - if max(a,b) is not b or min(a,b) is not a: - raise DateTestError, 'min/max failure' - d = {a-1:b, b:a+1} - if d[b-366] != b or d[a+(b-a)] != Date(10,1,1913): - raise DateTestError, 'dictionary failure' - - # verify date<->number conversions for first and last days for - # all years in firstyear .. lastyear - - lord = _days_before_year( firstyear ) - y = firstyear - while y <= lastyear: - ford = lord + 1 - lord = ford + _days_in_year(y) - 1 - fd, ld = Date(1,1,y), Date(12,31,y) - if (fd.ord,ld.ord) != (ford,lord): - raise DateTestError, ('date->num failed', y) - fd, ld = _num2date(ford), _num2date(lord) - if (1,1,y,12,31,y) != \ - (fd.month,fd.day,fd.year,ld.month,ld.day,ld.year): - raise DateTestError, ('num->date failed', y) - y = y + 1 diff --git a/Demo/classes/Dbm.py b/Demo/classes/Dbm.py deleted file mode 100755 index 8d7fe0f8f4..0000000000 --- a/Demo/classes/Dbm.py +++ /dev/null @@ -1,66 +0,0 @@ -# A wrapper around the (optional) built-in class dbm, supporting keys -# and values of almost any type instead of just string. -# (Actually, this works only for keys and values that can be read back -# correctly after being converted to a string.) - - -class Dbm: - - def __init__(self, filename, mode, perm): - import dbm - self.db = dbm.open(filename, mode, perm) - - def __repr__(self): - s = '' - for key in self.keys(): - t = `key` + ': ' + `self[key]` - if s: t = ', ' + t - s = s + t - return '{' + s + '}' - - def __len__(self): - return len(self.db) - - def __getitem__(self, key): - return eval(self.db[`key`]) - - def __setitem__(self, key, value): - self.db[`key`] = `value` - - def __delitem__(self, key): - del self.db[`key`] - - def keys(self): - res = [] - for key in self.db.keys(): - res.append(eval(key)) - return res - - def has_key(self, key): - return self.db.has_key(`key`) - - -def test(): - d = Dbm('@dbm', 'rw', 0600) - print d - while 1: - try: - key = input('key: ') - if d.has_key(key): - value = d[key] - print 'currently:', value - value = input('value: ') - if value == None: - del d[key] - else: - d[key] = value - except KeyboardInterrupt: - print '' - print d - except EOFError: - print '[eof]' - break - print d - - -test() diff --git a/Demo/classes/README b/Demo/classes/README deleted file mode 100644 index cca7524891..0000000000 --- a/Demo/classes/README +++ /dev/null @@ -1,14 +0,0 @@ -Examples of classes that implement special operators (see reference manual): - -Complex.py Complex numbers -Dates.py Date manipulation package by Tim Peters -Dbm.py Wrapper around built-in dbm, supporting arbitrary values -Range.py Example of a generator: re-implement built-in range() -Rat.py Rational numbers -Rev.py Yield the reverse of a sequence -Vec.py A simple vector class -bitvec.py A bit-vector class by Jan-Hein B\"uhrman - -(For straightforward examples of basic class features, such as use of -methods and inheritance, see the library code -- especially the window -modules are full of them.) diff --git a/Demo/classes/Range.py b/Demo/classes/Range.py deleted file mode 100755 index e7b6be2c7a..0000000000 --- a/Demo/classes/Range.py +++ /dev/null @@ -1,71 +0,0 @@ -# Example of a generator: re-implement the built-in range function -# without actually constructing the list of values. (It turns out -# that the built-in function is about 20 times faster -- that's why -# it's built-in. :-) - - -# Wrapper function to emulate the complicated range() arguments - -def range(*a): - if len(a) == 1: - start, stop, step = 0, a[0], 1 - elif len(a) == 2: - start, stop = a - step = 1 - elif len(a) == 3: - start, stop, step = a - else: - raise TypeError, 'range() needs 1-3 arguments' - return Range(start, stop, step) - - -# Class implementing a range object. -# To the user the instances feel like immutable sequences -# (and you can't concatenate or slice them) - -class Range: - - # initialization -- should be called only by range() above - def __init__(self, start, stop, step): - if step == 0: - raise ValueError, 'range() called with zero step' - self.start = start - self.stop = stop - self.step = step - self.len = max(0, int((self.stop - self.start) / self.step)) - - # implement `x` and is also used by print x - def __repr__(self): - return 'range' + `self.start, self.stop, self.step` - - # implement len(x) - def __len__(self): - return self.len - - # implement x[i] - def __getitem__(self, i): - if 0 <= i < self.len: - return self.start + self.step * i - else: - raise IndexError, 'range[i] index out of range' - - -# Small test program - -def test(): - import time, builtin - print range(10), range(-10, 10), range(0, 10, 2) - for i in range(100, -100, -10): print i, - print - t1 = time.millitimer() - for i in range(1000): - pass - t2 = time.millitimer() - for i in builtin.range(1000): - pass - t3 = time.millitimer() - print t2-t1, 'msec (class)' - print t3-t2, 'msec (built-in)' - - -test() diff --git a/Demo/classes/Rat.py b/Demo/classes/Rat.py deleted file mode 100755 index d10e4dfac4..0000000000 --- a/Demo/classes/Rat.py +++ /dev/null @@ -1,97 +0,0 @@ -# Rational numbers - - -def rat(num, den): - return Rat(num, den) - - -def gcd(a, b): - while b: - a, b = b, a%b - return a - - -class Rat: - - def __init__(self, num, den): - if den == 0: - raise ZeroDivisionError, 'rat(x, 0)' - g = gcd(num, den) - self.num = num/g - self.den = den/g - - def __repr__(self): - return 'rat' + `self.num, self.den` - - def __cmp__(a, b): - c = a-b - if c.num < 0: - return -1 - if c.num > 0: - return 1 - return 0 - - def __float__(self): - return float(self.num) / float(self.den) - - def __long__(self): - return long(self.num) / long(self.den) - - def __int__(self): - return int(self.num / self.den) - - def __coerce__(a, b): - t = type(b) - if t == type(0): - return a, rat(b, 1) - if t == type(0L): - return a, rat(b, 1L) - if t == type(0.0): - return a.__float__(), b - if t == type(a) and a.__class__ == b.__class__: - return a, b - raise TypeError, 'Rat.__coerce__: bad other arg' - - def __add__(a, b): - if type(b) <> type(a): - a, b = a.__coerce__(b) - return a + b - return rat(a.num*b.den + b.num*a.den, a.den*b.den) - - def __sub__(a, b): - return rat(a.num*b.den - b.num*a.den, a.den*b.den) - - def __mul__(a, b): - if type(b) <> type(a): - a, b = a.__coerce__(b) - return a * b - return rat(a.num*b.num, a.den*b.den) - - def __div__(a, b): - return rat(a.num*b.den, a.den*b.num) - - def __neg__(self): - return rat(-self.num, self.den) - - -def test(): - print rat(-1L, 1) - print rat(1, -1) - a = rat(1, 10) - print int(a), long(a), float(a) - b = rat(2, 5) - l = [a+b, a-b, a*b, a/b] - print l - l.sort() - print l - print rat(0, 1) - print a+1 - print a+1L - print a+1.0 - try: - print rat(1, 0) - raise SystemError, 'should have been ZeroDivisionError' - except ZeroDivisionError: - print 'OK' - -test() diff --git a/Demo/classes/Rev.py b/Demo/classes/Rev.py deleted file mode 100755 index c1874c65c5..0000000000 --- a/Demo/classes/Rev.py +++ /dev/null @@ -1,89 +0,0 @@ -# A class which presents the reverse of a sequence without duplicating it. -# From: "Steven D. Majewski" - -# It works on mutable or inmutable sequences. -# -# >>> for c in Rev( 'Hello World!' ) : sys.stdout.write( c ) -# ... else: sys.stdout.write( '\n' ) -# ... -# !dlroW olleH -# -# The .forw is so you can use anonymous sequences in __init__, and still -# keep a reference the forward sequence. ) -# If you give it a non-anonymous mutable sequence, the reverse sequence -# will track the updated values. ( but not reassignment! - another -# good reason to use anonymous values in creating the sequence to avoid -# confusion. Maybe it should be change to copy input sequence to break -# the connection completely ? ) -# -# >>> nnn = range( 0, 3 ) -# >>> rnn = Rev( nnn ) -# >>> for n in rnn: print n -# ... -# 2 -# 1 -# 0 -# >>> for n in range( 4, 6 ): nnn.append( n ) # update nnn -# ... -# >>> for n in rnn: print n # prints reversed updated values -# ... -# 5 -# 4 -# 2 -# 1 -# 0 -# >>> nnn = nnn[1:-1] -# >>> nnn -# [1, 2, 4] -# >>> for n in rnn: print n # prints reversed values of old nnn -# ... -# 5 -# 4 -# 2 -# 1 -# 0 -# >>> -# -# WH = Rev( 'Hello World!' ) -# print WH.forw, WH.back -# nnn = Rev( range( 1, 10 ) ) -# print nnn.forw -# print nnn -# -# produces output: -# -# Hello World! !dlroW olleH -# [1, 2, 3, 4, 5, 6, 7, 8, 9] -# [9, 8, 7, 6, 5, 4, 3, 2, 1] -# -# >>>rrr = Rev( nnn ) -# >>>rrr -# <1, 2, 3, 4, 5, 6, 7, 8, 9> - -from string import joinfields -class Rev: - def __init__( self, seq ): - self.forw = seq - self.back = self - def __len__( self ): - return len( self.forw ) - def __getitem__( self, j ): - return self.forw[ -( j + 1 ) ] - def __repr__( self ): - seq = self.forw - if type(seq) == type( [] ) : - wrap = '[]' - sep = ', ' - elif type(seq) == type( () ) : - wrap = '()' - sep = ', ' - elif type(seq) == type( '' ) : - wrap = '' - sep = '' - else: - wrap = '<>' - sep = ', ' - outstrs = [] - for item in self.back : - outstrs.append( str( item ) ) - return wrap[:1] + joinfields( outstrs, sep ) + wrap[-1:] diff --git a/Demo/classes/Vec.py b/Demo/classes/Vec.py deleted file mode 100755 index 8289bc847e..0000000000 --- a/Demo/classes/Vec.py +++ /dev/null @@ -1,64 +0,0 @@ -# A simple vector class - - -def vec(*v): - return apply(Vec, v) - - -class Vec: - - def __init__(self, *v): - self.v = [] - for x in v: - self.v.append(x) - - - def fromlist(self, v): - self.v = [] - if type(v) <> type([]): - raise TypeError - self.v = v[:] - return self - - - def __repr__(self): - return 'vec(' + `self.v`[1:-1] + ')' - - def __len__(self): - return len(self.v) - - def __getitem__(self, i): - return self.v[i] - - def __add__(a, b): - # Element-wise addition - v = [] - for i in range(len(a)): - v.append(a[i] + b[i]) - return Vec().fromlist(v) - - def __sub__(a, b): - # Element-wise subtraction - v = [] - for i in range(len(a)): - v.append(a[i] - b[i]) - return Vec().fromlist(v) - - def __mul__(self, scalar): - # Multiply by scalar - v = [] - for i in range(len(self.v)): - v.append(self.v[i]*scalar) - return Vec().fromlist(v) - - - -def test(): - a = vec(1, 2, 3) - b = vec(3, 2, 1) - print a - print b - print a+b - print a*3.0 - -test() diff --git a/Demo/classes/bitvec.py b/Demo/classes/bitvec.py deleted file mode 100755 index 69718d7a3e..0000000000 --- a/Demo/classes/bitvec.py +++ /dev/null @@ -1,332 +0,0 @@ -# -# this is a rather strict implementation of a bit vector class -# it is accessed the same way as an array of python-ints, except -# the value must be 0 or 1 -# - -import sys; rprt = sys.stderr.write #for debugging - -error = 'bitvec.error' - - -def _check_value(value): - if type(value) != type(0) or not 0 <= value < 2: - raise error, 'bitvec() items must have int value 0 or 1' - - -import math - -def _compute_len(param): - mant, l = math.frexp(float(param)) - bitmask = 1L << l - if bitmask <= param: - raise 'FATAL', '(param, l) = ' + `param, l` - while l: - bitmask = bitmask >> 1 - if param & bitmask: - break - l = l - 1 - return l - - -def _check_key(len, key): - if type(key) != type(0): - raise TypeError, 'sequence subscript not int' - if key < 0: - key = key + len - if not 0 <= key < len: - raise IndexError, 'list index out of range' - return key - -def _check_slice(len, i, j): - #the type is ok, Python already checked that - i, j = max(i, 0), min(len, j) - if i > j: - i = j - return i, j - - -class BitVec: - - def __init__(self, *params): - self._data = 0L - self._len = 0 - if not len(params): - pass - elif len(params) == 1: - param, = params - if type(param) == type([]): - value = 0L - bit_mask = 1L - for item in param: - # strict check - #_check_value(item) - if item: - value = value | bit_mask - bit_mask = bit_mask << 1 - self._data = value - self._len = len(param) - elif type(param) == type(0L): - if param < 0: - raise error, 'bitvec() can\'t handle negative longs' - self._data = param - self._len = _compute_len(param) - else: - raise error, 'bitvec() requires array or long parameter' - elif len(params) == 2: - param, length = params - if type(param) == type(0L): - if param < 0: - raise error, \ - 'can\'t handle negative longs' - self._data = param - if type(length) != type(0): - raise error, 'bitvec()\'s 2nd parameter must be int' - computed_length = _compute_len(param) - if computed_length > length: - print 'warning: bitvec() value is longer than the lenght indicates, truncating value' - self._data = self._data & \ - ((1L << length) - 1) - self._len = length - else: - raise error, 'bitvec() requires array or long parameter' - else: - raise error, 'bitvec() requires 0 -- 2 parameter(s)' - - - def append(self, item): - #_check_value(item) - #self[self._len:self._len] = [item] - self[self._len:self._len] = \ - BitVec(long(not not item), 1) - - - def count(self, value): - #_check_value(value) - if value: - data = self._data - else: - data = (~self)._data - count = 0 - while data: - data, count = data >> 1, count + (data & 1 != 0) - return count - - - def index(self, value): - #_check_value(value): - if value: - data = self._data - else: - data = (~self)._data - index = 0 - if not data: - raise ValueError, 'list.index(x): x not in list' - while not (data & 1): - data, index = data >> 1, index + 1 - return index - - - def insert(self, index, item): - #_check_value(item) - #self[index:index] = [item] - self[index:index] = BitVec(long(not not item), 1) - - - def remove(self, value): - del self[self.index(value)] - - - def reverse(self): - #ouch, this one is expensive! - #for i in self._len>>1: self[i], self[l-i] = self[l-i], self[i] - data, result = self._data, 0L - for i in range(self._len): - if not data: - result = result << (self._len - i) - break - result, data = (result << 1) | (data & 1), data >> 1 - self._data = result - - - def sort(self): - c = self.count(1) - self._data = ((1L << c) - 1) << (self._len - c) - - - def copy(self): - return BitVec(self._data, self._len) - - - def seq(self): - result = [] - for i in self: - result.append(i) - return result - - - def __repr__(self): - ##rprt('.' + '__repr__()\n') - return 'bitvec' + `self._data, self._len` - - def __cmp__(self, other, *rest): - #rprt(`self`+'.__cmp__'+`(other, ) + rest`+'\n') - if type(other) != type(self): - other = apply(bitvec, (other, ) + rest) - #expensive solution... recursive binary, with slicing - length = self._len - if length == 0 or other._len == 0: - return cmp(length, other._len) - if length != other._len: - min_lenght = min(length, other._len) - return cmp(self[:min_length], other[:min_length]) or \ - cmp(self[min_length:], other[min_length:]) - #the lengths are the same now... - if self._data == other._data: - return 0 - if length == 1: - return cmp(self[0], other[0]) - else: - length = length >> 1 - return cmp(self[:length], other[:length]) or \ - cmp(self[length:], other[length:]) - - - def __len__(self): - #rprt(`self`+'.__len__()\n') - return self._len - - def __getitem__(self, key): - #rprt(`self`+'.__getitem__('+`key`+')\n') - key = _check_key(self._len, key) - return self._data & (1L << key) != 0 - - def __setitem__(self, key, value): - #rprt(`self`+'.__setitem__'+`key, value`+'\n') - key = _check_key(self._len, key) - #_check_value(value) - if value: - self._data = self._data | (1L << key) - else: - self._data = self._data & ~(1L << key) - - def __delitem__(self, key): - #rprt(`self`+'.__delitem__('+`key`+')\n') - key = _check_key(self._len, key) - #el cheapo solution... - self._data = self[:key]._data | self[key+1:]._data >> key - self._len = self._len - 1 - - def __getslice__(self, i, j): - #rprt(`self`+'.__getslice__'+`i, j`+'\n') - i, j = _check_slice(self._len, i, j) - if i >= j: - return BitVec(0L, 0) - if i: - ndata = self._data >> i - else: - ndata = self._data - nlength = j - i - if j != self._len: - #we'll have to invent faster variants here - #e.g. mod_2exp - ndata = ndata & ((1L << nlength) - 1) - return BitVec(ndata, nlength) - - def __setslice__(self, i, j, sequence, *rest): - #rprt(`self`+'.__setslice__'+`(i, j, sequence) + rest`+'\n') - i, j = _check_slice(self._len, i, j) - if type(sequence) != type(self): - sequence = apply(bitvec, (sequence, ) + rest) - #sequence is now of our own type - ls_part = self[:i] - ms_part = self[j:] - self._data = ls_part._data | \ - ((sequence._data | \ - (ms_part._data << sequence._len)) << ls_part._len) - self._len = self._len - j + i + sequence._len - - def __delslice__(self, i, j): - #rprt(`self`+'.__delslice__'+`i, j`+'\n') - i, j = _check_slice(self._len, i, j) - if i == 0 and j == self._len: - self._data, self._len = 0L, 0 - elif i < j: - self._data = self[:i]._data | (self[j:]._data >> i) - self._len = self._len - j + i - - def __add__(self, other): - #rprt(`self`+'.__add__('+`other`+')\n') - retval = self.copy() - retval[self._len:self._len] = other - return retval - - def __mul__(self, multiplier): - #rprt(`self`+'.__mul__('+`multiplier`+')\n') - if type(multiplier) != type(0): - raise TypeError, 'sequence subscript not int' - if multiplier <= 0: - return BitVec(0L, 0) - elif multiplier == 1: - return self.copy() - #handle special cases all 0 or all 1... - if self._data == 0L: - return BitVec(0L, self._len * multiplier) - elif (~self)._data == 0L: - return ~BitVec(0L, self._len * multiplier) - #otherwise el cheapo again... - retval = BitVec(0L, 0) - while multiplier: - retval, multiplier = retval + self, multiplier - 1 - return retval - - def __and__(self, otherseq, *rest): - #rprt(`self`+'.__and__'+`(otherseq, ) + rest`+'\n') - if type(otherseq) != type(self): - otherseq = apply(bitvec, (otherseq, ) + rest) - #sequence is now of our own type - return BitVec(self._data & otherseq._data, \ - min(self._len, otherseq._len)) - - - def __xor__(self, otherseq, *rest): - #rprt(`self`+'.__xor__'+`(otherseq, ) + rest`+'\n') - if type(otherseq) != type(self): - otherseq = apply(bitvec, (otherseq, ) + rest) - #sequence is now of our own type - return BitVec(self._data ^ otherseq._data, \ - max(self._len, otherseq._len)) - - - def __or__(self, otherseq, *rest): - #rprt(`self`+'.__or__'+`(otherseq, ) + rest`+'\n') - if type(otherseq) != type(self): - otherseq = apply(bitvec, (otherseq, ) + rest) - #sequence is now of our own type - return BitVec(self._data | otherseq._data, \ - max(self._len, otherseq._len)) - - - def __invert__(self): - #rprt(`self`+'.__invert__()\n') - return BitVec(~self._data & ((1L << self._len) - 1), \ - self._len) - - def __coerce__(self, otherseq, *rest): - #needed for *some* of the arithmetic operations - #rprt(`self`+'.__coerce__'+`(otherseq, ) + rest`+'\n') - if type(otherseq) != type(self): - otherseq = apply(bitvec, (otherseq, ) + rest) - return self, otherseq - - def __int__(self): - return int(self._data) - - def __long__(self): - return long(self._data) - - def __float__(self): - return float(self._data) - - -bitvec = BitVec diff --git a/Demo/classes/class.doc b/Demo/classes/class.doc deleted file mode 100755 index fddc60bf7b..0000000000 --- a/Demo/classes/class.doc +++ /dev/null @@ -1,110 +0,0 @@ -New features of classes -======================= - -A class can implement certain operations that are invoked by special -syntax (such as subscription or arithmetic operations) by defining -methods with special names. - - -Special methods for any type ----------------------------- - -__repr__(self) --> string - -Used by the print statement and conversions (reverse quotes) to -compute the string representation of an object. - -__cmp__(self, other) --> int - -Used by all comparison operations. Should return -1 if selfother. Due to limitations in the -interpreter, exceptions raised by comparisons are ignored, and the -objects will be considered equal in this case. - - -Special methods for sequence and mapping types ----------------------------------------------- - -__len__(self) --> int - -Used by the built-in function len(). Should return the length of the -object, which should be >= 0. Also, an object whose __len__() method -returns 0 - -__getitem__(self, key) --> value - -Used to implement value = self[key]. Note that the special -interpretation of negative keys (if the class wishes to emulate a -sequence type) is up to the __getitem__ method. - -__setitem__(self, key, value) - -Used to implement self[key] = value. Same note as for __getitem__. - -__delitem__(self, key) - -Used to implement del self[key]. Same note as for __getitem__. - - -Special methods for sequence types ----------------------------------- - -__getslice__(self, i, j) --> sequence - -Used to implement self[i:j]. Note that missing i or j are replaced by -0 or len(self), respectively, and len(self) has been added to negative -i or j. - -__setslice__(self, i, j, sequence) - -Used to implement self[i:j] = value. Same note as for __getslice__. - -__delslice__(self, i, j) - -Used to implement del self[i:j]. Same note as for __getslice__. - - -Special methods for numeric types ---------------------------------- - -__add__, __sub__, __mul__, __div__, __mod__, __divmod__, __pow__, -__lshift__, __rshift__, __and__, __xor__, __or__ - -Used to implement the binary arithmetic operations (divmod and pow are -called by built-in functions). All have the call pattern -func(self, other) --> number. - -__neg__, __pos__, __abs__, __invert__ - -Used to implement the unary arithmetic operations (-, +, abs and ~). -All have the call pattern func(self) --> number. - -__nonzero__(self) --> int - -Used to implement boolean testing. An alternative name for this -method is __len__. - -__coerce__(self, other) --> (self1, other1) or None - -Used to implement "mixed-mode" numeric arithmetic. Either return a -tuple containing self and other converted to some common type, or None -if no way of conversion is known. When the common type would be the -type of other, it is sufficient to return None, since the interpreter -will also ask the other object to attempt a coercion (but sometimes, -if the implementation of the other type cannot be changed, it is -useful to do the conversion to the other type here). - -__int__(self) --> int -__long__(self) --> long -__float__(self) --> float - -Used to implement the built-in functions int(), long() and float(). - - -Notes ------ - -Except for __repr__ and __cmp__, when no appropriate method is -defined, attempts to execute the operation raise an exception. For -__repr__ and __cmp__, the traditional interpretations are used -in this case. diff --git a/Demo/cwilib/cwilib.py b/Demo/cwilib/cwilib.py deleted file mode 100755 index ebe468a853..0000000000 --- a/Demo/cwilib/cwilib.py +++ /dev/null @@ -1,213 +0,0 @@ -# Interface to the interactive CWI library catalog. - -import sys -import stdwin -from stdwinevents import * -import select -import telnetlib -import vt100win -from form import Form - - -# Main program - -def main(): - vt = vt100win.VT100win() - # - host = 'biefstuk.cwi.nl' - tn = telnetlib.Telnet(host, 0) - # - try: - vt.send(tn.read_until('login: ', 10)) - tn.write('cwilib\r') - # - vt.send(tn.read_until('Hit to continue...', 10)) - tn.write('\r') - # - vt.send(tn.read_until('QUIT', 20)) - except EOFError: - sys.stderr.write('Connection closed prematurely\n') - sys.exit(1) - # - define_screens(vt) - matches = vt.which_screens() - if 'menu' not in matches: - sys.stderr.write('Main menu does not appear\n') - sys.exit(1) - # - tn.write('\r\r') - vt.open('Progress -- CWI Library') - vt.set_debuglevel(0) - ui = UserInterface() - # - while 1: - try: - data = tn.read_very_eager() - except EOFError: - stdwin.message('Connection closed--goodbye') - break - if data: - print 'send...' - vt.send(data) - print 'send...done' - continue - event = stdwin.pollevent() - if event: - type, window, detail = event - if window == None and type == WE_LOST_SEL: - window = ui.queryform.window - event = type, window, detail - if type == WE_CLOSE: - break - if window in ui.windows: - ui.dispatch(type, window, detail) - elif window == vt.window: - if type == WE_NULL: - pass - elif type == WE_COMMAND: - if detail == WC_RETURN: - tn.write('\r') - elif detail == WC_BACKSPACE: - tn.write('\b') - elif detail == WC_TAB: - tn.write('\t') - elif detail == WC_UP: - tn.write('\033[A') - elif detail == WC_DOWN: - tn.write('\033[B') - elif detail == WC_RIGHT: - tn.write('\033[C') - elif detail == WC_LEFT: - tn.write('\033[D') - else: - print '*** Command:', detail - elif type == WE_CHAR: - tn.write(detail) - elif type == WE_DRAW: - vt.draw(detail) - elif type in (WE_ACTIVATE, WE_DEACTIVATE): - pass - else: - print '*** VT100 event:', type, detail - else: - print '*** Alien event:', type, window, detail - continue - rfd, wfd, xfd = select.select([tn, stdwin], [], []) - - -# Subroutine to define our screen recognition patterns - -def define_screens(vt): - vt.define_screen('menu', { - 'title': ('search', 0, 0, 80, - ' SEARCH FUNCTIONS +OTHER FUNCTIONS '), - }) - vt.define_screen('search', { - 'title': ('search', 0, 0, 80, ' Search '), - }) - vt.define_screen('shortlist', {'title': ('search', 0, 0, 80, - ' Short-list')}) - vt.define_screen('showrecord', { - 'title': ('search', 0, 0, 80, ' Show record '), - }) - vt.define_screen('timelimit', { - 'limit': ('search', 12, 0, 80, ' TIME LIMIT '), - }) - vt.define_screen('attention', { - 'BASE': ('copy', 0, 0, 0, 'search'), - 'title': ('search', 10, 0, 80, ' ATTENTION ')}) - vt.define_screen('syntaxerror', { - 'BASE': ('copy', 0, 0, 0, 'attention'), - 'message': ('search', 12, 0, 80, ' Syntax error'), - }) - vt.define_screen('emptyerror', { - 'BASE': ('copy', 0, 0, 0, 'attention'), - 'message': ('search', 12, 0, 80, - ' Check your input. Search at least one term'), - }) - vt.define_screen('unsortedwarning', { - 'BASE': ('copy', 0, 0, 0, 'attention'), - 'message': ('search', 12, 0, 80, - ' Number of records exceeds sort limit'), - }) - vt.define_screen('thereismore', { - 'BASE': ('copy', 0, 0, 0, 'showrecord'), - 'message': ('search', 15, 0, 80, - 'There is more within this record. Use the arrow keys'), - }) - vt.define_screen('nofurther', { - 'BASE': ('copy', 0, 0, 0, 'showrecord'), - 'message': ('search', 17, 0, 80, 'You cannot go further\.'), - }) - vt.define_screen('nofurtherback', { - 'BASE': ('copy', 0, 0, 0, 'showrecord'), - 'message': ('search', 17, 0, 80, - 'You cannot go further back'), - }) - - -# Class to implement our user interface. - -class UserInterface: - - def __init__(self): - stdwin.setfont('7x14') - self.queryform = QueryForm() - self.listform = ListForm() - self.recordform = RecordForm() - self.forms = [self.queryform, self.listform, self.recordform] - define_query_fields(self.queryform) - self.windows = [] - for form in self.forms: - if form.formheight > 0: - form.open() - self.windows.append(form.window) - - def __del__(self): - self.close() - - def close(self): - for form in self.forms: - form.close() - - def dispatch(self, type, window, detail): - for form in self.forms: - if window == form.window: - form.dispatch(type, detail) - - -def define_query_fields(f): - f.define_field('name', 'Name auth./ed.', 1, 60) - f.define_field('title', 'Title', 4, 60) - f.define_field('shelfmark', 'Shelf mark', 1, 60) - f.define_field('class', 'Prim. classif.', 1, 60) - f.define_field('series', 'Series', 1, 60) - f.define_field('congress', 'Congr. pl./year', 1, 60) - f.define_field('type', 'Type', 1, 60) - - -class QueryForm(Form): - - def __init__(self): - Form.__init__(self, 'Query form -- CWI Library') - - def dispatch(self, type, detail): - if type == WE_COMMAND and detail == WC_RETURN: - print '*** SUBMIT ***' - else: - Form.dispatch(self, type, detail) - - -class ListForm(Form): - - def __init__(self): - Form.__init__(self, 'Short list -- CWI Library') - - -class RecordForm(Form): - - def __init__(self): - Form.__init__(self, 'Record detail -- CWI Library') - - -main() diff --git a/Demo/cwilib/form.py b/Demo/cwilib/form.py deleted file mode 100755 index 8dd6ef96eb..0000000000 --- a/Demo/cwilib/form.py +++ /dev/null @@ -1,170 +0,0 @@ -# Fill-out form window - -import stdwin -from stdwinevents import * - - -class Form: - - def __init__(self, title): - self.title = title - self.window = None - self.fields = {} - self.fieldnames = [] - self.formwidth = self.formheight = 0 - self.focusname = None - self.tefocus = None - - def define_field(self, name, label, lines, chars): - self.fieldnames.append(name) - lh = stdwin.lineheight() - cw = stdwin.textwidth('m') - left = 20*cw - top = self.formheight + 4 - right = left + chars*cw - bottom = top + lines*lh - te = None - self.fields[name] = (label, left, top, right, bottom, te) - self.formheight = bottom + 2 - self.formwidth = max(self.formwidth, right + 4) - - def open(self): - if self.window: return - self.formwidth = max(100, self.formwidth) - self.formheight = max(50, self.formheight) - stdwin.setdefwinsize(self.formwidth, self.formheight) - stdwin.setdefscrollbars(0, 0) - self.window = stdwin.open(self.title) - self.window.setdocsize(self.formwidth, self.formheight) - for name in self.fieldnames: - label, left, top, right, bottom, te = \ - self.fields[name] - rect = (left, top), (right, bottom) - te = self.window.textcreate(rect) - te.setactive(0) - te.setview(rect) - self.fields[name] = \ - label, left, top, right, bottom, te - if self.fieldnames: - self.setfocus(self.fieldnames[0]) - - def setfocus(self, name): - if name <> self.focusname and self.tefocus: - self.tefocus.setactive(0) - self.focusname = name - if self.focusname: - self.tefocus = self.fields[self.focusname][-1] - self.tefocus.setactive(1) - else: - self.tefocus = None - - def dispatch(self, type, detail): - event = type, self.window, detail - if type == WE_NULL: - pass - elif type == WE_DRAW: - self.draw(detail) - elif type == WE_MOUSE_DOWN: - x, y = detail[0] - for name in self.fieldnames: - label, left, top, right, bottom, te = \ - self.fields[name] - if left <= x < right and \ - top <= y < bottom: - self.setfocus(name) - break - else: - stdwin.fleep() - return - if self.tefocus: - (left, top), (right, bottom) = \ - self.tefocus.getrect() - if x < left: x = left - if x >= right: x = right-1 - if y < top: y = top - if y >= bottom: - y = bottom-1 - x = right-1 - event = type, self.window, ((x,y),)+detail[1:] - if not self.tefocus.event(event): - stdwin.fleep() - elif type in (WE_MOUSE_MOVE, WE_MOUSE_UP, WE_CHAR): - if not self.tefocus or not self.tefocus.event(event): - stdwin.fleep() - elif type == WE_MOUSE_UP: - button = detail[2] - if button == 2: - self.paste_selection() - else: - self.make_selection() - elif type == WE_COMMAND: - if detail in (WC_BACKSPACE, WC_UP, WC_DOWN, - WC_LEFT, WC_RIGHT): - if not self.tefocus or \ - not self.tefocus.event(event): - stdwin.fleep() - elif detail == WC_RETURN: - print '*** Submit query' - elif detail == WC_TAB: - if not self.fields: - stdwin.fleep() - return - if not self.focusname: - i = 0 - else: - i = self.fieldnames.index( - self.focusname) - i = (i+1) % len(self.fieldnames) - self.setfocus(self.fieldnames[i]) - self.tefocus.setfocus(0, 0x7fff) - self.make_selection() - elif type in (WE_ACTIVATE, WE_DEACTIVATE): - pass - elif type == WE_LOST_SEL: - if self.tefocus: - a, b = self.tefocus.getfocus() - self.tefocus.setfocus(a, a) - else: - print 'Form.dispatch(%d, %s)' % (type, `detail`) - - def draw(self, detail): - d = self.window.begindrawing() - d.cliprect(detail) - d.erase(detail) - self.drawform(d, detail) - d.noclip() - d.close() - # Stupid textedit objects can't draw with open draw object... - self.drawtextedit(detail) - - def drawform(self, d, detail): - for name in self.fieldnames: - label, left, top, right, bottom, te = self.fields[name] - d.text((0, top), label) - d.box((left-3, top-2), (right+4, bottom+2)) - - def drawtextedit(self, detail): - for name in self.fieldnames: - label, left, top, right, bottom, te = self.fields[name] - te.draw(detail) - - def make_selection(self): - s = self.tefocus.getfocustext() - if not s: - return - stdwin.rotatecutbuffers(1) - stdwin.setcutbuffer(0, s) - if not self.window.setselection(WS_PRIMARY, s): - stdwin.fleep() - - def paste_selection(self): - if not self.tefocus: - stdwin.fleep() - return - s = stdwin.getselection(WS_PRIMARY) - if not s: - s = stdwin.getcutbuffer(0) - if not s: - stdwin.fleep() - return - self.tefocus.replace(s) diff --git a/Demo/cwilib/telnetlib.py b/Demo/cwilib/telnetlib.py deleted file mode 100755 index 3a48a79b75..0000000000 --- a/Demo/cwilib/telnetlib.py +++ /dev/null @@ -1,321 +0,0 @@ -# A TELNET client class. Based on RFC 854: TELNET Protocol -# Specification, by J. Postel and J. Reynolds - - -# Example: -# -# >>> from telnetlib import Telnet -# >>> tn = Telnet('voorn.cwi.nl', 79) # connect to finger port -# >>> tn.write('guido\r\n') -# >>> print tn.read_all() -# Login name: guido In real life: Guido van Rossum -# Office: M353, x4127 Home phone: 020-6225521 -# Directory: /ufs/guido Shell: /usr/local/bin/esh -# On since Oct 28 11:02:16 on ttyq1 -# Project: Multimedia Kernel Systems -# No Plan. -# >>> -# -# Note that read() won't read until eof -- it just reads some data -# (but it guarantees to read at least one byte unless EOF is hit). -# -# It is possible to pass a Telnet object to select.select() in order -# to wait until more data is available. Note that in this case, -# read_eager() may return '' even if there was data on the socket, -# because the protocol negotiation may have eaten the data. -# This is why EOFError is needed to distinguish between "no data" -# and "connection closed" (since the socket also appears ready for -# reading when it is closed). -# -# Bugs: -# - may hang when connection is slow in the middle of an IAC sequence -# -# To do: -# - option negotiation - - -# Imported modules -import socket -import select -import string -import regsub - -# Tunable parameters -DEBUGLEVEL = 0 - -# Telnet protocol defaults -TELNET_PORT = 23 - -# Telnet protocol characters (don't change) -IAC = chr(255) # "Interpret As Command" -DONT = chr(254) -DO = chr(253) -WONT = chr(252) -WILL = chr(251) - - -# Telnet interface class - -class Telnet: - - # Constructor - def __init__(self, host, *args): - if not args: - port = TELNET_PORT - else: - if len(args) > 1: raise TypeError, 'too many args' - port = args[0] - if not port: port = TELNET_PORT - self.debuglevel = DEBUGLEVEL - self.host = host - self.port = port - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.sock.connect((self.host, self.port)) - self.rawq = '' - self.irawq = 0 - self.cookedq = '' - self.eof = 0 - - # Destructor - def __del__(self): - self.close() - - # Debug message - def msg(self, msg, *args): - if self.debuglevel > 0: - print 'Telnet(%s,%d):' % (self.host, self.port), msg % args - - # Set debug level - def set_debuglevel(self, debuglevel): - self.debuglevel = debuglevel - - # Explicit close - def close(self): - if self.sock: - self.sock.close() - self.sock = None - self.eof = 1 - - # Return socket (e.g. for select) - def get_socket(self): - return self.sock - - # Return socket's fileno (e.g. for select) - def fileno(self): - return self.sock.fileno() - - # Write a string to the socket, doubling any IAC characters - # Might block if the connection is blocked - # May raise socket.error if the connection is closed - def write(self, buffer): - if IAC in buffer: - buffer = regsub.gsub(IAC, IAC+IAC, buffer) - self.sock.send(buffer) - - # The following read_* methods exist: - # Special case: - # - read_until() reads until a string is encountered or a timeout is hit - # These may block: - # - read_all() reads all data until EOF - # - read_some() reads at least one byte until EOF - # These may do I/O but won't block doing it: - # - read_very_eager() reads all data available on the socket - # - read_eager() reads either data already queued or some data - # available on the socket - # These don't do I/O: - # - read_lazy() reads all data in the raw queue (processing it first) - # - read_very_lazy() reads all data in the cooked queue - - # Read until a given string is encountered or until timeout - # Raise EOFError if connection closed and no cooked data available - # Return '' if no cooked data available otherwise - def read_until(self, match, *args): - if not args: - timeout = None - else: - if len(args) > 1: raise TypeError, 'too many args' - timeout = args[0] - n = len(match) - self.process_rawq() - i = string.find(self.cookedq, match) - if i >= 0: - i = i+n - buf = self.cookedq[:i] - self.cookedq = self.cookedq[i:] - return buf - s_reply = ([self], [], []) - s_args = s_reply - if timeout is not None: - s_args = s_args + (timeout,) - while not self.eof and apply(select.select, s_args) == s_reply: - i = max(0, len(self.cookedq)-n) - self.fill_rawq() - self.process_rawq() - i = string.find(self.cookedq, match, i) - if i >= 0: - i = i+n - buf = self.cookedq[:i] - self.cookedq = self.cookedq[i:] - return buf - return self.read_very_lazy() - - # Read all data until EOF - # Block until connection closed - def read_all(self): - self.process_rawq() - while not self.eof: - self.fill_rawq() - self.process_rawq() - buf = self.cookedq - self.cookedq = '' - return buf - - # Read at least one byte of cooked data unless EOF is hit - # Return '' if EOF is hit - # Block if no data is immediately available - def read_some(self): - self.process_rawq() - while not self.cookedq and not self.eof: - self.fill_rawq() - self.process_rawq() - buf = self.cookedq - self.cookedq = '' - return buf - - # Read everything that's possible without blocking in I/O (eager) - # Raise EOFError if connection closed and no cooked data available - # Return '' if no cooked data available otherwise - # Don't block unless in the midst of an IAC sequence - def read_very_eager(self): - self.process_rawq() - while not self.eof and self.sock_avail(): - self.fill_rawq() - self.process_rawq() - return self.read_very_lazy() - - # Read readily available data - # Raise EOFError if connection closed and no cooked data available - # Return '' if no cooked data available otherwise - # Don't block unless in the midst of an IAC sequence - def read_eager(self): - self.process_rawq() - while not self.cookedq and not self.eof and self.sock_avail(): - self.fill_rawq() - self.process_rawq() - return self.read_very_lazy() - - # Process and return data that's already in the queues (lazy) - # Raise EOFError if connection closed and no data available - # Return '' if no cooked data available otherwise - # Don't block unless in the midst of an IAC sequence - def read_lazy(self): - self.process_rawq() - return self.read_very_lazy() - - # Return any data available in the cooked queue (very lazy) - # Raise EOFError if connection closed and no data available - # Return '' if no cooked data available otherwise - # Don't block - def read_very_lazy(self): - buf = self.cookedq - self.cookedq = '' - if not buf and self.eof and not self.rawq: - raise EOFError, 'telnet connection closed' - return buf - - # Transfer from raw queue to cooked queue - # Set self.eof when connection is closed - # Don't block unless in the midst of an IAC sequence - def process_rawq(self): - buf = '' - try: - while self.rawq: - c = self.rawq_getchar() - if c != IAC: - buf = buf + c - continue - c = self.rawq_getchar() - if c == IAC: - buf = buf + c - elif c in (DO, DONT): - opt = self.rawq_getchar() - self.msg('IAC %s %d', c == DO and 'DO' or 'DONT', ord(c)) - self.sock.send(IAC + WONT + opt) - elif c in (WILL, WONT): - opt = self.rawq_getchar() - self.msg('IAC %s %d', - c == WILL and 'WILL' or 'WONT', ord(c)) - else: - self.msg('IAC %s not recognized' % `c`) - except EOFError: # raised by self.rawq_getchar() - pass - self.cookedq = self.cookedq + buf - - # Get next char from raw queue - # Block if no data is immediately available - # Raise EOFError when connection is closed - def rawq_getchar(self): - if not self.rawq: - self.fill_rawq() - if self.eof: - raise EOFError - c = self.rawq[self.irawq] - self.irawq = self.irawq + 1 - if self.irawq >= len(self.rawq): - self.rawq = '' - self.irawq = 0 - return c - - # Fill raw queue from exactly one recv() system call - # Block if no data is immediately available - # Set self.eof when connection is closed - def fill_rawq(self): - if self.irawq >= len(self.rawq): - self.rawq = '' - self.irawq = 0 - # The buffer size should be fairly small so as to avoid quadratic - # behavior in process_rawq() above - buf = self.sock.recv(50) - self.eof = (not buf) - self.rawq = self.rawq + buf - - # Test whether data is available on the socket - def sock_avail(self): - return select.select([self], [], [], 0) == ([self], [], []) - - -# Test program -# Usage: test [-d] ... [host [port]] -def test(): - import sys, string, socket, select - debuglevel = 0 - while sys.argv[1:] and sys.argv[1] == '-d': - debuglevel = debuglevel+1 - del sys.argv[1] - host = 'localhost' - if sys.argv[1:]: - host = sys.argv[1] - port = 0 - if sys.argv[2:]: - portstr = sys.argv[2] - try: - port = string.atoi(portstr) - except string.atoi_error: - port = socket.getservbyname(portstr, 'tcp') - tn = Telnet(host, port) - tn.set_debuglevel(debuglevel) - while 1: - rfd, wfd, xfd = select.select([tn, sys.stdin], [], []) - if sys.stdin in rfd: - line = sys.stdin.readline() - tn.write(line) - if tn in rfd: - try: - text = tn.read_eager() - except EOFError: - print '*** Connection closed by remote host ***' - break - if text: - sys.stdout.write(text) - sys.stdout.flush() - tn.close() diff --git a/Demo/cwilib/vt100.py b/Demo/cwilib/vt100.py deleted file mode 100755 index 9edd4810b9..0000000000 --- a/Demo/cwilib/vt100.py +++ /dev/null @@ -1,328 +0,0 @@ -# VT100 terminal emulator. -# This is incomplete and slow, but will do for now... -# It shouldn't be difficult to extend it to be a more-or-less complete -# VT100 emulator. And little bit of profiling could go a long way... - -from array import array -import regex -import string - -# Tunable parameters -DEBUGLEVEL = 1 - -# Symbolic constants -ESC = '\033' - - -# VT100 emulation class - -class VT100: - - def __init__(self): - self.debuglevel = DEBUGLEVEL - # Unchangeable parameters (for now) - self.width = 80 - self.height = 24 - self.blankline = array('c', ' '*self.width) - self.blankattr = array('b', '\0'*self.width) - # Set mutable display state - self.reset() - # Set parser state - self.unfinished = '' - # Set screen recognition state - self.reset_recognizer() - - def msg(self, msg, *args): - if self.debuglevel > 0: - print 'VT100:', msg%args - - def set_debuglevel(self, debuglevel): - self.debuglevel = debuglevel - - def reset(self): - self.lines = [] - self.attrs = [] - self.fill_bottom() - self.x = 0 - self.y = 0 - self.curattrs = [] - - def show(self): - lineno = 0 - for line in self.lines: - lineno = lineno + 1 - i = len(line) - while i > 0 and line[i-1] == ' ': i = i-1 - print line[:i] - print 'CURSOR:', self.x, self.y - - def fill_bottom(self): - while len(self.lines) < self.height: - self.lines.append(self.blankline[:]) - self.attrs.append(self.blankattr[:]) - - def fill_top(self): - while len(self.lines) < self.height: - self.lines.insert(0, self.blankline[:]) - self.attrs.insert(0, self.blankattr[:]) - - def clear_all(self): - self.lines = [] - self.attrs = [] - self.fill_bottom() - - def clear_below(self): - del self.lines[self.y:] - del self.attrs[self.y:] - self.fill_bottom() - - def clear_above(self): - del self.lines[:self.y] - del self.attrs[:self.y] - self.fill_top() - - def send(self, buffer): - self.msg('send: unfinished=%s, buffer=%s', - `self.unfinished`, `buffer`) - self.unfinished = self.unfinished + buffer - i = 0 - n = len(self.unfinished) - while i < n: - c = self.unfinished[i] - i = i+1 - if c != ESC: - self.add_char(c) - continue - if i >= n: - i = i-1 - break - c = self.unfinished[i] - i = i+1 - if c == 'c': - self.reset() - continue - if c <> '[': - self.msg('unrecognized: ESC %s', `c`) - continue - argstr = '' - while i < n: - c = self.unfinished[i] - i = i+1 - if c not in '0123456789;': - break - argstr = argstr + c - else: - i = i - len(argstr) - 2 - break -## self.msg('found ESC [ %s %s' % (`argstr`, `c`)) - args = string.splitfields(argstr, ';') - for j in range(len(args)): - s = args[j] - while s[:1] == '0': s = s[1:] - if s: args[j] = eval(s) - else: args[j] = 0 - p1 = p2 = 0 - if args: p1 = args[0] - if args[1:]: p2 = args[1] - if c in '@ABCDH': - if not p1: p1 = 1 - if c in 'H': - if not p2: p2 = 1 - if c == '@': - for j in range(p1): - self.add_char(' ') - elif c == 'A': - self.move_by(0, -p1) - elif c == 'B': - self.move_by(0, p1) - elif c == 'C': - self.move_by(p1, 0) - elif c == 'D': - self.move_by(-p1, 0) - elif c == 'H': - self.move_to(p2-1, p1-1) - elif c == 'J': - if p1 == 0: self.clear_above() - elif p1 == 1: self.clear_below() - elif p1 == 2: self.clear_all() - else: self.msg('weird ESC [ %d J', p1) - elif c == 'K': - if p1 == 0: self.erase_right() - elif p1 == 1: self.erase_left() - elif p1 == 2: self.erase_line() - else: self.msg('weird ESC [ %d K', p1) - elif c == 'm': - if p1 == 0: - self.curattrs = [] - else: - if p1 not in self.curattrs: - self.curattrs.append(p1) - self.curattrs.sort() - else: - self.msg('unrecognized: ESC [ %s', `argstr+c`) - self.unfinished = self.unfinished[i:] - - def add_char(self, c): - if c == '\r': - self.move_to(0, self.y) - return - if c in '\n\f\v': - self.move_to(self.x, self.y + 1) - if self.y >= self.height: - self.scroll_up(1) - self.move_to(self.x, self.height - 1) - return - if c == '\b': - self.move_by(-1, 0) - return - if c == '\a': - self.msg('BELL') - return - if c == '\t': - self.move_to((self.x+8)/8*8, self.y) - return - if c == '\0': - return - if c < ' ' or c > '~': - self.msg('ignored control char: %s', `c`) - return - if self.x >= self.width: - self.move_to(0, self.y + 1) - if self.y >= self.height: - self.scroll_up(1) - self.move_to(self.x, self.height - 1) - self.lines[self.y][self.x] = c - if self.curattrs: - self.attrs[self.y][self.x] = max(self.curattrs) - else: - self.attrs[self.y][self.x] = 0 - self.move_by(1, 0) - - def move_to(self, x, y): - self.x = min(max(0, x), self.width) - self.y = min(max(0, y), self.height) - - def move_by(self, dx, dy): - self.move_to(self.x + dx, self.y + dy) - - def scroll_up(self, nlines): - del self.lines[:max(0, nlines)] - del self.attrs[:max(0, nlines)] - self.fill_bottom() - - def scroll_down(self, nlines): - del self.lines[-max(0, nlines):] - del self.attrs[-max(0, nlines):] - self.fill_top() - - def erase_left(self): - x = min(self.width-1, x) - y = min(self.height-1, y) - self.lines[y][:x] = self.blankline[:x] - self.attrs[y][:x] = self.blankattr[:x] - - def erase_right(self): - x = min(self.width-1, x) - y = min(self.height-1, y) - self.lines[y][x:] = self.blankline[x:] - self.attrs[y][x:] = self.blankattr[x:] - - def erase_line(self): - self.lines[y][:] = self.blankline - self.attrs[y][:] = self.blankattr - - # The following routines help automating the recognition of - # standard screens. A standard screen is characterized by - # a number of fields. A field is part of a line, - # characterized by a (lineno, begin, end) tuple; - # e.g. the first 10 characters of the second line are - # specified by the tuple (1, 0, 10). Fields can be: - # - regex: desired contents given by a regular expression, - # - extract: can be extracted, - # - cursor: screen is only valid if cursor in field, - # - copy: identical to another screen (position is ignored). - # A screen is defined as a dictionary full of fields. Screens - # also have names and are placed in a dictionary. - - def reset_recognizer(self): - self.screens = {} - - def define_screen(self, screenname, fields): - fieldscopy = {} - # Check if the fields make sense - for fieldname in fields.keys(): - field = fields[fieldname] - ftype, lineno, begin, end, extra = field - if ftype in ('match', 'search'): - extra = regex.compile(extra) - elif ftype == 'extract': - extra = None - elif ftype == 'cursor': - extra = None - elif ftype == 'copy': - if not self.screens.has_key(extra): - raise ValueError, 'bad copy ref' - else: - raise ValueError, 'bad ftype: %s' % `ftype` - fieldscopy[fieldname] = ( - ftype, lineno, begin, end, extra) - self.screens[screenname] = fieldscopy - - def which_screens(self): - self.busy = [] - self.okay = [] - self.fail = [] - for name in self.screens.keys(): - ok = self.match_screen(name) - return self.okay[:] - - def match_screen(self, name): - if name in self.busy: raise RuntimeError, 'recursive match' - if name in self.okay: return 1 - if name in self.fail: return 0 - self.busy.append(name) - fields = self.screens[name] - ok = 0 - for key in fields.keys(): - field = fields[key] - ftype, lineno, begin, end, extra = field - if ftype == 'copy': - if not self.match_screen(extra): break - elif ftype == 'search': - text = self.lines[lineno][begin:end].tostring() - if extra.search(text) < 0: - break - elif ftype == 'match': - text = self.lines[lineno][begin:end].tostring() - if extra.match(text) < 0: - break - elif ftype == 'cursor': - if self.x != lineno or not \ - begin <= self.y < end: - break - else: - ok = 1 - if ok: - self.okay.append(name) - else: - self.fail.append(name) - self.busy.remove(name) - return ok - - def extract_field(self, screenname, fieldname): - ftype, lineno, begin, end, extra = \ - self.screens[screenname][fieldname] - return stripright(self.lines[lineno][begin:end].tostring()) - - def extract_rect(self, left, top, right, bottom): - lines = [] - for i in range(top, bottom): - lines.append(stripright(self.lines[i][left:right]) - .tostring()) - return lines - - -def stripright(line): - i = len(line) - while i > 0 and line[i-1] in string.whitespace: i = i-1 - return line[:i] diff --git a/Demo/cwilib/vt100win.py b/Demo/cwilib/vt100win.py deleted file mode 100755 index 122e5f9dfa..0000000000 --- a/Demo/cwilib/vt100win.py +++ /dev/null @@ -1,78 +0,0 @@ -# VT100 terminal emulator in a STDWIN window. - -import stdwin -from stdwinevents import * -from vt100 import VT100 - -class VT100win(VT100): - - def __init__(self): - VT100.__init__(self) - self.window = None - self.last_x = -1 - self.last_y = -1 - - def __del__(self): - self.close() - - def open(self, title): - stdwin.setfont('7x14') - self.charwidth = stdwin.textwidth('m') - self.lineheight = stdwin.lineheight() - self.docwidth = self.width * self.charwidth - self.docheight = self.height * self.lineheight - stdwin.setdefwinsize(self.docwidth + 2, self.docheight + 2) - stdwin.setdefscrollbars(0, 0) - self.window = stdwin.open(title) - self.window.setdocsize(self.docwidth + 2, self.docheight + 2) - - def close(self): - if self.window: - self.window.close() - self.window = None - - def show(self): - if not self.window: return - self.window.change(((-10, -10), - (self.docwidth+10, self.docheight+10))) - - def draw(self, detail): - d = self.window.begindrawing() - fg = stdwin.getfgcolor() - red = stdwin.fetchcolor('red') - d.cliprect(detail) - d.erase(detail) - lh = self.lineheight - cw = self.charwidth - for y in range(self.height): - d.text((0, y*lh), self.lines[y].tostring()) - if self.attrs[y] <> self.blankattr: - for x in range(len(self.attrs[y])): - if self.attrs[y][x] == 7: - p1 = x*cw, y*lh - p2 = (x+1)*cw, (y+1)*lh - d.invert((p1, p2)) - x = self.x * cw - y = self.y * lh - d.setfgcolor(red) - d.invert((x, y), (x+cw, y+lh)) - d.setfgcolor(fg) - d.close() - - def move_to(self, x, y): - VT100.move_to(self, x, y) - if not self.window: return - if self.y != self.last_y: - self.window.change((0, self.last_y * self.lineheight), - (self.width*self.charwidth, - (self.last_y+1) * self.lineheight)) - self.last_x = self.x - self.last_y = y - self.window.change((0, self.y * self.lineheight), - (self.width*self.charwidth, - (self.y+1) * self.lineheight)) - - def send(self, str): - VT100.send(self, str) -## self.show() - diff --git a/Demo/rpc/MANIFEST b/Demo/rpc/MANIFEST deleted file mode 100644 index e65f3ebee8..0000000000 --- a/Demo/rpc/MANIFEST +++ /dev/null @@ -1,10 +0,0 @@ - File Name Archive # Description ------------------------------------------------------------ - MANIFEST 1 This shipping list - README 1 - T.py 1 - mountclient.py 1 - nfsclient.py 1 - rpc.py 1 - test 1 - xdr.py 1 diff --git a/Demo/rpc/README b/Demo/rpc/README deleted file mode 100644 index be75c10400..0000000000 --- a/Demo/rpc/README +++ /dev/null @@ -1,23 +0,0 @@ -This is a Python interface to Sun RPC, designed and implemented mostly -by reading the Internet RFCs about the subject. - -There are two library modules, xdr.py and rpc.py, and several example -clients: mountclient.py, nfsclient.py, and rnusersclient.py, -implementing the NFS Mount protocol, (part of) the NFS protocol, and -the "rnusers" protocol (used by rusers(1)), respectively. The latter -demonstrates the use of broadcast via the Port mapper's CALLIT -procedure. - -There is also a way to create servers in Python. - -To test the nfs client, run it from the shell with something like this: - - python -c 'import nfsclient; nfsclient.test()' [hostname [filesystemname]] - -When called without a filesystemname, it lists the filesystems at the -host; default host is the local machine. - -Other clients are tested similarly. - -For hostname, use e.g. wuarchive.wustl.edu or gatekeeper.dec.com (two -hosts that are known to export NFS filesystems with little restrictions). diff --git a/Demo/rpc/T.py b/Demo/rpc/T.py deleted file mode 100644 index 475372bfff..0000000000 --- a/Demo/rpc/T.py +++ /dev/null @@ -1,22 +0,0 @@ -# Simple interface to report execution times of program fragments. -# Call TSTART() to reset the timer, TSTOP(...) to report times. - -import sys, os, time - -def TSTART(): - global t0, t1 - u, s, cu, cs = os.times() - t0 = u+cu, s+cs, time.millitimer() - -def TSTOP(*label): - global t0, t1 - u, s, cu, cs = os.times() - t1 = u+cu, s+cs, time.millitimer() - tt = [] - for i in range(3): - tt.append(t1[i] - t0[i]) - [u, s, r] = tt - msg = '' - for x in label: msg = msg + (x + ' ') - msg = msg + `u` + ' user, ' + `s` + ' sys, ' + `r*0.001` + ' real\n' - sys.stderr.write(msg) diff --git a/Demo/rpc/mountclient.py b/Demo/rpc/mountclient.py deleted file mode 100644 index ff66b3d6cc..0000000000 --- a/Demo/rpc/mountclient.py +++ /dev/null @@ -1,201 +0,0 @@ -# Mount RPC client -- RFC 1094 (NFS), Appendix A - -# This module demonstrates how to write your own RPC client in Python. -# Since there is no RPC compiler for Python (yet), you must first -# create classes derived from Packer and Unpacker to handle the data -# types for the server you want to interface to. You then write the -# client class. If you want to support both the TCP and the UDP -# version of a protocol, use multiple inheritance as shown below. - - -import rpc -from rpc import Packer, Unpacker, TCPClient, UDPClient - - -# Program number and version for the mount protocol -MOUNTPROG = 100005 -MOUNTVERS = 1 - -# Size of the 'fhandle' opaque structure -FHSIZE = 32 - - -# Packer derived class for Mount protocol clients. -# The only thing we need to pack beyond basic types is an 'fhandle' - -class MountPacker(Packer): - - def pack_fhandle(self, fhandle): - self.pack_fopaque(FHSIZE, fhandle) - - -# Unpacker derived class for Mount protocol clients. -# The important types we need to unpack are fhandle, fhstatus, -# mountlist and exportlist; mountstruct, exportstruct and groups are -# used to unpack components of mountlist and exportlist and the -# corresponding functions are passed as function argument to the -# generic unpack_list function. - -class MountUnpacker(Unpacker): - - def unpack_fhandle(self): - return self.unpack_fopaque(FHSIZE) - - def unpack_fhstatus(self): - status = self.unpack_uint() - if status == 0: - fh = self.unpack_fhandle() - else: - fh = None - return status, fh - - def unpack_mountlist(self): - return self.unpack_list(self.unpack_mountstruct) - - def unpack_mountstruct(self): - hostname = self.unpack_string() - directory = self.unpack_string() - return (hostname, directory) - - def unpack_exportlist(self): - return self.unpack_list(self.unpack_exportstruct) - - def unpack_exportstruct(self): - filesys = self.unpack_string() - groups = self.unpack_groups() - return (filesys, groups) - - def unpack_groups(self): - return self.unpack_list(self.unpack_string) - - -# These are the procedures specific to the Mount client class. -# Think of this as a derived class of either TCPClient or UDPClient. - -class PartialMountClient: - - # This method is called by Client.__init__ to initialize - # self.packer and self.unpacker - def addpackers(self): - self.packer = MountPacker() - self.unpacker = MountUnpacker('') - - # This method is called by Client.__init__ to bind the socket - # to a particular network interface and port. We use the - # default network interface, but if we're running as root, - # we want to bind to a reserved port - def bindsocket(self): - import os - try: - uid = os.getuid() - except AttributeError: - uid = 1 - if uid == 0: - port = rpc.bindresvport(self.sock, '') - # 'port' is not used - else: - self.sock.bind(('', 0)) - - # This function is called to cough up a suitable - # authentication object for a call to procedure 'proc'. - def mkcred(self): - if self.cred == None: - self.cred = rpc.AUTH_UNIX, rpc.make_auth_unix_default() - return self.cred - - # The methods Mnt, Dump etc. each implement one Remote - # Procedure Call. This is done by calling self.make_call() - # with as arguments: - # - # - the procedure number - # - the arguments (or None) - # - the "packer" function for the arguments (or None) - # - the "unpacker" function for the return value (or None) - # - # The packer and unpacker function, if not None, *must* be - # methods of self.packer and self.unpacker, respectively. - # A value of None means that there are no arguments or is no - # return value, respectively. - # - # The return value from make_call() is the return value from - # the remote procedure call, as unpacked by the "unpacker" - # function, or None if the unpacker function is None. - # - # (Even if you expect a result of None, you should still - # return the return value from make_call(), since this may be - # needed by a broadcasting version of the class.) - # - # If the call fails, make_call() raises an exception - # (this includes time-outs and invalid results). - # - # Note that (at least with the UDP protocol) there is no - # guarantee that a call is executed at most once. When you do - # get a reply, you know it has been executed at least once; - # when you don't get a reply, you know nothing. - - def Mnt(self, directory): - return self.make_call(1, directory, \ - self.packer.pack_string, \ - self.unpacker.unpack_fhstatus) - - def Dump(self): - return self.make_call(2, None, \ - None, self.unpacker.unpack_mountlist) - - def Umnt(self, directory): - return self.make_call(3, directory, \ - self.packer.pack_string, None) - - def Umntall(self): - return self.make_call(4, None, None, None) - - def Export(self): - return self.make_call(5, None, \ - None, self.unpacker.unpack_exportlist) - - -# We turn the partial Mount client into a full one for either protocol -# by use of multiple inheritance. (In general, when class C has base -# classes B1...Bn, if x is an instance of class C, methods of x are -# searched first in C, then in B1, then in B2, ..., finally in Bn.) - -class TCPMountClient(PartialMountClient, TCPClient): - - def __init__(self, host): - TCPClient.__init__(self, host, MOUNTPROG, MOUNTVERS) - - -class UDPMountClient(PartialMountClient, UDPClient): - - def __init__(self, host): - UDPClient.__init__(self, host, MOUNTPROG, MOUNTVERS) - - -# A little test program for the Mount client. This takes a host as -# command line argument (default the local machine), prints its export -# list, and attempts to mount and unmount each exported files system. -# An optional first argument of -t or -u specifies the protocol to use -# (TCP or UDP), default is UDP. - -def test(): - import sys - if sys.argv[1:] and sys.argv[1] == '-t': - C = TCPMountClient - del sys.argv[1] - elif sys.argv[1:] and sys.argv[1] == '-u': - C = UDPMountClient - del sys.argv[1] - else: - C = UDPMountClient - if sys.argv[1:]: host = sys.argv[1] - else: host = '' - mcl = C(host) - list = mcl.Export() - for item in list: - print item - try: - mcl.Mnt(item[0]) - except: - print 'Sorry' - continue - mcl.Umnt(item[0]) diff --git a/Demo/rpc/nfsclient.py b/Demo/rpc/nfsclient.py deleted file mode 100644 index 498e2d0b98..0000000000 --- a/Demo/rpc/nfsclient.py +++ /dev/null @@ -1,201 +0,0 @@ -# NFS RPC client -- RFC 1094 - -# XXX This is not yet complete. -# XXX Only GETATTR, SETTTR, LOOKUP and READDIR are supported. - -# (See mountclient.py for some hints on how to write RPC clients in -# Python in general) - -import rpc -from rpc import UDPClient, TCPClient -from mountclient import FHSIZE, MountPacker, MountUnpacker - -NFS_PROGRAM = 100003 -NFS_VERSION = 2 - -# enum stat -NFS_OK = 0 -# (...many error values...) - -# enum ftype -NFNON = 0 -NFREG = 1 -NFDIR = 2 -NFBLK = 3 -NFCHR = 4 -NFLNK = 5 - - -class NFSPacker(MountPacker): - - def pack_sattrargs(self, sa): - file, attributes = sa - self.pack_fhandle(file) - self.pack_sattr(attributes) - - def pack_sattr(self, sa): - mode, uid, gid, size, atime, mtime = sa - self.pack_uint(mode) - self.pack_uint(uid) - self.pack_uint(gid) - self.pack_uint(size) - self.pack_timeval(atime) - self.pack_timeval(mtime) - - def pack_diropargs(self, da): - dir, name = da - self.pack_fhandle(dir) - self.pack_string(name) - - def pack_readdirargs(self, ra): - dir, cookie, count = ra - self.pack_fhandle(dir) - self.pack_uint(cookie) - self.pack_uint(count) - - def pack_timeval(self, tv): - secs, usecs = tv - self.pack_uint(secs) - self.pack_uint(usecs) - - -class NFSUnpacker(MountUnpacker): - - def unpack_readdirres(self): - status = self.unpack_enum() - if status == NFS_OK: - entries = self.unpack_list(self.unpack_entry) - eof = self.unpack_bool() - rest = (entries, eof) - else: - rest = None - return (status, rest) - - def unpack_entry(self): - fileid = self.unpack_uint() - name = self.unpack_string() - cookie = self.unpack_uint() - return (fileid, name, cookie) - - def unpack_diropres(self): - status = self.unpack_enum() - if status == NFS_OK: - fh = self.unpack_fhandle() - fa = self.unpack_fattr() - rest = (fh, fa) - else: - rest = None - return (status, rest) - - def unpack_attrstat(self): - status = self.unpack_enum() - if status == NFS_OK: - attributes = self.unpack_fattr() - else: - attributes = None - return status, attributes - - def unpack_fattr(self): - type = self.unpack_enum() - mode = self.unpack_uint() - nlink = self.unpack_uint() - uid = self.unpack_uint() - gid = self.unpack_uint() - size = self.unpack_uint() - blocksize = self.unpack_uint() - rdev = self.unpack_uint() - blocks = self.unpack_uint() - fsid = self.unpack_uint() - fileid = self.unpack_uint() - atime = self.unpack_timeval() - mtime = self.unpack_timeval() - ctime = self.unpack_timeval() - return (type, mode, nlink, uid, gid, size, blocksize, \ - rdev, blocks, fsid, fileid, atime, mtime, ctime) - - def unpack_timeval(self): - secs = self.unpack_uint() - usecs = self.unpack_uint() - return (secs, usecs) - - -class NFSClient(UDPClient): - - def __init__(self, host): - UDPClient.__init__(self, host, NFS_PROGRAM, NFS_VERSION) - - def addpackers(self): - self.packer = NFSPacker() - self.unpacker = NFSUnpacker('') - - def mkcred(self): - if self.cred == None: - self.cred = rpc.AUTH_UNIX, rpc.make_auth_unix_default() - return self.cred - - def Getattr(self, fh): - return self.make_call(1, fh, \ - self.packer.pack_fhandle, \ - self.unpacker.unpack_attrstat) - - def Setattr(self, sa): - return self.make_call(2, sa, \ - self.packer.pack_sattrargs, \ - self.unpacker.unpack_attrstat) - - # Root() is obsolete - - def Lookup(self, da): - return self.make_call(4, da, \ - self.packer.pack_diropargs, \ - self.unpacker.unpack_diropres) - - # ... - - def Readdir(self, ra): - return self.make_call(16, ra, \ - self.packer.pack_readdirargs, \ - self.unpacker.unpack_readdirres) - - # Shorthand to get the entire contents of a directory - def Listdir(self, dir): - list = [] - ra = (dir, 0, 2000) - while 1: - (status, rest) = self.Readdir(ra) - if status <> NFS_OK: - break - entries, eof = rest - last_cookie = None - for fileid, name, cookie in entries: - list.append(fileid, name) - last_cookie = cookie - if eof or last_cookie == None: - break - ra = (ra[0], last_cookie, ra[2]) - return list - - -def test(): - import sys - if sys.argv[1:]: host = sys.argv[1] - else: host = '' - if sys.argv[2:]: filesys = sys.argv[2] - else: filesys = None - from mountclient import UDPMountClient, TCPMountClient - mcl = TCPMountClient(host) - if filesys == None: - list = mcl.Export() - for item in list: - print item - return - sf = mcl.Mnt(filesys) - print sf - fh = sf[1] - if fh: - ncl = NFSClient(host) - as = ncl.Getattr(fh) - print as - list = ncl.Listdir(fh) - for item in list: print item - mcl.Umnt(filesys) diff --git a/Demo/rpc/rnusersclient.py b/Demo/rpc/rnusersclient.py deleted file mode 100644 index e9cad620fd..0000000000 --- a/Demo/rpc/rnusersclient.py +++ /dev/null @@ -1,98 +0,0 @@ -# Remote nusers client interface - -import rpc -from rpc import Packer, Unpacker, UDPClient, BroadcastUDPClient - - -class RnusersPacker(Packer): - def pack_utmp(self, ui): - ut_line, ut_name, ut_host, ut_time = utmp - self.pack_string(ut_line) - self.pack_string(ut_name) - self.pack_string(ut_host) - self.pack_int(ut_time) - def pack_utmpidle(self, ui): - ui_itmp, ui_idle = ui - self.pack_utmp(ui_utmp) - self.pack_uint(ui_idle) - def pack_utmpidlearr(self, list): - self.pack_array(list, self.pack_itmpidle) - - -class RnusersUnpacker(Unpacker): - def unpack_utmp(self): - ut_line = self.unpack_string() - ut_name = self.unpack_string() - ut_host = self.unpack_string() - ut_time = self.unpack_int() - return ut_line, ut_name, ut_host, ut_time - def unpack_utmpidle(self): - ui_utmp = self.unpack_utmp() - ui_idle = self.unpack_uint() - return ui_utmp, ui_idle - def unpack_utmpidlearr(self): - return self.unpack_array(self.unpack_utmpidle) - - -class PartialRnusersClient: - - def addpackers(self): - self.packer = RnusersPacker() - self.unpacker = RnusersUnpacker('') - - def Num(self): - return self.make_call(1, None, None, self.unpacker.unpack_int) - - def Names(self): - return self.make_call(2, None, \ - None, self.unpacker.unpack_utmpidlearr) - - def Allnames(self): - return self.make_call(3, None, \ - None, self.unpacker.unpack_utmpidlearr) - - -class RnusersClient(PartialRnusersClient, UDPClient): - - def __init__(self, host): - UDPClient.__init__(self, host, 100002, 2) - - -class BroadcastRnusersClient(PartialRnusersClient, BroadcastUDPClient): - - def __init__(self, bcastaddr): - BroadcastUDPClient.__init__(self, bcastaddr, 100002, 2) - - -def test(): - import sys - if not sys.argv[1:]: - testbcast() - return - else: - host = sys.argv[1] - c = RnusersClient(host) - list = c.Names() - for (line, name, host, time), idle in list: - line = strip0(line) - name = strip0(name) - host = strip0(host) - print `name`, `host`, `line`, time, idle - -def testbcast(): - c = BroadcastRnusersClient('') - def listit(list, fromaddr): - host, port = fromaddr - print host + '\t:', - for (line, name, host, time), idle in list: - print strip0(name), - print - c.set_reply_handler(listit) - all = c.Names() - print 'Total Count:', len(all) - -def strip0(s): - while s and s[-1] == '\0': s = s[:-1] - return s - -test() diff --git a/Demo/rpc/rpc.py b/Demo/rpc/rpc.py deleted file mode 100644 index fb21fc2f98..0000000000 --- a/Demo/rpc/rpc.py +++ /dev/null @@ -1,863 +0,0 @@ -# Sun RPC version 2 -- RFC1057. - -# XXX There should be separate exceptions for the various reasons why -# XXX an RPC can fail, rather than using RuntimeError for everything - -# XXX The UDP version of the protocol resends requests when it does -# XXX not receive a timely reply -- use only for idempotent calls! - -# XXX There is no provision for call timeout on TCP connections - -import xdr -import socket -import os - -RPCVERSION = 2 - -CALL = 0 -REPLY = 1 - -AUTH_NULL = 0 -AUTH_UNIX = 1 -AUTH_SHORT = 2 -AUTH_DES = 3 - -MSG_ACCEPTED = 0 -MSG_DENIED = 1 - -SUCCESS = 0 # RPC executed successfully -PROG_UNAVAIL = 1 # remote hasn't exported program -PROG_MISMATCH = 2 # remote can't support version # -PROC_UNAVAIL = 3 # program can't support procedure -GARBAGE_ARGS = 4 # procedure can't decode params - -RPC_MISMATCH = 0 # RPC version number != 2 -AUTH_ERROR = 1 # remote can't authenticate caller - -AUTH_BADCRED = 1 # bad credentials (seal broken) -AUTH_REJECTEDCRED = 2 # client must begin new session -AUTH_BADVERF = 3 # bad verifier (seal broken) -AUTH_REJECTEDVERF = 4 # verifier expired or replayed -AUTH_TOOWEAK = 5 # rejected for security reasons - - -class Packer(xdr.Packer): - - def pack_auth(self, auth): - flavor, stuff = auth - self.pack_enum(flavor) - self.pack_opaque(stuff) - - def pack_auth_unix(self, stamp, machinename, uid, gid, gids): - self.pack_uint(stamp) - self.pack_string(machinename) - self.pack_uint(uid) - self.pack_uint(gid) - self.pack_uint(len(gids)) - for i in gids: - self.pack_uint(i) - - def pack_callheader(self, xid, prog, vers, proc, cred, verf): - self.pack_uint(xid) - self.pack_enum(CALL) - self.pack_uint(RPCVERSION) - self.pack_uint(prog) - self.pack_uint(vers) - self.pack_uint(proc) - self.pack_auth(cred) - self.pack_auth(verf) - # Caller must add procedure-specific part of call - - def pack_replyheader(self, xid, verf): - self.pack_uint(xid) - self.pack_enum(REPLY) - self.pack_uint(MSG_ACCEPTED) - self.pack_auth(verf) - self.pack_enum(SUCCESS) - # Caller must add procedure-specific part of reply - - -# Exceptions -BadRPCFormat = 'rpc.BadRPCFormat' -BadRPCVersion = 'rpc.BadRPCVersion' -GarbageArgs = 'rpc.GarbageArgs' - -class Unpacker(xdr.Unpacker): - - def unpack_auth(self): - flavor = self.unpack_enum() - stuff = self.unpack_opaque() - return (flavor, stuff) - - def unpack_callheader(self): - xid = self.unpack_uint(xid) - temp = self.unpack_enum() - if temp <> CALL: - raise BadRPCFormat, 'no CALL but ' + `temp` - temp = self.unpack_uint() - if temp <> RPCVERSION: - raise BadRPCVerspion, 'bad RPC version ' + `temp` - prog = self.unpack_uint() - vers = self.unpack_uint() - proc = self.unpack_uint() - cred = self.unpack_auth() - verf = self.unpack_auth() - return xid, prog, vers, proc, cred, verf - # Caller must add procedure-specific part of call - - def unpack_replyheader(self): - xid = self.unpack_uint() - mtype = self.unpack_enum() - if mtype <> REPLY: - raise RuntimeError, 'no REPLY but ' + `mtype` - stat = self.unpack_enum() - if stat == MSG_DENIED: - stat = self.unpack_enum() - if stat == RPC_MISMATCH: - low = self.unpack_uint() - high = self.unpack_uint() - raise RuntimeError, \ - 'MSG_DENIED: RPC_MISMATCH: ' + `low, high` - if stat == AUTH_ERROR: - stat = self.unpack_uint() - raise RuntimeError, \ - 'MSG_DENIED: AUTH_ERROR: ' + `stat` - raise RuntimeError, 'MSG_DENIED: ' + `stat` - if stat <> MSG_ACCEPTED: - raise RuntimeError, \ - 'Neither MSG_DENIED nor MSG_ACCEPTED: ' + `stat` - verf = self.unpack_auth() - stat = self.unpack_enum() - if stat == PROG_UNAVAIL: - raise RuntimeError, 'call failed: PROG_UNAVAIL' - if stat == PROG_MISMATCH: - low = self.unpack_uint() - high = self.unpack_uint() - raise RuntimeError, \ - 'call failed: PROG_MISMATCH: ' + `low, high` - if stat == PROC_UNAVAIL: - raise RuntimeError, 'call failed: PROC_UNAVAIL' - if stat == GARBAGE_ARGS: - raise RuntimeError, 'call failed: GARBAGE_ARGS' - if stat <> SUCCESS: - raise RuntimeError, 'call failed: ' + `stat` - return xid, verf - # Caller must get procedure-specific part of reply - - -# Subroutines to create opaque authentication objects - -def make_auth_null(): - return '' - -def make_auth_unix(seed, host, uid, gid, groups): - p = Packer() - p.pack_auth_unix(seed, host, uid, gid, groups) - return p.get_buf() - -def make_auth_unix_default(): - try: - from os import getuid, getgid - uid = getuid() - gid = getgid() - except ImportError: - uid = gid = 0 - import time - return make_auth_unix(int(time.time()), \ - socket.gethostname(), uid, gid, []) - - -# Common base class for clients - -class Client: - - def __init__(self, host, prog, vers, port): - self.host = host - self.prog = prog - self.vers = vers - self.port = port - self.makesocket() # Assigns to self.sock - self.bindsocket() - self.connsocket() - self.lastxid = 0 # XXX should be more random? - self.addpackers() - self.cred = None - self.verf = None - - def close(self): - self.sock.close() - - def makesocket(self): - # This MUST be overridden - raise RuntimeError, 'makesocket not defined' - - def connsocket(self): - # Override this if you don't want/need a connection - self.sock.connect((self.host, self.port)) - - def bindsocket(self): - # Override this to bind to a different port (e.g. reserved) - self.sock.bind(('', 0)) - - def addpackers(self): - # Override this to use derived classes from Packer/Unpacker - self.packer = Packer() - self.unpacker = Unpacker('') - - def make_call(self, proc, args, pack_func, unpack_func): - # Don't normally override this (but see Broadcast) - if pack_func is None and args is not None: - raise TypeError, 'non-null args with null pack_func' - self.start_call(proc) - if pack_func: - pack_func(args) - self.do_call() - if unpack_func: - result = unpack_func() - else: - result = None - self.unpacker.done() - return result - - def start_call(self, proc): - # Don't override this - self.lastxid = xid = self.lastxid + 1 - cred = self.mkcred() - verf = self.mkverf() - p = self.packer - p.reset() - p.pack_callheader(xid, self.prog, self.vers, proc, cred, verf) - - def do_call(self): - # This MUST be overridden - raise RuntimeError, 'do_call not defined' - - def mkcred(self): - # Override this to use more powerful credentials - if self.cred == None: - self.cred = (AUTH_NULL, make_auth_null()) - return self.cred - - def mkverf(self): - # Override this to use a more powerful verifier - if self.verf == None: - self.verf = (AUTH_NULL, make_auth_null()) - return self.verf - - def call_0(self): # Procedure 0 is always like this - return self.make_call(0, None, None, None) - - -# Record-Marking standard support - -def sendfrag(sock, last, frag): - x = len(frag) - if last: x = x | 0x80000000L - header = (chr(int(x>>24 & 0xff)) + chr(int(x>>16 & 0xff)) + \ - chr(int(x>>8 & 0xff)) + chr(int(x & 0xff))) - sock.send(header + frag) - -def sendrecord(sock, record): - sendfrag(sock, 1, record) - -def recvfrag(sock): - header = sock.recv(4) - if len(header) < 4: - raise EOFError - x = long(ord(header[0]))<<24 | ord(header[1])<<16 | \ - ord(header[2])<<8 | ord(header[3]) - last = ((x & 0x80000000) != 0) - n = int(x & 0x7fffffff) - frag = '' - while n > 0: - buf = sock.recv(n) - if not buf: raise EOFError - n = n - len(buf) - frag = frag + buf - return last, frag - -def recvrecord(sock): - record = '' - last = 0 - while not last: - last, frag = recvfrag(sock) - record = record + frag - return record - - -# Try to bind to a reserved port (must be root) - -last_resv_port_tried = None -def bindresvport(sock, host): - global last_resv_port_tried - FIRST, LAST = 600, 1024 # Range of ports to try - if last_resv_port_tried == None: - import os - last_resv_port_tried = FIRST + os.getpid() % (LAST-FIRST) - for i in range(last_resv_port_tried, LAST) + \ - range(FIRST, last_resv_port_tried): - last_resv_port_tried = i - try: - sock.bind((host, i)) - return last_resv_port_tried - except socket.error, (errno, msg): - if errno <> 114: - raise socket.error, (errno, msg) - raise RuntimeError, 'can\'t assign reserved port' - - -# Client using TCP to a specific port - -class RawTCPClient(Client): - - def makesocket(self): - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - - def do_call(self): - call = self.packer.get_buf() - sendrecord(self.sock, call) - reply = recvrecord(self.sock) - u = self.unpacker - u.reset(reply) - xid, verf = u.unpack_replyheader() - if xid <> self.lastxid: - # Can't really happen since this is TCP... - raise RuntimeError, 'wrong xid in reply ' + `xid` + \ - ' instead of ' + `self.lastxid` - - -# Client using UDP to a specific port - -class RawUDPClient(Client): - - def makesocket(self): - self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - - def do_call(self): - call = self.packer.get_buf() - self.sock.send(call) - try: - from select import select - except ImportError: - print 'WARNING: select not found, RPC may hang' - select = None - BUFSIZE = 8192 # Max UDP buffer size - timeout = 1 - count = 5 - while 1: - r, w, x = [self.sock], [], [] - if select: - r, w, x = select(r, w, x, timeout) - if self.sock not in r: - count = count - 1 - if count < 0: raise RuntimeError, 'timeout' - if timeout < 25: timeout = timeout *2 -## print 'RESEND', timeout, count - self.sock.send(call) - continue - reply = self.sock.recv(BUFSIZE) - u = self.unpacker - u.reset(reply) - xid, verf = u.unpack_replyheader() - if xid <> self.lastxid: -## print 'BAD xid' - continue - break - - -# Client using UDP broadcast to a specific port - -class RawBroadcastUDPClient(RawUDPClient): - - def __init__(self, bcastaddr, prog, vers, port): - RawUDPClient.__init__(self, bcastaddr, prog, vers, port) - self.reply_handler = None - self.timeout = 30 - - def connsocket(self): - # Don't connect -- use sendto - self.sock.allowbroadcast(1) - - def set_reply_handler(self, reply_handler): - self.reply_handler = reply_handler - - def set_timeout(self, timeout): - self.timeout = timeout # Use None for infinite timeout - - def make_call(self, proc, args, pack_func, unpack_func): - if pack_func is None and args is not None: - raise TypeError, 'non-null args with null pack_func' - self.start_call(proc) - if pack_func: - pack_func(args) - call = self.packer.get_buf() - self.sock.sendto(call, (self.host, self.port)) - try: - from select import select - except ImportError: - print 'WARNING: select not found, broadcast will hang' - select = None - BUFSIZE = 8192 # Max UDP buffer size (for reply) - replies = [] - if unpack_func is None: - def dummy(): pass - unpack_func = dummy - while 1: - r, w, x = [self.sock], [], [] - if select: - if self.timeout is None: - r, w, x = select(r, w, x) - else: - r, w, x = select(r, w, x, self.timeout) - if self.sock not in r: - break - reply, fromaddr = self.sock.recvfrom(BUFSIZE) - u = self.unpacker - u.reset(reply) - xid, verf = u.unpack_replyheader() - if xid <> self.lastxid: -## print 'BAD xid' - continue - reply = unpack_func() - self.unpacker.done() - replies.append((reply, fromaddr)) - if self.reply_handler: - self.reply_handler(reply, fromaddr) - return replies - - -# Port mapper interface - -# Program number, version and (fixed!) port number -PMAP_PROG = 100000 -PMAP_VERS = 2 -PMAP_PORT = 111 - -# Procedure numbers -PMAPPROC_NULL = 0 # (void) -> void -PMAPPROC_SET = 1 # (mapping) -> bool -PMAPPROC_UNSET = 2 # (mapping) -> bool -PMAPPROC_GETPORT = 3 # (mapping) -> unsigned int -PMAPPROC_DUMP = 4 # (void) -> pmaplist -PMAPPROC_CALLIT = 5 # (call_args) -> call_result - -# A mapping is (prog, vers, prot, port) and prot is one of: - -IPPROTO_TCP = 6 -IPPROTO_UDP = 17 - -# A pmaplist is a variable-length list of mappings, as follows: -# either (1, mapping, pmaplist) or (0). - -# A call_args is (prog, vers, proc, args) where args is opaque; -# a call_result is (port, res) where res is opaque. - - -class PortMapperPacker(Packer): - - def pack_mapping(self, mapping): - prog, vers, prot, port = mapping - self.pack_uint(prog) - self.pack_uint(vers) - self.pack_uint(prot) - self.pack_uint(port) - - def pack_pmaplist(self, list): - self.pack_list(list, self.pack_mapping) - - def pack_call_args(self, ca): - prog, vers, proc, args = ca - self.pack_uint(prog) - self.pack_uint(vers) - self.pack_uint(proc) - self.pack_opaque(args) - - -class PortMapperUnpacker(Unpacker): - - def unpack_mapping(self): - prog = self.unpack_uint() - vers = self.unpack_uint() - prot = self.unpack_uint() - port = self.unpack_uint() - return prog, vers, prot, port - - def unpack_pmaplist(self): - return self.unpack_list(self.unpack_mapping) - - def unpack_call_result(self): - port = self.unpack_uint() - res = self.unpack_opaque() - return port, res - - -class PartialPortMapperClient: - - def addpackers(self): - self.packer = PortMapperPacker() - self.unpacker = PortMapperUnpacker('') - - def Set(self, mapping): - return self.make_call(PMAPPROC_SET, mapping, \ - self.packer.pack_mapping, \ - self.unpacker.unpack_uint) - - def Unset(self, mapping): - return self.make_call(PMAPPROC_UNSET, mapping, \ - self.packer.pack_mapping, \ - self.unpacker.unpack_uint) - - def Getport(self, mapping): - return self.make_call(PMAPPROC_GETPORT, mapping, \ - self.packer.pack_mapping, \ - self.unpacker.unpack_uint) - - def Dump(self): - return self.make_call(PMAPPROC_DUMP, None, \ - None, \ - self.unpacker.unpack_pmaplist) - - def Callit(self, ca): - return self.make_call(PMAPPROC_CALLIT, ca, \ - self.packer.pack_call_args, \ - self.unpacker.unpack_call_result) - - -class TCPPortMapperClient(PartialPortMapperClient, RawTCPClient): - - def __init__(self, host): - RawTCPClient.__init__(self, \ - host, PMAP_PROG, PMAP_VERS, PMAP_PORT) - - -class UDPPortMapperClient(PartialPortMapperClient, RawUDPClient): - - def __init__(self, host): - RawUDPClient.__init__(self, \ - host, PMAP_PROG, PMAP_VERS, PMAP_PORT) - - -class BroadcastUDPPortMapperClient(PartialPortMapperClient, \ - RawBroadcastUDPClient): - - def __init__(self, bcastaddr): - RawBroadcastUDPClient.__init__(self, \ - bcastaddr, PMAP_PROG, PMAP_VERS, PMAP_PORT) - - -# Generic clients that find their server through the Port mapper - -class TCPClient(RawTCPClient): - - def __init__(self, host, prog, vers): - pmap = TCPPortMapperClient(host) - port = pmap.Getport((prog, vers, IPPROTO_TCP, 0)) - pmap.close() - if port == 0: - raise RuntimeError, 'program not registered' - RawTCPClient.__init__(self, host, prog, vers, port) - - -class UDPClient(RawUDPClient): - - def __init__(self, host, prog, vers): - pmap = UDPPortMapperClient(host) - port = pmap.Getport((prog, vers, IPPROTO_UDP, 0)) - pmap.close() - if port == 0: - raise RuntimeError, 'program not registered' - RawUDPClient.__init__(self, host, prog, vers, port) - - -class BroadcastUDPClient(Client): - - def __init__(self, bcastaddr, prog, vers): - self.pmap = BroadcastUDPPortMapperClient(bcastaddr) - self.pmap.set_reply_handler(self.my_reply_handler) - self.prog = prog - self.vers = vers - self.user_reply_handler = None - self.addpackers() - - def close(self): - self.pmap.close() - - def set_reply_handler(self, reply_handler): - self.user_reply_handler = reply_handler - - def set_timeout(self, timeout): - self.pmap.set_timeout(timeout) - - def my_reply_handler(self, reply, fromaddr): - port, res = reply - self.unpacker.reset(res) - result = self.unpack_func() - self.unpacker.done() - self.replies.append((result, fromaddr)) - if self.user_reply_handler is not None: - self.user_reply_handler(result, fromaddr) - - def make_call(self, proc, args, pack_func, unpack_func): - self.packer.reset() - if pack_func: - pack_func(args) - if unpack_func is None: - def dummy(): pass - self.unpack_func = dummy - else: - self.unpack_func = unpack_func - self.replies = [] - packed_args = self.packer.get_buf() - dummy_replies = self.pmap.Callit( \ - (self.prog, self.vers, proc, packed_args)) - return self.replies - - -# Server classes - -# These are not symmetric to the Client classes -# XXX No attempt is made to provide authorization hooks yet - -class Server: - - def __init__(self, host, prog, vers, port): - self.host = host # Should normally be '' for default interface - self.prog = prog - self.vers = vers - self.port = port # Should normally be 0 for random port - self.makesocket() # Assigns to self.sock and self.prot - self.bindsocket() - self.host, self.port = self.sock.getsockname() - self.addpackers() - - def register(self): - mapping = self.prog, self.vers, self.prot, self.port - p = TCPPortMapperClient(self.host) - if not p.Set(mapping): - raise RuntimeError, 'register failed' - - def unregister(self): - mapping = self.prog, self.vers, self.prot, self.port - p = TCPPortMapperClient(self.host) - if not p.Unset(mapping): - raise RuntimeError, 'unregister failed' - - def handle(self, call): - # Don't use unpack_header but parse the header piecewise - # XXX I have no idea if I am using the right error responses! - self.unpacker.reset(call) - self.packer.reset() - xid = self.unpacker.unpack_uint() - self.packer.pack_uint(xid) - temp = self.unpacker.unpack_enum() - if temp <> CALL: - return None # Not worthy of a reply - self.packer.pack_uint(REPLY) - temp = self.unpacker.unpack_uint() - if temp <> RPCVERSION: - self.packer.pack_uint(MSG_DENIED) - self.packer.pack_uint(RPC_MISMATCH) - self.packer.pack_uint(RPCVERSION) - self.packer.pack_uint(RPCVERSION) - return self.packer.get_buf() - self.packer.pack_uint(MSG_ACCEPTED) - self.packer.pack_auth((AUTH_NULL, make_auth_null())) - prog = self.unpacker.unpack_uint() - if prog <> self.prog: - self.packer.pack_uint(PROG_UNAVAIL) - return self.packer.get_buf() - vers = self.unpacker.unpack_uint() - if vers <> self.vers: - self.packer.pack_uint(PROG_MISMATCH) - self.packer.pack_uint(self.vers) - self.packer.pack_uint(self.vers) - return self.packer.get_buf() - proc = self.unpacker.unpack_uint() - methname = 'handle_' + `proc` - try: - meth = getattr(self, methname) - except AttributeError: - self.packer.pack_uint(PROC_UNAVAIL) - return self.packer.get_buf() - cred = self.unpacker.unpack_auth() - verf = self.unpacker.unpack_auth() - try: - meth() # Unpack args, call turn_around(), pack reply - except (EOFError, GarbageArgs): - # Too few or too many arguments - self.packer.reset() - self.packer.pack_uint(xid) - self.packer.pack_uint(REPLY) - self.packer.pack_uint(MSG_ACCEPTED) - self.packer.pack_auth((AUTH_NULL, make_auth_null())) - self.packer.pack_uint(GARBAGE_ARGS) - return self.packer.get_buf() - - def turn_around(self): - try: - self.unpacker.done() - except RuntimeError: - raise GarbageArgs - self.packer.pack_uint(SUCCESS) - - def handle_0(self): # Handle NULL message - self.turn_around() - - def makesocket(self): - # This MUST be overridden - raise RuntimeError, 'makesocket not defined' - - def bindsocket(self): - # Override this to bind to a different port (e.g. reserved) - self.sock.bind((self.host, self.port)) - - def addpackers(self): - # Override this to use derived classes from Packer/Unpacker - self.packer = Packer() - self.unpacker = Unpacker('') - - -class TCPServer(Server): - - def makesocket(self): - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.prot = IPPROTO_TCP - - def loop(self): - self.sock.listen(0) - while 1: - self.session(self.sock.accept()) - - def session(self, connection): - sock, (host, port) = connection - while 1: - try: - call = recvrecord(sock) - except EOFError: - break - except socket.error, msg: - print 'socket error:', msg - break - reply = self.handle(call) - if reply is not None: - sendrecord(sock, reply) - - def forkingloop(self): - # Like loop but uses forksession() - self.sock.listen(0) - while 1: - self.forksession(self.sock.accept()) - - def forksession(self, connection): - # Like session but forks off a subprocess - import os - # Wait for deceased children - try: - while 1: - pid, sts = os.waitpid(0, 1) - except os.error: - pass - pid = None - try: - pid = os.fork() - if pid: # Parent - connection[0].close() - return - # Child - self.session(connection) - finally: - # Make sure we don't fall through in the parent - if pid == 0: - os._exit(0) - - -class UDPServer(Server): - - def makesocket(self): - self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - self.prot = IPPROTO_UDP - - def loop(self): - while 1: - self.session() - - def session(self): - call, host_port = self.sock.recvfrom(8192) - reply = self.handle(call) - if reply <> None: - self.sock.sendto(reply, host_port) - - -# Simple test program -- dump local portmapper status - -def test(): - pmap = UDPPortMapperClient('') - list = pmap.Dump() - list.sort() - for prog, vers, prot, port in list: - print prog, vers, - if prot == IPPROTO_TCP: print 'tcp', - elif prot == IPPROTO_UDP: print 'udp', - else: print prot, - print port - - -# Test program for broadcast operation -- dump everybody's portmapper status - -def testbcast(): - import sys - if sys.argv[1:]: - bcastaddr = sys.argv[1] - else: - bcastaddr = '' - def rh(reply, fromaddr): - host, port = fromaddr - print host + '\t' + `reply` - pmap = BroadcastUDPPortMapperClient(bcastaddr) - pmap.set_reply_handler(rh) - pmap.set_timeout(5) - replies = pmap.Getport((100002, 1, IPPROTO_UDP, 0)) - - -# Test program for server, with corresponding client -# On machine A: python -c 'import rpc; rpc.testsvr()' -# On machine B: python -c 'import rpc; rpc.testclt()' A -# (A may be == B) - -def testsvr(): - # Simple test class -- proc 1 doubles its string argument as reply - class S(UDPServer): - def handle_1(self): - arg = self.unpacker.unpack_string() - self.turn_around() - print 'RPC function 1 called, arg', `arg` - self.packer.pack_string(arg + arg) - # - s = S('', 0x20000000, 1, 0) - try: - s.unregister() - except RuntimeError, msg: - print 'RuntimeError:', msg, '(ignored)' - s.register() - print 'Service started...' - try: - s.loop() - finally: - s.unregister() - print 'Service interrupted.' - - -def testclt(): - import sys - if sys.argv[1:]: host = sys.argv[1] - else: host = '' - # Client for above server - class C(UDPClient): - def call_1(self, arg): - return self.make_call(1, arg, \ - self.packer.pack_string, \ - self.unpacker.unpack_string) - c = C(host, 0x20000000, 1) - print 'making call...' - reply = c.call_1('hello, world, ') - print 'call returned', `reply` diff --git a/Demo/rpc/test b/Demo/rpc/test deleted file mode 100755 index d3c9591b70..0000000000 --- a/Demo/rpc/test +++ /dev/null @@ -1,23 +0,0 @@ -: ${PYTHON=python} - -set -xe - -$PYTHON -c 'from rpc import test; test()' -$PYTHON -c 'from rpc import test; test()' charon.cwi.nl - -$PYTHON -c 'from rpc import testsvr; testsvr()' & -SVR=$! -sleep 2 -$PYTHON -c 'from rpc import testclt; testclt()' -kill -2 $SVR - -$PYTHON -c 'from mountclient import test; test()' -$PYTHON -c 'from mountclient import test; test()' gatekeeper.dec.com - -$PYTHON -c 'from nfsclient import test; test()' -$PYTHON -c 'from nfsclient import test; test()' gatekeeper.dec.com -$PYTHON -c 'from nfsclient import test; test()' gatekeeper.dec.com /archive - -$PYTHON -c 'from rnusersclient import test; test()' '' - -$PYTHON -c 'from rpc import testbcast; testbcast()' diff --git a/Demo/rpc/xdr.py b/Demo/rpc/xdr.py deleted file mode 100644 index 0c5185ee88..0000000000 --- a/Demo/rpc/xdr.py +++ /dev/null @@ -1,201 +0,0 @@ -# Implement (a subset of) Sun XDR -- RFC1014. - - -try: - import struct -except ImportError: - struct = None - - -Long = type(0L) - - -class Packer: - - def __init__(self): - self.reset() - - def reset(self): - self.buf = '' - - def get_buf(self): - return self.buf - - def pack_uint(self, x): - self.buf = self.buf + \ - (chr(int(x>>24 & 0xff)) + chr(int(x>>16 & 0xff)) + \ - chr(int(x>>8 & 0xff)) + chr(int(x & 0xff))) - if struct and struct.pack('l', 1) == '\0\0\0\1': - def pack_uint(self, x): - if type(x) == Long: - x = int((x + 0x80000000L) % 0x100000000L \ - - 0x80000000L) - self.buf = self.buf + struct.pack('l', x) - - pack_int = pack_uint - - pack_enum = pack_int - - def pack_bool(self, x): - if x: self.buf = self.buf + '\0\0\0\1' - else: self.buf = self.buf + '\0\0\0\0' - - def pack_uhyper(self, x): - self.pack_uint(int(x>>32 & 0xffffffff)) - self.pack_uint(int(x & 0xffffffff)) - - pack_hyper = pack_uhyper - - def pack_float(self, x): - # XXX - self.buf = self.buf + struct.pack('f', x) - - def pack_double(self, x): - # XXX - self.buf = self.buf + struct.pack('d', x) - - def pack_fstring(self, n, s): - if n < 0: - raise ValueError, 'fstring size must be nonnegative' - n = ((n+3)/4)*4 - data = s[:n] - data = data + (n - len(data)) * '\0' - self.buf = self.buf + data - - pack_fopaque = pack_fstring - - def pack_string(self, s): - n = len(s) - self.pack_uint(n) - self.pack_fstring(n, s) - - pack_opaque = pack_string - - def pack_list(self, list, pack_item): - for item in list: - self.pack_uint(1) - pack_item(item) - self.pack_uint(0) - - def pack_farray(self, n, list, pack_item): - if len(list) <> n: - raise ValueError, 'wrong array size' - for item in list: - pack_item(item) - - def pack_array(self, list, pack_item): - n = len(list) - self.pack_uint(n) - self.pack_farray(n, list) - - -class Unpacker: - - def __init__(self, data): - self.reset(data) - - def reset(self, data): - self.buf = data - self.pos = 0 - - def done(self): - if self.pos < len(self.buf): - raise RuntimeError, 'unextracted data remains' - - def unpack_uint(self): - i = self.pos - self.pos = j = i+4 - data = self.buf[i:j] - if len(data) < 4: - raise EOFError - x = long(ord(data[0]))<<24 | ord(data[1])<<16 | \ - ord(data[2])<<8 | ord(data[3]) - # Return a Python long only if the value is not representable - # as a nonnegative Python int - if x < 0x80000000L: x = int(x) - return x - if struct and struct.unpack('l', '\0\0\0\1') == 1: - def unpack_uint(self): - i = self.pos - self.pos = j = i+4 - data = self.buf[i:j] - if len(data) < 4: - raise EOFError - return struct.unpack('l', data) - - def unpack_int(self): - x = self.unpack_uint() - if x >= 0x80000000L: x = x - 0x100000000L - return int(x) - - unpack_enum = unpack_int - - unpack_bool = unpack_int - - def unpack_uhyper(self): - hi = self.unpack_uint() - lo = self.unpack_uint() - return long(hi)<<32 | lo - - def unpack_hyper(self): - x = self.unpack_uhyper() - if x >= 0x8000000000000000L: x = x - 0x10000000000000000L - return x - - def unpack_float(self): - # XXX - i = self.pos - self.pos = j = i+4 - data = self.buf[i:j] - if len(data) < 4: - raise EOFError - return struct.unpack('f', data)[0] - - def unpack_double(self): - # XXX - i = self.pos - self.pos = j = i+8 - data = self.buf[i:j] - if len(data) < 8: - raise EOFError - return struct.unpack('8', data)[0] - - def unpack_fstring(self, n): - if n < 0: - raise ValueError, 'fstring size must be nonnegative' - i = self.pos - j = i + (n+3)/4*4 - if j > len(self.buf): - raise EOFError - self.pos = j - return self.buf[i:i+n] - - unpack_fopaque = unpack_fstring - - def unpack_string(self): - n = self.unpack_uint() - return self.unpack_fstring(n) - - unpack_opaque = unpack_string - - def unpack_list(self, unpack_item): - list = [] - while 1: - x = self.unpack_uint() - if x == 0: break - if x <> 1: - raise RuntimeError, \ - '0 or 1 expected, got ' + `x` - item = unpack_item() - list.append(item) - return list - - def unpack_farray(self, n, unpack_item): - list = [] - for i in range(n): - list.append(unpack_item()) - return list - - def unpack_array(self, unpack_item): - n = self.unpack_uint() - return self.unpack_farray(n, unpack_item) diff --git a/Demo/scripts/README b/Demo/scripts/README deleted file mode 100644 index 4c46f5f611..0000000000 --- a/Demo/scripts/README +++ /dev/null @@ -1,38 +0,0 @@ -This directory contains a collection of executable Python scripts. - -Some perform Python housekeeping jobs (e.g., converting old syntax or -generating tags files), others are useful UNIX tools, are some are -just cute demos (e.g., pi.py). - -A number of these of these deserve a link in your bin directory. All -deserve study if you want to learn Python programming. - -Table of contents: - -byteyears.py Print product of a file's size and age -checkpyc.py Check presence and validity of ".pyc" files -classfix.py Convert old class syntax to new -copytime.py Copy one file's atime and mtime to another -h2py.py Translate #define's into Python assignments -dutree.py Format du(1) output as a tree sorted by size -eptags.py Create Emacs TAGS file for Python modules -fact.py Factorize numbers -findlinksto.py Recursively find symbolic links to a given path prefix -fixps.py Fix Python scripts' first line (if #!) -fixcid.py Massive identifier substitution on C source files -freeze.py Convert a Python script into a free-standing binary -from.py Summarize mailbox -linktree.py Make a copy of a tree with links to original files -lll.py Find and list symbolic links in current directory -lpwatch.py Watch BSD line printer queues -methfix.py Fix old method syntax def f(self, (a1, ..., aN)): -mkreal.py Turn a symbolic link into a real file or directory -objgraph.py Print object graph from nm output on a library -pdeps.py Print dependencies between Python modules -pi.py Print all digits of pi -- given enough time and memory -pp.py Emulate some Perl command line options -primes.py Print prime numbers -ptags.py Create vi tags file for Python modules -suff.py Sort a list of files by suffix -which.py Find a program in $PATH -xxci.py Wrapper for rcsdiff and ci diff --git a/Demo/scripts/eqfix.py b/Demo/scripts/eqfix.py deleted file mode 100755 index 74b5536ea8..0000000000 --- a/Demo/scripts/eqfix.py +++ /dev/null @@ -1,200 +0,0 @@ -#! /ufs/guido/bin/sgi/python -#! /usr/local/bin/python - -# Fix Python source files to use the new equality test operator, i.e., -# if x = y: ... -# is changed to -# if x == y: ... -# The script correctly tokenizes the Python program to reliably -# distinguish between assignments and equality tests. -# -# Command line arguments are files or directories to be processed. -# Directories are searched recursively for files whose name looks -# like a python module. -# Symbolic links are always ignored (except as explicit directory -# arguments). Of course, the original file is kept as a back-up -# (with a "~" attached to its name). -# It complains about binaries (files containing null bytes) -# and about files that are ostensibly not Python files: if the first -# line starts with '#!' and does not contain the string 'python'. -# -# Changes made are reported to stdout in a diff-like format. -# -# Undoubtedly you can do this using find and sed or perl, but this is -# a nice example of Python code that recurses down a directory tree -# and uses regular expressions. Also note several subtleties like -# preserving the file's mode and avoiding to even write a temp file -# when no changes are needed for a file. -# -# NB: by changing only the function fixline() you can turn this -# into a program for a different change to Python programs... - -import sys -import regex -import os -from stat import * -import string - -err = sys.stderr.write -dbg = err -rep = sys.stdout.write - -def main(): - bad = 0 - if not sys.argv[1:]: # No arguments - err('usage: ' + sys.argv[0] + ' file-or-directory ...\n') - sys.exit(2) - for arg in sys.argv[1:]: - if os.path.isdir(arg): - if recursedown(arg): bad = 1 - elif os.path.islink(arg): - err(arg + ': will not process symbolic links\n') - bad = 1 - else: - if fix(arg): bad = 1 - sys.exit(bad) - -ispythonprog = regex.compile('^[a-zA-Z0-9_]+\.py$') -def ispython(name): - return ispythonprog.match(name) >= 0 - -def recursedown(dirname): - dbg('recursedown(' + `dirname` + ')\n') - bad = 0 - try: - names = os.listdir(dirname) - except os.error, msg: - err(dirname + ': cannot list directory: ' + `msg` + '\n') - return 1 - names.sort() - subdirs = [] - for name in names: - if name in (os.curdir, os.pardir): continue - fullname = os.path.join(dirname, name) - if os.path.islink(fullname): pass - elif os.path.isdir(fullname): - subdirs.append(fullname) - elif ispython(name): - if fix(fullname): bad = 1 - for fullname in subdirs: - if recursedown(fullname): bad = 1 - return bad - -def fix(filename): -## dbg('fix(' + `filename` + ')\n') - try: - f = open(filename, 'r') - except IOError, msg: - err(filename + ': cannot open: ' + `msg` + '\n') - return 1 - head, tail = os.path.split(filename) - tempname = os.path.join(head, '@' + tail) - g = None - # If we find a match, we rewind the file and start over but - # now copy everything to a temp file. - lineno = 0 - while 1: - line = f.readline() - if not line: break - lineno = lineno + 1 - if g is None and '\0' in line: - # Check for binary files - err(filename + ': contains null bytes; not fixed\n') - f.close() - return 1 - if lineno == 1 and g is None and line[:2] == '#!': - # Check for non-Python scripts - words = string.split(line[2:]) - if words and regex.search('[pP]ython', words[0]) < 0: - msg = filename + ': ' + words[0] - msg = msg + ' script; not fixed\n' - err(msg) - f.close() - return 1 - while line[-2:] == '\\\n': - nextline = f.readline() - if not nextline: break - line = line + nextline - lineno = lineno + 1 - newline = fixline(line) - if newline != line: - if g is None: - try: - g = open(tempname, 'w') - except IOError, msg: - f.close() - err(tempname+': cannot create: '+\ - `msg`+'\n') - return 1 - f.seek(0) - lineno = 0 - rep(filename + ':\n') - continue # restart from the beginning - rep(`lineno` + '\n') - rep('< ' + line) - rep('> ' + newline) - if g is not None: - g.write(newline) - - # End of file - f.close() - if not g: return 0 # No changes - - # Finishing touch -- move files - - # First copy the file's mode to the temp file - try: - statbuf = os.stat(filename) - os.chmod(tempname, statbuf[ST_MODE] & 07777) - except os.error, msg: - err(tempname + ': warning: chmod failed (' + `msg` + ')\n') - # Then make a backup of the original file as filename~ - try: - os.rename(filename, filename + '~') - except os.error, msg: - err(filename + ': warning: backup failed (' + `msg` + ')\n') - # Now move the temp file to the original file - try: - os.rename(tempname, filename) - except os.error, msg: - err(filename + ': rename failed (' + `msg` + ')\n') - return 1 - # Return succes - return 0 - - -from tokenize import tokenprog - -match = {'if':':', 'elif':':', 'while':':', 'return':'\n', \ - '(':')', '[':']', '{':'}', '`':'`'} - -def fixline(line): - # Quick check for easy case - if '=' not in line: return line - - i, n = 0, len(line) - stack = [] - while i < n: - j = tokenprog.match(line, i) - if j < 0: - # A bad token; forget about the rest of this line - print '(Syntax error:)' - print line, - return line - a, b = tokenprog.regs[3] # Location of the token proper - token = line[a:b] - i = i+j - if stack and token == stack[-1]: - del stack[-1] - elif match.has_key(token): - stack.append(match[token]) - elif token == '=' and stack: - line = line[:a] + '==' + line[b:] - i, n = a + len('=='), len(line) - elif token == '==' and not stack: - print '(Warning: \'==\' at top level:)' - print line, - return line - - -main() diff --git a/Demo/scripts/fact.py b/Demo/scripts/fact.py deleted file mode 100755 index bf49afcc44..0000000000 --- a/Demo/scripts/fact.py +++ /dev/null @@ -1,48 +0,0 @@ -#! /usr/local/bin/python - -# Factorize numbers. -# The algorithm is not efficient, but easy to understand. -# If there are large factors, it will take forever to find them, -# because we try all odd numbers between 3 and sqrt(n)... - -import sys -from math import sqrt - -error = 'fact.error' # exception - -def fact(n): - if n < 1: raise error # fact() argument should be >= 1 - if n == 1: return [] # special case - res = [] - # Treat even factors special, so we can use i = i+2 later - while n%2 == 0: - res.append(2) - n = n/2 - # Try odd numbers up to sqrt(n) - limit = sqrt(float(n+1)) - i = 3 - while i <= limit: - if n%i == 0: - res.append(i) - n = n/i - limit = sqrt(n+1) - else: - i = i+2 - if n != 1: - res.append(n) - return res - -def main(): - if len(sys.argv) > 1: - for arg in sys.argv[1:]: - n = eval(arg) - print n, fact(n) - else: - try: - while 1: - n = input() - print n, fact(n) - except EOFError: - pass - -main() diff --git a/Demo/scripts/freeze.py b/Demo/scripts/freeze.py deleted file mode 100755 index c17c33f83d..0000000000 --- a/Demo/scripts/freeze.py +++ /dev/null @@ -1,453 +0,0 @@ -#! /ufs/guido/bin/sgi/python - -# Given a Python script, create a binary that runs the script. -# The binary is 100% independent of Python libraries and binaries. -# It will not contain any Python source code -- only "compiled" Python -# (as initialized static variables containing marshalled code objects). -# It even does the right thing for dynamically loaded modules! -# The module search path of the binary is set to the current directory. -# -# Some problems remain: -# - It's highly non-portable, since it knows about paths and libraries -# (there's a customization section though, and it knows how to -# distinguish an SGI from a Sun SPARC system -- adding knowledge -# about more systems is left as an exercise for the reader). -# - You need to have the Python source tree lying around as well as -# the "libpython.a" used to generate the Python binary. -# - For scripts that use many modules it generates absurdly large -# files (frozen.c and config.o as well as the final binary), -# and is consequently rather slow. -# -# Caveats: -# - The search for modules sometimes finds modules that are never -# actually imported since the code importing them is never executed. -# - If an imported module isn't found, you get a warning but the -# process of freezing continues. The binary will fail if it -# actually tries to import one of these modules. -# - This often happens with the module 'mac', which module 'os' tries -# to import (to determine whether it is running on a Macintosh). -# You can ignore the warning about this. -# - If the program dynamically reads or generates Python code and -# executes it, this code may reference built-in or library modules -# that aren't present in the frozen binary, and this will fail. -# - Your program may be using external data files, e.g. compiled -# forms definitions (*.fd). These aren't incorporated. Since -# sys.path in the resulting binary only contains '.', if your -# program searches its data files along sys.path (as the 'flp' -# modules does to find its forms definitions), you may need to -# change the program to extend the search path or instruct its users -# to set the environment variable PYTHONPATH to point to your data -# files. -# -# Usage hints: -# - If you have a bunch of scripts that you want to freeze, instead -# of freezing each of them separately, you might consider writing -# a tiny main script that looks at sys.argv[0] and then imports -# the corresponding module. You can then make links to the -# frozen binary named after the various scripts you support. -# Pass the additional scripts as arguments after the main script. -# A minimal script to do this is the following. -# import sys, posixpath -# exec('import ' + posixpath.basename(sys.argv[0]) + '\n') - - -import os -import sys -import regex -import getopt -import regsub -import string -import marshal - -# Function to join two pathnames with a slash in between -j = os.path.join - -################################## -# START OF CONFIGURATION SECTION # -################################## - -# Attempt to guess machine architecture -if os.path.exists('/usr/lib/libgl_s'): ARCH = 'sgi' -else: ARCH = 'sun4' - -# Site parametrizations (change to match your site) -CC = 'cc' # C compiler -TOP = '/ufs/guido/src' # Parent of all source trees -PYTHON = j(TOP, 'python') # Top of the Python source tree -SRC = j(PYTHON, 'src') # Python source directory -BLD = j(PYTHON, 'build.' + ARCH) # Python build directory -#BLD = SRC # Use this if you build in SRC - -# Other packages (change to match your site) -DL = j(TOP, 'dl') # Top of the dl source tree -DL_DLD = j(TOP, 'dl-dld') # The dl-dld source directory -DLD = j(TOP, 'dld-3.2.3') # The dld source directory -FORMS = j(TOP, 'forms') # Top of the FORMS source tree -STDWIN = j(TOP, 'stdwin') # Top of the STDWIN source tree -READLINE = j(TOP, 'readline.' + ARCH) # Top of the GNU Readline source tree -SUN_X11 = '/usr/local/X11R5/lib/libX11.a' - -# File names (usually no need to change) -LIBP = j(BLD, 'libpython.a') # Main Python library -CONFIG = j(SRC, 'config.c') # Configuration source file -FMAIN = j(SRC, 'frozenmain.c') # Special main source file - -# Libraries needed when linking. First tuple item is built-in module -# for which it is needed (or '*' for always), rest are ld arguments. -# There is a separate list per architecture. -libdeps_sgi = [ \ - ('stdwin', j(STDWIN, 'Build/' + ARCH + '/x11/lib/lib.a')), \ - ('fl', j(FORMS, 'FORMS/libforms.a'), '-lfm_s'), \ - ('*', j(READLINE, 'libreadline.a'), '-ltermcap'), \ - ('al', '-laudio'), \ - ('sv', '-lsvideo', '-lXext'), \ - ('cd', '-lcdaudio', '-lds'), \ - ('cl', '-lcl'), \ - ('imgfile', '-limage', '-lgutil', '-lm'), \ - ('mpz', '/ufs/jh/src/gmp-1.2/libgmp.a'), \ - ('md5', '/ufs/jh/src/md5/md5.o'), \ - ('*', '-lsun'), \ - ('*', j(DL, 'libdl.a'), '-lmld'), \ - ('*', '-lmpc'), \ - ('fm', '-lfm_s'), \ - ('gl', '-lgl_s', '-lX11_s'), \ - ('stdwin', '-lX11_s'), \ - ('*', '-lm'), \ - ('*', '-lc_s'), \ - ] -libdeps_sun4 = [ \ - ('*', '-Bstatic'), \ - ('stdwin', j(STDWIN, 'Build/' + ARCH + '/x11/lib/lib.a')), \ - ('*', j(READLINE, 'libreadline.a')), \ - ('*', '-lm'), \ - ('*', j(DL_DLD,'libdl.a'), j(DLD,'libdld.a')), \ - ('*', SUN_X11), \ - ('*', '-ltermcap'), \ - ('*', '-lc'), \ - ] -libdeps = eval('libdeps_' + ARCH) - -################################ -# END OF CONFIGURATION SECTION # -################################ - -# Exception used when scanfile fails -NoSuchFile = 'NoSuchFile' - -# Global options -quiet = 0 # -q -verbose = 0 # -v -noexec = 0 # -n -nowrite = 0 # -N -ofile = 'a.out' # -o file - -# Main program -- argument parsing etc. -def main(): - global quiet, verbose, noexec, nowrite, ofile - try: - opts, args = getopt.getopt(sys.argv[1:], 'nNo:qv') - except getopt.error, msg: - usage(str(msg)) - sys.exit(2) - for o, a in opts: - if o == '-n': noexec = 1 - if o == '-N': nowrite = 1 - if o == '-o': ofile = a - if o == '-q': verbose = 0; quiet = 1 - if o == '-v': verbose = verbose + 1; quiet = 0 - if len(args) < 1: - usage('please pass at least one file argument') - sys.exit(2) - process(args[0], args[1:]) - -# Print usage message to stderr -def usage(*msgs): - sys.stdout = sys.stderr - for msg in msgs: print msg - print 'Usage: freeze [options] scriptfile [modulefile ...]' - print '-n : generate the files but don\'t compile and link' - print '-N : don\'t write frozen.c (do compile unless -n given)' - print '-o file : binary output file (default a.out)' - print '-q : quiet (no messages at all except errors)' - print '-v : verbose (lots of extra messages)' - -# Process the script file -def process(filename, addmodules): - global noexec - # - if not quiet: print 'Computing needed modules ...' - todo = {} - todo['__main__'] = filename - for name in addmodules: - mod = os.path.basename(name) - if mod[-3:] == '.py': mod = mod[:-3] - todo[mod] = name - try: - dict = closure(todo) - except NoSuchFile, filename: - sys.stderr.write('Can\'t open file %s\n' % filename) - sys.exit(1) - # - mods = dict.keys() - mods.sort() - # - if verbose: - print '%-15s %s' % ('Module', 'Filename') - for mod in mods: - print '%-15s %s' % (`mod`, dict[mod]) - # - if not quiet: print 'Looking for dynamically linked modules ...' - dlmodules = [] - objs = [] - libs = [] - for mod in mods: - if dict[mod][-2:] == '.o': - if verbose: print 'Found', mod, dict[mod] - dlmodules.append(mod) - objs.append(dict[mod]) - libsname = dict[mod][:-2] + '.libs' - try: - f = open(libsname, 'r') - except IOError: - f = None - if f: - libtext = f.read() - f.close() - for lib in string.split(libtext): - if lib in libs: libs.remove(lib) - libs.append(lib) - # - if not nowrite: - if not quiet: print 'Writing frozen.c ...' - writefrozen('frozen.c', dict) - else: - if not quiet: print 'NOT writing frozen.c ...' - # - if not dlmodules: - config = CONFIG - if not quiet: print 'Using existing', config, '...' - else: - config = 'tmpconfig.c' - if nowrite: - if not quiet: print 'NOT writing config.c ...' - else: - if not quiet: - print 'Writing config.c with dl modules ...' - f = open(CONFIG, 'r') - g = open(config, 'w') - m1 = regex.compile('-- ADDMODULE MARKER 1 --') - m2 = regex.compile('-- ADDMODULE MARKER 2 --') - while 1: - line = f.readline() - if not line: break - g.write(line) - if m1.search(line) >= 0: - if verbose: print 'Marker 1 ...' - for mod in dlmodules: - g.write('extern void init' + \ - mod + '();\n') - if m2.search(line) >= 0: - if verbose: print 'Marker 2 ...' - for mod in dlmodules: - g.write('{"' + mod + \ - '", init' + mod + '},\n') - g.close() - # - if not quiet: - if noexec: print 'Generating compilation commands ...' - else: print 'Starting compilation ...' - defs = ['-DUSE_FROZEN', '-DPYTHONPATH=\'"."\''] - for mod in dict.keys(): - if dict[mod] == '' and mod <> 'sys': - defs.append('-DUSE_' + string.upper(mod)) - # - incs = ['-I.', '-I' + SRC] - if dict.has_key('stdwin'): - incs.append('-I' + j(STDWIN, 'H')) - # - srcs = [config, FMAIN] - # - libs.append(LIBP) - for item in libdeps: - m = item[0] - if m == '*' or dict.has_key(m): - for l in item[1:]: - if l in libs: libs.remove(l) - libs.append(l) - # - sts = 0 - # - cmd = CC + ' -c' - cmd = cmd + ' ' + string.join(defs) - cmd = cmd + ' ' + string.join(incs) - cmd = cmd + ' ' + string.join(srcs) - print cmd - # - if not noexec: - sts = os.system(cmd) - if sts: - print 'Exit status', sts, '-- turning on -n' - noexec = 1 - # - for s in srcs: - s = os.path.basename(s) - if s[-2:] == '.c': s = s[:-2] - o = s + '.o' - objs.insert(0, o) - # - cmd = CC - cmd = cmd + ' ' + string.join(objs) - cmd = cmd + ' ' + string.join(libs) - cmd = cmd + ' -o ' + ofile - print cmd - # - if not noexec: - sts = os.system(cmd) - if sts: - print 'Exit status', sts - else: - print 'Done.' - # - if not quiet: print 'Note: consider this:'; print 'strip', ofile - # - sys.exit(sts) - - -# Generate code for a given module -def makecode(filename): - if filename[-2:] == '.o': - return None - try: - f = open(filename, 'r') - except IOError: - return None - if verbose: print 'Making code from', filename, '...' - text = f.read() - code = compile(text, filename, 'exec') - f.close() - return marshal.dumps(code) - - -# Write the C source file containing the frozen Python code -def writefrozen(filename, dict): - f = open(filename, 'w') - codelist = [] - for mod in dict.keys(): - codestring = makecode(dict[mod]) - if codestring is not None: - codelist.append((mod, codestring)) - write = sys.stdout.write - save_stdout = sys.stdout - try: - sys.stdout = f - for mod, codestring in codelist: - if verbose: - write('Writing initializer for %s\n'%mod) - print 'static char M_' + mod + '[' + \ - str(len(codestring)) + '+1] = {' - for i in range(0, len(codestring), 16): - for c in codestring[i:i+16]: - print str(ord(c)) + ',', - print - print '};' - print 'struct frozen {' - print ' char *name;' - print ' char *code;' - print ' int size;' - print '} frozen_modules[] = {' - for mod, codestring in codelist: - print ' {"' + mod + '",', - print 'M_' + mod + ',', - print str(len(codestring)) + '},' - print ' {0, 0, 0} /* sentinel */' - print '};' - finally: - sys.stdout = save_stdout - f.close() - - -# Determine the names and filenames of the modules imported by the -# script, recursively. This is done by scanning for lines containing -# import statements. (The scanning has only superficial knowledge of -# Python syntax and no knowledge of semantics, so in theory the result -# may be incorrect -- however this is quite unlikely if you don't -# intentionally obscure your Python code.) - -# Compute the closure of scanfile() -- special first file because of script -def closure(todo): - done = {} - while todo: - newtodo = {} - for modname in todo.keys(): - if not done.has_key(modname): - filename = todo[modname] - if filename is None: - filename = findmodule(modname) - done[modname] = filename - if filename in ('', ''): - continue - modules = scanfile(filename) - for m in modules: - if not done.has_key(m): - newtodo[m] = None - todo = newtodo - return done - -# Scan a file looking for import statements -importstr = '\(^\|:\)[ \t]*import[ \t]+\([a-zA-Z0-9_, \t]+\)' -fromstr = '\(^\|:\)[ \t]*from[ \t]+\([a-zA-Z0-9_]+\)[ \t]+import[ \t]+' -isimport = regex.compile(importstr) -isfrom = regex.compile(fromstr) -def scanfile(filename): - allmodules = {} - try: - f = open(filename, 'r') - except IOError, msg: - raise NoSuchFile, filename - while 1: - line = f.readline() - if not line: break # EOF - while line[-2:] == '\\\n': # Continuation line - line = line[:-2] + ' ' - line = line + f.readline() - if isimport.search(line) >= 0: - rawmodules = isimport.group(2) - modules = string.splitfields(rawmodules, ',') - for i in range(len(modules)): - modules[i] = string.strip(modules[i]) - elif isfrom.search(line) >= 0: - modules = [isfrom.group(2)] - else: - continue - for mod in modules: - allmodules[mod] = None - f.close() - return allmodules.keys() - -# Find the file containing a module, given its name; None if not found -builtins = sys.builtin_module_names + ['sys'] -def findmodule(modname): - if modname in builtins: return '' - for dirname in sys.path: - dlfullname = os.path.join(dirname, modname + 'module.o') - try: - f = open(dlfullname, 'r') - except IOError: - f = None - if f: - f.close() - return dlfullname - fullname = os.path.join(dirname, modname + '.py') - try: - f = open(fullname, 'r') - except IOError: - continue - f.close() - return fullname - if not quiet: - sys.stderr.write('Warning: module %s not found\n' % modname) - return '' - - -# Call the main program -main() diff --git a/Demo/scripts/from.py b/Demo/scripts/from.py deleted file mode 100755 index 4c01b4c3a8..0000000000 --- a/Demo/scripts/from.py +++ /dev/null @@ -1,35 +0,0 @@ -#! /usr/local/bin/python - -# Print From and Subject of messages in $MAIL. -# Extension to multiple mailboxes and other bells & whistles are left -# as exercises for the reader. - -import sys, os - -# Open mailbox file. Exits with exception when this fails. - -try: - mailbox = os.environ['MAIL'] -except (AttributeError, KeyError): - sys.stderr.write('No environment variable $MAIL\n') - sys.exit(2) - -try: - mail = open(mailbox, 'r') -except IOError: - sys.stderr.write('Cannot open mailbox file: ' + mailbox + '\n') - sys.exit(2) - -while 1: - line = mail.readline() - if not line: break # EOF - if line[:5] == 'From ': - # Start of message found - print line[:-1], - while 1: - line = mail.readline() - if not line: break # EOF - if line == '\n': break # Blank line ends headers - if line[:8] == 'Subject:': - print `line[9:-1]`, - print diff --git a/Demo/scripts/lpwatch.py b/Demo/scripts/lpwatch.py deleted file mode 100755 index 7fa85db09d..0000000000 --- a/Demo/scripts/lpwatch.py +++ /dev/null @@ -1,110 +0,0 @@ -#! /ufs/guido/bin/sgi/python -#! /usr/local/bin/python - -# Watch line printer queue(s). -# Intended for BSD 4.3 lpq. - -import posix -import sys -import time -import string - -DEF_PRINTER = 'psc' -DEF_DELAY = 10 - -def main(): - delay = DEF_DELAY # XXX Use getopt() later - try: - thisuser = posix.environ['LOGNAME'] - except: - thisuser = posix.environ['USER'] - printers = sys.argv[1:] - if printers: - # Strip '-P' from printer names just in case - # the user specified it... - for i in range(len(printers)): - if printers[i][:2] == '-P': - printers[i] = printers[i][2:] - else: - if posix.environ.has_key('PRINTER'): - printers = [posix.environ['PRINTER']] - else: - printers = [DEF_PRINTER] - # - clearhome = posix.popen('clear', 'r').read() - # - while 1: - text = clearhome - for name in printers: - text = text + makestatus(name, thisuser) + '\n' - print text - time.sleep(delay) - -def makestatus(name, thisuser): - pipe = posix.popen('lpq -P' + name + ' 2>&1', 'r') - lines = [] - users = {} - aheadbytes = 0 - aheadjobs = 0 - userseen = 0 - totalbytes = 0 - totaljobs = 0 - while 1: - line = pipe.readline() - if not line: break - fields = string.split(line) - n = len(fields) - if len(fields) >= 6 and fields[n-1] == 'bytes': - rank = fields[0] - user = fields[1] - job = fields[2] - files = fields[3:-2] - bytes = eval(fields[n-2]) - if user == thisuser: - userseen = 1 - elif not userseen: - aheadbytes = aheadbytes + bytes - aheadjobs = aheadjobs + 1 - totalbytes = totalbytes + bytes - totaljobs = totaljobs + 1 - if users.has_key(user): - ujobs, ubytes = users[user] - else: - ujobs, ubytes = 0, 0 - ujobs = ujobs + 1 - ubytes = ubytes + bytes - users[user] = ujobs, ubytes - else: - if fields and fields[0] <> 'Rank': - line = string.strip(line) - if line == 'no entries': - line = name + ': idle' - elif line[-22:] == ' is ready and printing': - line = name - lines.append(line) - # - if totaljobs: - line = `(totalbytes+1023)/1024` + ' K' - if totaljobs <> len(users): - line = line + ' (' + `totaljobs` + ' jobs)' - if len(users) == 1: - line = line + ' for ' + users.keys()[0] - else: - line = line + ' for ' + `len(users)` + ' users' - if userseen: - if aheadjobs == 0: - line = line + ' (' + thisuser + ' first)' - else: - line = line + ' (' + `(aheadbytes+1023)/1024` - line = line + ' K before ' + thisuser + ')' - lines.append(line) - # - sts = pipe.close() - if sts: - lines.append('lpq exit status ' + `sts`) - return string.joinfields(lines, ': ') - -try: - main() -except KeyboardInterrupt: - pass diff --git a/Demo/scripts/makedir.py b/Demo/scripts/makedir.py deleted file mode 100755 index 563c83fe4c..0000000000 --- a/Demo/scripts/makedir.py +++ /dev/null @@ -1,20 +0,0 @@ -#! /usr/local/bin/python - -# Like mkdir, but also make intermediate directories if necessary. -# It is not an error if the given directory already exists (as long -# as it is a directory). -# Errors are not treated specially -- you just get a Python exception. - -import sys, os - -def main(): - for p in sys.argv[1:]: - makedirs(p) - -def makedirs(p): - if not os.path.isdir(p): - head, tail = os.path.split(p) - makedirs(head) - os.mkdir(p, 0777) - -main() diff --git a/Demo/scripts/markov.py b/Demo/scripts/markov.py deleted file mode 100755 index 6a6d2b2c48..0000000000 --- a/Demo/scripts/markov.py +++ /dev/null @@ -1,116 +0,0 @@ -#! /usr/local/bin/python - -class Markov: - def __init__(self, histsize, choice): - self.histsize = histsize - self.choice = choice - self.trans = {} - def add(self, state, next): - if not self.trans.has_key(state): - self.trans[state] = [next] - else: - self.trans[state].append(next) - def put(self, seq): - n = self.histsize - add = self.add - add(None, seq[:0]) - for i in range(len(seq)): - add(seq[max(0, i-n):i], seq[i:i+1]) - add(seq[len(seq)-n:], None) - def get(self): - choice = self.choice - trans = self.trans - n = self.histsize - seq = choice(trans[None]) - while 1: - subseq = seq[max(0, len(seq)-n):] - options = trans[subseq] - next = choice(options) - if not next: break - seq = seq + next - return seq - -def test(): - import sys, string, whrandom, getopt - args = sys.argv[1:] - try: - opts, args = getopt.getopt(args, '0123456789cdw') - except getopt.error: - print 'Usage: markov [-#] [-cddqw] [file] ...' - print 'Options:' - print '-#: 1-digit history size (default 2)' - print '-c: characters (default)' - print '-w: words' - print '-d: more debugging output' - print '-q: no debugging output' - print 'Input files (default stdin) are split in paragraphs' - print 'separated blank lines and each paragraph is split' - print 'in words by whitespace, then reconcatenated with' - print 'exactly one space separating words.' - print 'Output consists of paragraphs separated by blank' - print 'lines, where lines are no longer than 72 characters.' - histsize = 2 - do_words = 0 - debug = 1 - for o, a in opts: - if '-0' <= o <= '-9': histsize = eval(o[1:]) - if o == '-c': do_words = 0 - if o == '-d': debug = debug + 1 - if o == '-q': debug = 0 - if o == '-w': do_words = 1 - if not args: args = ['-'] - m = Markov(histsize, whrandom.choice) - try: - for filename in args: - if filename == '-': - f = sys.stdin - if f.isatty(): - print 'Sorry, need stdin from file' - continue - else: - f = open(filename, 'r') - if debug: print 'processing', filename, '...' - text = f.read() - f.close() - paralist = string.splitfields(text, '\n\n') - for para in paralist: - if debug > 1: print 'feeding ...' - words = string.split(para) - if words: - if do_words: data = tuple(words) - else: data = string.joinfields(words, ' ') - m.put(data) - except KeyboardInterrupt: - print 'Interrupted -- continue with data read so far' - if not m.trans: - print 'No valid input files' - return - if debug: print 'done.' - if debug > 1: - for key in m.trans.keys(): - if key is None or len(key) < histsize: - print `key`, m.trans[key] - if histsize == 0: print `''`, m.trans[''] - print - while 1: - data = m.get() - if do_words: words = data - else: words = string.split(data) - n = 0 - limit = 72 - for w in words: - if n + len(w) > limit: - print - n = 0 - print w, - n = n + len(w) + 1 - print - print - -def tuple(list): - if len(list) == 0: return () - if len(list) == 1: return (list[0],) - i = len(list)/2 - return tuple(list[:i]) + tuple(list[i:]) - -test() diff --git a/Demo/scripts/mkrcs.py b/Demo/scripts/mkrcs.py deleted file mode 100755 index 9ba2c31752..0000000000 --- a/Demo/scripts/mkrcs.py +++ /dev/null @@ -1,61 +0,0 @@ -#! /ufs/guido/bin/sgi/python -#! /usr/local/bin/python - -# A rather specialized script to make sure that a symbolic link named -# RCS exists pointing to a real RCS directory in a parallel tree -# referenced as RCStree in an ancestor directory. -# (I use this because I like my RCS files to reside on a physically -# different machine). - -import os - -def main(): - rcstree = 'RCStree' - rcs = 'RCS' - if os.path.islink(rcs): - print `rcs`, 'is a symlink to', `os.readlink(rcs)` - return - if os.path.isdir(rcs): - print `rcs`, 'is an ordinary directory' - return - if os.path.exists(rcs): - print `rcs`, 'is a file?!?!' - return - # - p = os.getcwd() - up = '' - down = '' - # Invariants: - # (1) join(p, down) is the current directory - # (2) up is the same directory as p - # Ergo: - # (3) join(up, down) is the current directory - #print 'p =', `p` - while not os.path.isdir(os.path.join(p, rcstree)): - head, tail = os.path.split(p) - #print 'head =', `head`, '; tail =', `tail` - if not tail: - print 'Sorry, no ancestor dir contains', `rcstree` - return - p = head - up = os.path.join(os.pardir, up) - down = os.path.join(tail, down) - #print 'p =', `p`, '; up =', `up`, '; down =', `down` - there = os.path.join(up, rcstree) - there = os.path.join(there, down) - there = os.path.join(there, rcs) - if os.path.isdir(there): - print `there`, 'already exists' - else: - print 'making', `there` - makedirs(there) - print 'making symlink', `rcs`, '->', `there` - os.symlink(there, rcs) - -def makedirs(p): - if not os.path.isdir(p): - head, tail = os.path.split(p) - makedirs(head) - os.mkdir(p, 0777) - -main() diff --git a/Demo/scripts/pi.py b/Demo/scripts/pi.py deleted file mode 100755 index 200cb4ae8d..0000000000 --- a/Demo/scripts/pi.py +++ /dev/null @@ -1,33 +0,0 @@ -#! /usr/local/bin/python - -# Print digits of pi forever. -# -# The algorithm, using Python's 'long' integers ("bignums"), works -# with continued fractions, and was conceived by Lambert Meertens. -# -# See also the ABC Programmer's Handbook, by Geurts, Meertens & Pemberton, -# published by Prentice-Hall (UK) Ltd., 1990. - -import sys - -def main(): - k, a, b, a1, b1 = 2L, 4L, 1L, 12L, 4L - while 1: - # Next approximation - p, q, k = k*k, 2L*k+1L, k+1L - a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1 - # Print common digits - d, d1 = a/b, a1/b1 - while d == d1: - output(d) - a, a1 = 10L*(a%b), 10L*(a1%b1) - d, d1 = a/b, a1/b1 - -def output(d): - # Use write() to avoid spaces between the digits - # Use int(d) to avoid a trailing L after each digit - sys.stdout.write(`int(d)`) - # Flush so the output is seen immediately - sys.stdout.flush() - -main() diff --git a/Demo/scripts/pp.py b/Demo/scripts/pp.py deleted file mode 100755 index eaf7e41537..0000000000 --- a/Demo/scripts/pp.py +++ /dev/null @@ -1,138 +0,0 @@ -#! /usr/local/bin/python - -# Emulate some Perl command line options. -# Usage: pp [-a] [-c] [-d] [-e scriptline] [-F fieldsep] [-n] [-p] [file] ... -# Where the options mean the following: -# -a : together with -n or -p, splits each line into list F -# -c : check syntax only, do not execute any code -# -d : run the script under the debugger, pdb -# -e scriptline : gives one line of the Python script; may be repeated -# -F fieldsep : sets the field separator for the -a option [not in Perl] -# -n : runs the script for each line of input -# -p : prints the line after the script has run -# When no script lines have been passed, the first file argument -# contains the script. With -n or -p, the remaining arguments are -# read as input to the script, line by line. If a file is '-' -# or missing, standard input is read. - -# XXX To do: -# - add -i extension option (change files in place) -# - make a single loop over the files and lines (changes effect of 'break')? -# - add an option to specify the record separator -# - except for -n/-p, run directly from the file if at all possible - -import sys -import string -import getopt - -FS = '' -SCRIPT = [] -AFLAG = 0 -CFLAG = 0 -DFLAG = 0 -NFLAG = 0 -PFLAG = 0 - -try: - optlist, ARGS = getopt.getopt(sys.argv[1:], 'acde:F:np') -except getopt.error, msg: - sys.stderr.write(sys.argv[0] + ': ' + msg + '\n') - sys.exit(2) - -for option, optarg in optlist: - if option == '-a': - AFLAG = 1 - elif option == '-c': - CFLAG = 1 - elif option == '-d': - DFLAG = 1 - elif option == '-e': - for line in string.splitfields(optarg, '\n'): - SCRIPT.append(line) - elif option == '-F': - FS = optarg - elif option == '-n': - NFLAG = 1 - PFLAG = 0 - elif option == '-p': - NFLAG = 1 - PFLAG = 1 - else: - print option, 'not recognized???' - -if not ARGS: ARGS.append('-') - -if not SCRIPT: - if ARGS[0] == '-': - fp = sys.stdin - else: - fp = open(ARGS[0], 'r') - while 1: - line = fp.readline() - if not line: break - SCRIPT.append(line[:-1]) - del fp - del ARGS[0] - if not ARGS: ARGS.append('-') - -if CFLAG: - prologue = ['if 0:'] - epilogue = [] -elif NFLAG: - # Note that it is on purpose that AFLAG and PFLAG are - # tested dynamically each time through the loop - prologue = [ \ - 'LINECOUNT = 0', \ - 'for FILE in ARGS:', \ - ' \tif FILE == \'-\':', \ - ' \t \tFP = sys.stdin', \ - ' \telse:', \ - ' \t \tFP = open(FILE, \'r\')', \ - ' \tLINENO = 0', \ - ' \twhile 1:', \ - ' \t \tLINE = FP.readline()', \ - ' \t \tif not LINE: break', \ - ' \t \tLINENO = LINENO + 1', \ - ' \t \tLINECOUNT = LINECOUNT + 1', \ - ' \t \tL = LINE[:-1]', \ - ' \t \taflag = AFLAG', \ - ' \t \tif aflag:', \ - ' \t \t \tif FS: F = string.splitfields(L, FS)', \ - ' \t \t \telse: F = string.split(L)' \ - ] - epilogue = [ \ - ' \t \tif not PFLAG: continue', \ - ' \t \tif aflag:', \ - ' \t \t \tif FS: print string.joinfields(F, FS)', \ - ' \t \t \telse: print string.join(F)', \ - ' \t \telse: print L', \ - ] -else: - prologue = ['if 1:'] - epilogue = [] - -# Note that we indent using tabs only, so that any indentation style -# used in 'command' will come out right after re-indentation. - -program = string.joinfields(prologue, '\n') + '\n' -for line in SCRIPT: - program = program + (' \t \t' + line + '\n') -program = program + (string.joinfields(epilogue, '\n') + '\n') - -import tempfile -tfn = tempfile.mktemp() -try: - fp = open(tfn, 'w') - fp.write(program) - fp.close() - if DFLAG: - import pdb - pdb.run('execfile(' + `tfn` + ')') - else: - execfile(tfn) -finally: - import os - try: - os.unlink(tfn) - except: - pass diff --git a/Demo/scripts/primes.py b/Demo/scripts/primes.py deleted file mode 100755 index 3e6a64623f..0000000000 --- a/Demo/scripts/primes.py +++ /dev/null @@ -1,26 +0,0 @@ -#! /usr/local/bin/python - -# Print prime numbers in a given range - -def main(): - import sys - min, max = 2, 0x7fffffff - if sys.argv[1:]: - min = int(eval(sys.argv[1])) - if sys.argv[2:]: - max = int(eval(sys.argv[2])) - primes(min, max) - -def primes(min, max): - if 2 >= min: print 2 - primes = [2] - i = 3 - while i <= max: - for p in primes: - if i%p == 0 or p*p > i: break - if i%p <> 0: - primes.append(i) - if i >= min: print i - i = i+2 - -main() diff --git a/Demo/scripts/update.py b/Demo/scripts/update.py deleted file mode 100755 index e8f6283676..0000000000 --- a/Demo/scripts/update.py +++ /dev/null @@ -1,91 +0,0 @@ -#! /usr/local/bin/python - -# Update a bunch of files according to a script. -# The input file contains lines of the form ::, -# meaning that the given line of the given file is to be replaced -# by the given text. This is useful for performing global substitutions -# on grep output: - -import os -import sys -import regex - -pat = '^\([^: \t\n]+\):\([1-9][0-9]*\):' -prog = regex.compile(pat) - -class FileObj: - def __init__(self, filename): - self.filename = filename - self.changed = 0 - try: - self.lines = open(filename, 'r').readlines() - except IOError, msg: - print '*** Can\'t open "%s":' % filename, msg - self.lines = None - return - print 'diffing', self.filename - - def finish(self): - if not self.changed: - print 'no changes to', self.filename - return - try: - os.rename(self.filename, self.filename + '~') - fp = open(self.filename, 'w') - except (os.error, IOError), msg: - print '*** Can\'t rewrite "%s":' % self.filename, msg - return - print 'writing', self.filename - for line in self.lines: - fp.write(line) - fp.close() - self.changed = 0 - - def process(self, lineno, rest): - if self.lines is None: - print '(not processed): %s:%s:%s' % ( - self.filename, lineno, rest), - return - i = eval(lineno) - 1 - if not 0 <= i < len(self.lines): - print '*** Line number out of range: %s:%s:%s' % ( - self.filename, lineno, rest), - return - if self.lines[i] == rest: - print '(no change): %s:%s:%s' % ( - self.filename, lineno, rest), - return - if not self.changed: - self.changed = 1 - print '%sc%s' % (lineno, lineno) - print '<', self.lines[i], - print '---' - self.lines[i] = rest - print '>', self.lines[i], - -def main(): - if sys.argv[1:]: - try: - fp = open(sys.argv[1], 'r') - except IOError, msg: - print 'Can\'t open "%s":' % sys.argv[1], msg - sys.exit(1) - else: - fp = sys.stdin - curfile = None - while 1: - line = fp.readline() - if not line: - if curfile: curfile.finish() - break - n = prog.match(line) - if n < 0: - print 'Funny line:', line, - continue - filename, lineno = prog.group(1, 2) - if not curfile or filename <> curfile.filename: - if curfile: curfile.finish() - curfile = FileObj(filename) - curfile.process(lineno, line[n:]) - -main() diff --git a/Demo/scripts/wh.py b/Demo/scripts/wh.py deleted file mode 100755 index b9b09efa6a..0000000000 --- a/Demo/scripts/wh.py +++ /dev/null @@ -1,2 +0,0 @@ -# This is here so I can use 'wh' instead of 'which' in '~/bin/generic_python' -import which diff --git a/Demo/sgi/al/README b/Demo/sgi/al/README deleted file mode 100644 index fba67b7ddf..0000000000 --- a/Demo/sgi/al/README +++ /dev/null @@ -1,15 +0,0 @@ -This directory contains programs using the "al" interface, which gives -access to the most important parts of the SGI Audio Library for the -Indigo and 4D/35. - -alwatch.py Watch changes in device settings -broadcast.py Broadcast audio using UDP packets -cmpaf.py Compare different audio compression schemes (uses fl) -intercom.py 2-way communication with another host (uses fl) -playaiff.py Play an AIFF file (as output by recordaiff) -playback.py Play raw audio data read from stdin -playold.py Play an audio file recorded by the old 4D/25 audio -radio.py Listen to UDP packets sent by broadcast.py -rec_play.py Repeatedly record and play back a sample -record.py Record raw audio data to stdout -unicast.py Like broadcast but sends to one host diff --git a/Demo/sgi/al/alwatch.py b/Demo/sgi/al/alwatch.py deleted file mode 100755 index 4a52ab22fa..0000000000 --- a/Demo/sgi/al/alwatch.py +++ /dev/null @@ -1,33 +0,0 @@ -import time -import al, AL -import string - -dev = AL.DEFAULT_DEVICE - -source_name = ['line', 'microphone', 'digital'] - -params = al.queryparams(dev) -for i in range(1, len(params), 2): - params[i] = -1 -while 1: - time.millisleep(100) - old = params[:] - al.getparams(dev, params) - if params <> old: - for i in range(0, len(params), 2): - if params[i+1] <> old[i+1]: - name = al.getname(dev, params[i]) - if params[i] == AL.INPUT_SOURCE: - if 0 <= old[i+1] < len(source_name): - oldval = source_name[old[i+1]] - else: - oldval = '' - newval = source_name[params[i+1]] - else: - oldval = `old[i+1]` - newval = `params[i+1]` - print string.ljust(name, 25), - print '(' + string.rjust(oldval, 10) + ')', - print '-->', - print string.rjust(newval, 10) - print diff --git a/Demo/sgi/al/broadcast.py b/Demo/sgi/al/broadcast.py deleted file mode 100755 index 5ee96560f8..0000000000 --- a/Demo/sgi/al/broadcast.py +++ /dev/null @@ -1,27 +0,0 @@ -#! /ufs/guido/bin/sgi/python - -# broadcast [port] -# -# Broadcast audio input on the network as UDP packets; -# they can be received on any SGI machine with "radio.py". -# This uses the input sampling rate, input source etc. set by apanel. -# It uses the default sample width and #channels (16 bit/sample stereo). -# (This is 192,000 Bytes at a sampling speed of 48 kHz, or ~137 -# packets/second -- use with caution!!!) - -import sys, al -from socket import * - -port = 5555 -if sys.argv[1:]: port = eval(sys.argv[1]) - -s = socket(AF_INET, SOCK_DGRAM) -s.allowbroadcast(1) - -p = al.openport('broadcast', 'r') - -address = '', port -while 1: - # 700 samples equals 1400 bytes, or about the max packet size! - data = p.readsamps(700) - s.sendto(data, address) diff --git a/Demo/sgi/al/cmpaf.py b/Demo/sgi/al/cmpaf.py deleted file mode 100755 index 509f0aad18..0000000000 --- a/Demo/sgi/al/cmpaf.py +++ /dev/null @@ -1,65 +0,0 @@ -# Compare different audio compression schemes. -# -# This copies mono audio data from the input port to the output port, -# and puts up a window with 4 toggle buttons: -# -# uLAW : convert the data to uLAW and back -# ADPCM : convert the data to ADPCM and back -# Difference : make only the difference between the converted and the -# original data audible -# Exit : quit from the program - -import fl -import FL -import flp -import al -import AL -import audioop -import sys - -class Cmpaf(): - def init(self): - parsetree = flp.parse_form('cmpaf_form','form') - flp.create_full_form(self, parsetree) - c = al.newconfig() - c.setchannels(AL.MONO) - c.setqueuesize(1800) - self.iport = al.openport('cmpaf','r', c) - self.oport = al.openport('cmpaf','w', c) - self.do_adpcm = self.do_ulaw = self.do_diff = 0 - self.acstate = None - self.form.show_form(FL.PLACE_SIZE, 1, 'compare audio formats') - return self - - def run(self): - while 1: - olddata = data = self.iport.readsamps(600) - if self.do_ulaw: - data = audioop.lin2ulaw(data, 2) - data = audioop.ulaw2lin(data, 2) - if self.do_adpcm: - data, nacstate = audioop.lin2adpcm(data, 2, \ - self.acstate) - data, dummy = audioop.adpcm2lin(data, 2, \ - self.acstate) - self.acstate = nacstate - if self.do_diff: - olddata = audioop.mul(olddata, 2, -1) - data = audioop.add(olddata, data, 2) - self.oport.writesamps(data) - fl.check_forms() - - def cb_exit(self, *args): - sys.exit(0) - - def cb_adpcm(self, obj, val): - self.do_adpcm = obj.get_button() - - def cb_ulaw(self, obj, val): - self.do_ulaw = obj.get_button() - - def cb_diff(self, obj, val): - self.do_diff = obj.get_button() - -cmpaf = Cmpaf().init() -cmpaf.run() diff --git a/Demo/sgi/al/cmpaf_form.fd b/Demo/sgi/al/cmpaf_form.fd deleted file mode 100755 index 6667405133..0000000000 --- a/Demo/sgi/al/cmpaf_form.fd +++ /dev/null @@ -1,90 +0,0 @@ -Magic: 12321 - -Internal Form Definition File - (do not change) - -Number of forms: 1 - -=============== FORM =============== -Name: form -Width: 230.000000 -Height: 80.000000 -Number of Objects: 5 - --------------------- -class: 1 -type: 1 -box: 0.000000 0.000000 230.000000 80.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: -callback: -argument: - --------------------- -class: 12 -type: 1 -box: 10.000000 40.000000 100.000000 30.000000 -boxtype: 1 -colors: 39 3 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: uLAW -name: ulawbutton -callback: cb_ulaw -argument: 0 - --------------------- -class: 12 -type: 1 -box: 10.000000 10.000000 100.000000 30.000000 -boxtype: 1 -colors: 39 3 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: ADPCM -name: adpcm_button -callback: cb_adpcm -argument: 0 - --------------------- -class: 11 -type: 0 -box: 170.000000 10.000000 50.000000 20.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: EXIT -name: exit_button -callback: cb_exit -argument: 0 - --------------------- -class: 12 -type: 1 -box: 120.000000 40.000000 100.000000 30.000000 -boxtype: 1 -colors: 39 3 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: Difference -name: diffbutton -callback: cb_diff -argument: 0 - -============================== -create_the_forms diff --git a/Demo/sgi/al/intercom.py b/Demo/sgi/al/intercom.py deleted file mode 100755 index fd983d39ad..0000000000 --- a/Demo/sgi/al/intercom.py +++ /dev/null @@ -1,212 +0,0 @@ -# intercom -- use mike and headset to *talk* to a person on another host. -# For SGI 4D/35 or Indigo running IRIX 4.0. -# Uses 16 bit sampling at 16000 samples/sec, or 32000 bytes/sec, -# tranmitted in 32 1000-byte UDP packets. (In each direction!) -# -# usage: -# intercom hostname - start talking to person on other host -# intercom -r hostname - called remotely to do the setup - -from names import * -import sys, time, posix, gl, fl, FL, al, AL, getopt, rand -from socket import * - -# UDP port numbers used (one for each direction!) -PORT1 = 51042 -PORT2 = PORT1+1 - -# Figure out the user name -try: - user = posix.environ['LOGNAME'] -except: - user = posix.environ['USER'] - -# Debug flags (Implemented as a list; non-empty means debugging is on) -debug = [] - -def main(): - remote = 0 - opts, args = getopt.getopt(sys.argv[1:], 'rd') - for opt, arg in opts: - if opt == '-r': remote = 1 - elif opt == '-d': debug.append(opt) - if len(args) <> 1: - msg = 'usage: intercom [-d] [-r] hostname' - msg = msg + ' (-r is for internal use only!)\n' - sys.stderr.write(msg) - sys.exit(2) - if remote: - server(args[0]) - else: - client(args[0]) - -def client(hostname): - print 'client starting' - cmd = 'rsh ' + hostname + ' "cd ' + AUDIODIR - cmd = cmd + '; DISPLAY=:0; export DISPLAY' - cmd = cmd + '; ' + PYTHON + ' intercom.py -r ' - for flag in debug: cmd = cmd + flag + ' ' - cmd = cmd + gethostname() - cmd = cmd + '"' - if debug: print cmd - pipe = posix.popen(cmd, 'r') - ack = 0 - nak = 0 - while 1: - line = pipe.readline() - if not line: break - sys.stdout.write('remote: ' + line) - if line == 'NAK\n': - nak = 1 - break - elif line == 'ACK\n': - ack = 1 - break - if nak: - print 'Remote user doesn\'t want to talk to you.' - return - if not ack: - print 'No acknowledgement (remote side crashed?).' - return - # - print 'Ready...' - # - s = socket(AF_INET, SOCK_DGRAM) - s.bind('', PORT2) - # - otheraddr = gethostbyname(hostname), PORT1 - try: - try: - ioloop(s, otheraddr) - except KeyboardInterrupt: - log('client got intr') - except error: - log('client got error') - finally: - s.sendto('', otheraddr) - log('client finished sending empty packet to server') - # - log('client exit') - print 'Done.' - -def server(hostname): - print 'server starting' - sys.stdout.flush() - # - if not remotedialog(): - print 'NAK' - return - # - print 'ACK' - # - s = socket(AF_INET, SOCK_DGRAM) - s.bind('', PORT1) - # - # Close std{in,out,err} so rsh will exit; reopen them as dummies - # - sys.stdin.close() - sys.stdin = open('/dev/null', 'r') - sys.stdout.close() - sys.stdout = open('/dev/null', 'w') - sys.stderr.close() - if debug: - sys.stderr = open('/tmp/intercom.err', 'a') - else: - sys.stderr = open('/dev/null', 'w') - # - ioloop(s, (gethostbyname(hostname), PORT2)) - log('server exit') - sys.exit(0) - -def remotedialog(): - gl.foreground() - gl.ringbell() - m1 = user + ' wants to talk to you over the audio channel.' - m2 = 'If it\'s OK, put on your headset and click Yes.' - m3 = 'If you\'re too busy, click No.' - return fl.show_question(m1, m2, m3) - -def ioloop(s, otheraddr): - # - dev = AL.DEFAULT_DEVICE - params = al.queryparams(dev) - al.getparams(dev, params) - time.sleep(1) - saveparams = params[:] - for i in range(0, len(params), 2): - if params[i] in (AL.INPUT_RATE, AL.OUTPUT_RATE): - params[i+1] = AL.RATE_16000 - elif params[i] == AL.INPUT_SOURCE: - params[i+1] = AL.INPUT_MIC - try: - al.setparams(dev, params) - ioloop1(s, otheraddr) - finally: - al.setparams(dev, saveparams) - -def ioloop1(s, otheraddr): - # - # Watch out! data is in bytes, but the port counts in samples, - # which are two bytes each (for 16-bit samples). - # Luckily, we use mono, else it would be worse (2 samples/frame...) - # - SAMPSPERBUF = 500 - BYTESPERSAMP = 2 # AL.SAMPLE_16 - BUFSIZE = BYTESPERSAMP*SAMPSPERBUF - QSIZE = 4*SAMPSPERBUF - # - config = al.newconfig() - config.setqueuesize(QSIZE) - config.setwidth(AL.SAMPLE_16) - config.setchannels(AL.MONO) - # - pid = posix.fork() - if pid: - # Parent -- speaker/headphones handler - log('parent started') - spkr = al.openport('spkr', 'w', config) - while 1: - data = s.recv(BUFSIZE) - if len(data) == 0: - # EOF packet - log('parent got empty packet; killing child') - posix.kill(pid, 15) - return - # Discard whole packet if we are too much behind - if spkr.getfillable() > len(data) / BYTESPERSAMP: - if len(debug) >= 2: - log('parent Q full; dropping packet') - spkr.writesamps(data) - else: - # Child -- microphone handler - log('child started') - try: - try: - mike = al.openport('mike', 'r', config) - # Sleep a while to let the other side get started - time.sleep(1) - # Drain the queue before starting to read - data = mike.readsamps(mike.getfilled()) - # Loop, sending packets from the mike to the net - while 1: - data = mike.readsamps(SAMPSPERBUF) - s.sendto(data, otheraddr) - except KeyboardInterrupt: - log('child got interrupt; exiting') - posix._exit(0) - except error: - log('child got error; exiting') - posix._exit(1) - finally: - log('child got unexpected error; leaving w/ traceback') - -def log(msg): - if not debug: return - if type(msg) <> type(''): - msg = `msg` - - f = open('/tmp/intercom.log', 'a') - f.write(`sys.argv` + ' ' + `posix.getpid()` + ': ' + msg + '\n') - f.close() - -main() diff --git a/Demo/sgi/al/listen.py b/Demo/sgi/al/listen.py deleted file mode 100755 index 83f850a657..0000000000 --- a/Demo/sgi/al/listen.py +++ /dev/null @@ -1,34 +0,0 @@ -# Listen to the input on host argv[1]. - -import sys, al, AL, posix - -BUFSIZE = 2000 -QSIZE = 4000 - -def main(): - if len(sys.argv) <> 2: - sys.stderr.write('usage: ' + sys.argv[0] + ' hostname\n') - sys.exit(2) - hostname = sys.argv[1] - cmd = 'exec rsh 'FORM': - raise aiff.Error, 'FORM chunk expected at start of file' - aiff.read_form_chunk(f) - while 1: - try: - type, size = aiff.read_chunk_header(f) - except EOFError: - break - if v: print 'header:', `type`, size - if type == 'COMM': - nchannels, nsampframes, sampwidth, samprate = \ - aiff.read_comm_chunk(f) - if v: print nchannels, nsampframes, sampwidth, samprate - elif type == 'SSND': - offset, blocksize = aiff.read_ssnd_chunk(f) - if v: print offset, blocksize - data = f.read(size-8) - if size%2: void = f.read(1) - p = makeport(nchannels, sampwidth, samprate) - play(p, data, offset, blocksize) - elif type in aiff.skiplist: - aiff.skip_chunk(f, size) - else: - raise aiff.Error, 'bad chunk type ' + type - -def makeport(nchannels, sampwidth, samprate): - c = al.newconfig() - c.setchannels(nchannels) - c.setwidth(sampwidth/8) - # can't set the rate... - p = al.openport('', 'w', c) - return p - -def play(p, data, offset, blocksize): - data = data[offset:] - p.writesamps(data) - while p.getfilled() > 0: time.millisleep(10) - -main() diff --git a/Demo/sgi/al/playback.py b/Demo/sgi/al/playback.py deleted file mode 100755 index 967f746cf8..0000000000 --- a/Demo/sgi/al/playback.py +++ /dev/null @@ -1,23 +0,0 @@ -# Read mono 16bit samples from stdin and write them to the audio device. -# Assume the sampling rate is compatible. -# Use a small queue size to minimize delays. - -import al, sys -import AL - -BUFSIZE = 2000 -QSIZE = 4000 - -def main(): - c = al.newconfig() - c.setchannels(AL.MONO) - c.setqueuesize(QSIZE) - p = al.openport('', 'w', c) - while 1: - data = sys.stdin.read(BUFSIZE) - p.writesamps(data) - -try: - main() -except KeyboardInterrupt: - sys.exit(1) diff --git a/Demo/sgi/al/playold.py b/Demo/sgi/al/playold.py deleted file mode 100755 index d0cb59268a..0000000000 --- a/Demo/sgi/al/playold.py +++ /dev/null @@ -1,51 +0,0 @@ -# Play old style sound files (Guido's private format) - -import al, sys, time -import AL - -BUFSIZE = 8000 - -def main(): - if len(sys.argv) < 2: - f = sys.stdin - filename = sys.argv[0] - else: - if len(sys.argv) <> 2: - sys.stderr.write('usage: ' + \ - sys.argv[0] + ' filename\n') - sys.exit(2) - filename = sys.argv[1] - f = open(filename, 'r') - # - magic = f.read(4) - extra = '' - if magic == '0008': - rate = 8000 - elif magic == '0016': - rate = 16000 - elif magic == '0032': - rate = 32000 - else: - sys.stderr.write('no magic header; assuming 8k samples/sec.\n') - rate = 8000 - extra = magic - # - pv = [AL.OUTPUT_RATE, rate] - al.setparams(AL.DEFAULT_DEVICE, pv) - c = al.newconfig() - c.setchannels(AL.MONO) - c.setwidth(AL.SAMPLE_8) - port = al.openport(filename, 'w', c) - if extra: - port.writesamps(extra) - while 1: - buf = f.read(BUFSIZE) - if not buf: break - port.writesamps(buf) - while port.getfilled() > 0: - time.millisleep(100) - -try: - main() -except KeyboardInterrupt: - sys.exit(1) diff --git a/Demo/sgi/al/radio.py b/Demo/sgi/al/radio.py deleted file mode 100755 index 6cde805c38..0000000000 --- a/Demo/sgi/al/radio.py +++ /dev/null @@ -1,21 +0,0 @@ -#! /ufs/guido/bin/sgi/python - -# radio [port] -# -# Receive audio packets broadcast by "broadcast.py" on another SGI machine. -# Use apanel to set the output sampling rate to match that of the broadcast. - -import sys, al -from socket import * - -port = 5555 -if sys.argv[1:]: port = eval(sys.argv[1]) - -s = socket(AF_INET, SOCK_DGRAM) -s.bind('', port) - -p = al.openport('radio', 'w') - -while 1: - data = s.recv(1400) - p.writesamps(data) diff --git a/Demo/sgi/al/rec_play.py b/Demo/sgi/al/rec_play.py deleted file mode 100755 index e538b99111..0000000000 --- a/Demo/sgi/al/rec_play.py +++ /dev/null @@ -1,28 +0,0 @@ -# -# records an AIFF sample and plays it -# infinity number of times. -# - -import time -import al - -def recordit () : - p = al.openport('hello', 'r') - print 'recording...' - buf = p.readsamps(500000) - print 'done.' - p.closeport() - - return buf - -def playit (buf) : - p = al.openport('hello', 'w') - print 'playing...' - p.writesamps(buf) - while p.getfilled() > 0: - time.millisleep(10) - print 'done.' - p.closeport() - -while 1 : - playit (recordit ()) diff --git a/Demo/sgi/al/record.py b/Demo/sgi/al/record.py deleted file mode 100755 index e5c0f5b2d8..0000000000 --- a/Demo/sgi/al/record.py +++ /dev/null @@ -1,23 +0,0 @@ -# Record mono 16bits samples from the audio device and send them to stdout. -# Assume the sampling rate is compatible. -# Use a small queue size to minimize delays. - -import al, sys -import AL - -BUFSIZE = 2000 -QSIZE = 4000 - -def main(): - c = al.newconfig() - c.setchannels(AL.MONO) - c.setqueuesize(QSIZE) - p = al.openport('', 'r', c) - while 1: - data = p.readsamps(BUFSIZE) - sys.stdout.write(data) - -try: - main() -except KeyboardInterrupt: - sys.exit(1) diff --git a/Demo/sgi/al/unicast.py b/Demo/sgi/al/unicast.py deleted file mode 100755 index 8e0c1a8378..0000000000 --- a/Demo/sgi/al/unicast.py +++ /dev/null @@ -1,26 +0,0 @@ -#! /ufs/guido/bin/sgi/python - -# unicast host [port] -# -# Similar to "broadcast.py" but sends to a specific host only; -# use "radio.py" on the designated host to receive. -# This is less stressful on other hosts on the same ethernet segment -# if you need to send to one host only. - -import sys, al -from socket import * - -host = sys.argv[1] - -port = 5555 -if sys.argv[2:]: port = eval(sys.argv[1]) - -s = socket(AF_INET, SOCK_DGRAM) - -p = al.openport('unicast', 'r') - -address = host, port -while 1: - # 700 samples equals 1400 bytes, or about the max packet size! - data = p.readsamps(700) - s.sendto(data, address) diff --git a/Demo/sgi/al/x.py b/Demo/sgi/al/x.py deleted file mode 100755 index ecc12d8198..0000000000 --- a/Demo/sgi/al/x.py +++ /dev/null @@ -1,12 +0,0 @@ -# Demonstrate that rsh exits when the remote end closes std{in,out,err}. -# rsh voorn exec /ufs/guido/bin/sgi/python /ufs/guido/mm/demo/audio/x.py - -print 'hoi!' -import sys -sys.stdin.close() -sys.stdout.close() -sys.stderr.close() -import time -time.sleep(5) -sys.stdout = open('@', 'w') -sys.stdout.write('Hello\n') diff --git a/Demo/sgi/audio/README b/Demo/sgi/audio/README deleted file mode 100644 index 02a3701f92..0000000000 --- a/Demo/sgi/audio/README +++ /dev/null @@ -1,8 +0,0 @@ -Programs that demonstrate the use of the audio device on the SGI 4D/25. -These require the built-in module 'audio'. - -XXX This hardware is already obsolete; see ../al for examples of audio -XXX on the Indigo and 4D/35. - -play Read a sound sample from a file and play it through the - speaker. Options to set volume, sampling rate etc. diff --git a/Demo/sgi/audio/play.py b/Demo/sgi/audio/play.py deleted file mode 100755 index adc76252d8..0000000000 --- a/Demo/sgi/audio/play.py +++ /dev/null @@ -1,75 +0,0 @@ -#! /usr/local/python - -import sys -import audio - -import string -import getopt -import auds - -debug = [] - -DEF_RATE = 3 - -def main(): - # - gain = 100 - rate = 0 - starter = audio.write - stopper = 0 - # - optlist, args = getopt.getopt(sys.argv[1:], 'adg:r:') - # - for optname, optarg in optlist: - if 0: - pass - elif optname == '-d': - debug.append(1) - elif optname == '-g': - gain = string.atoi(optarg) - if not (0 < gain < 256): - raise optarg.error, '-g gain out of range' - elif optname == '-r': - rate = string.atoi(optarg) - if not (1 <= rate <= 3): - raise optarg.error, '-r rate out of range' - elif optname == '-a': - starter = audio.start_playing - stopper = audio.wait_playing - # - audio.setoutgain(gain) - audio.setrate(rate) - # - if not args: - play(starter, rate, auds.loadfp(sys.stdin)) - else: - real_stopper = 0 - for file in args: - if real_stopper: - real_stopper() - play(starter, rate, auds.load(file)) - real_stopper = stopper - -def play(starter, rate, data): - magic = data[:4] - if magic == '0008': - mrate = 3 - elif magic == '0016': - mrate = 2 - elif magic == '0032': - mrate = 1 - else: - mrate = 0 - if mrate: - data = data[4:] - else: - mrate = DEF_RATE - if not rate: rate = mrate - audio.setrate(rate) - starter(data) - -try: - main() -finally: - audio.setoutgain(0) - audio.done() diff --git a/Demo/sgi/audio_stdwin/README b/Demo/sgi/audio_stdwin/README deleted file mode 100644 index 6d96fe1e40..0000000000 --- a/Demo/sgi/audio_stdwin/README +++ /dev/null @@ -1,19 +0,0 @@ -Three programs that provide a user interface based upon STDWIN to the -audio device of the SGI 4D/25. These scripts also demonstrate the power -of a set of window interface classes implemented in Python that simplify -the construction of all sorts of buttons, etc. - -XXX This hardware is already obsolete; see ../al for examples of audio -XXX on the Indigo and 4D/35. - -jukebox Browses a directory full of sound samples and lets you - play selected ones. (Probably not fully functional, it - requires a conversion program.) - -rec A tape recorder that lets you record a sound sample, - play it back, and save it to a file. Various options to - set sampling rate, volume etc. When idle it doubles - as a VU meter. - -vumeter A VU meter that displays a history of the volume of - sound recently sampled from the microphone. diff --git a/Demo/sgi/audio_stdwin/jukebox.py b/Demo/sgi/audio_stdwin/jukebox.py deleted file mode 100755 index b2239929a9..0000000000 --- a/Demo/sgi/audio_stdwin/jukebox.py +++ /dev/null @@ -1,321 +0,0 @@ -#! /usr/local/python - -# JUKEBOX: browse directories full of sampled sound files. -# -# One or more "list windows" display the files and subdirectories of -# the arguments. Double-clicking on a subdirectory opens a new window -# displaying its contents (and so on recursively). Double clicking -# on a file plays it as a sound file (assuming it is one). -# -# Playing is asynchronous: the application keeps listening to events -# while the sample is playing, so you can change the volume (gain) -# during playing, cancel playing or start a new sample right away. -# -# The control window displays the current output gain and a primitive -# "stop button" to cancel the current play request. -# -# Sound files must currently be in Dik Winter's compressed Mac format. -# Since decompression is costly, decompressed samples are saved in -# /usr/tmp/@j* until the application is left. The files are read -# afresh each time, though. - -import audio -import sunaudio -import commands -import getopt -import path -import posix -import rand -import stdwin -from stdwinevents import * -import string -import sys - -from WindowParent import WindowParent -from HVSplit import VSplit -from Buttons import PushButton -from Sliders import ComplexSlider - -# Pathnames - -HOME_BIN_SGI = '/ufs/guido/bin/sgi/' # Directory where macsound2sgi lives -DEF_DB = '/ufs/dik/sounds/Mac/HCOM' # Default directory of sounds - - -# Global variables - -class struct: pass # Class to define featureless structures - -G = struct() # Holds writable global variables - - -# Main program - -def main(): - G.synchronous = 0 # If set, use synchronous audio.write() - G.debug = 0 # If set, print debug messages - G.gain = 75 # Output gain - G.rate = 3 # Sampling rate - G.busy = 0 # Set while asynchronous playing is active - G.windows = [] # List of open windows (except control) - G.mode = 'mac' # Macintosh mode - G.tempprefix = '/usr/tmp/@j' + `rand.rand()` + '-' - # - optlist, args = getopt.getopt(sys.argv[1:], 'dg:r:sSa') - for optname, optarg in optlist: - if optname == '-d': - G.debug = 1 - elif optname == '-g': - G.gain = string.atoi(optarg) - if not (0 < G.gain < 256): - raise optarg.error, '-g gain out of range' - elif optname == '-r': - G.rate = string.atoi(optarg) - if not (1 <= G.rate <= 3): - raise optarg.error, '-r rate out of range' - elif optname == '-s': - G.synchronous = 1 - elif optname == '-S': - G.mode = 'sgi' - elif optname == '-a': - G.mode = 'sun' - # - if not args: - args = [DEF_DB] - # - G.cw = opencontrolwindow() - for dirname in args: - G.windows.append(openlistwindow(dirname)) - # - # - savegain = audio.getoutgain() - try: - # Initialize stdaudio - audio.setoutgain(0) - audio.start_playing('') - dummy = audio.wait_playing() - audio.setoutgain(0) - maineventloop() - finally: - audio.setoutgain(savegain) - audio.done() - clearcache() - -def maineventloop(): - mouse_events = WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP - while G.windows: - type, w, detail = event = stdwin.getevent() - if w == G.cw.win: - if type == WE_CLOSE: - return - G.cw.dispatch(event) - else: - if type == WE_DRAW: - w.drawproc(w, detail) - elif type in mouse_events: - w.mouse(w, type, detail) - elif type == WE_CLOSE: - w.close(w) - del w, event - else: - if G.debug: print type, w, detail - -# Control window -- to set gain and cancel play operations in progress - -def opencontrolwindow(): - cw = WindowParent().create('Jukebox', (0, 0)) - v = VSplit().create(cw) - # - gain = ComplexSlider().define(v) - gain.setminvalmax(0, G.gain, 255) - gain.settexts(' ', ' ') - gain.sethook(gain_setval_hook) - # - stop = PushButton().definetext(v, 'Stop') - stop.hook = stop_hook - # - cw.realize() - return cw - -def gain_setval_hook(self): - G.gain = self.val - if G.busy: audio.setoutgain(G.gain) - -def stop_hook(self): - if G.busy: - audio.setoutgain(0) - dummy = audio.stop_playing() - G.busy = 0 - - -# List windows -- to display list of files and subdirectories - -def openlistwindow(dirname): - list = posix.listdir(dirname) - list.sort() - i = 0 - while i < len(list): - if list[i] == '.' or list[i] == '..': - del list[i] - else: - i = i+1 - for i in range(len(list)): - name = list[i] - if path.isdir(path.join(dirname, name)): - list[i] = list[i] + '/' - width = maxwidth(list) - width = width + stdwin.textwidth(' ') # XXX X11 stdwin bug workaround - height = len(list) * stdwin.lineheight() - stdwin.setdefwinsize(width, min(height, 500)) - w = stdwin.open(dirname) - stdwin.setdefwinsize(0, 0) - w.setdocsize(width, height) - w.drawproc = drawlistwindow - w.mouse = mouselistwindow - w.close = closelistwindow - w.dirname = dirname - w.list = list - w.selected = -1 - return w - -def maxwidth(list): - width = 1 - for name in list: - w = stdwin.textwidth(name) - if w > width: width = w - return width - -def drawlistwindow(w, area): - d = w.begindrawing() - d.erase((0, 0), (1000, 10000)) - lh = d.lineheight() - h, v = 0, 0 - for name in w.list: - d.text((h, v), name) - v = v + lh - showselection(w, d) - -def hideselection(w, d): - if w.selected >= 0: - invertselection(w, d) - -def showselection(w, d): - if w.selected >= 0: - invertselection(w, d) - -def invertselection(w, d): - lh = d.lineheight() - h1, v1 = p1 = 0, w.selected*lh - h2, v2 = p2 = 1000, v1 + lh - d.invert(p1, p2) - -def mouselistwindow(w, type, detail): - (h, v), clicks, button = detail[:3] - d = w.begindrawing() - lh = d.lineheight() - if 0 <= v < lh*len(w.list): - i = v / lh - else: - i = -1 - if w.selected <> i: - hideselection(w, d) - w.selected = i - showselection(w, d) - if type == WE_MOUSE_DOWN and clicks >= 2 and i >= 0: - name = path.join(w.dirname, w.list[i]) - if name[-1:] == '/': - if clicks == 2: - G.windows.append(openlistwindow(name[:-1])) - else: - playfile(name) - -def closelistwindow(w): - remove(G.windows, w) - -def remove(list, item): - for i in range(len(list)): - if list[i] == item: - del list[i] - break - - -# Playing tools - -cache = {} - -def clearcache(): - for x in cache.keys(): - try: - sts = posix.system('rm -f ' + cache[x]) - if sts: - print cmd - print 'Exit status', sts - except: - print cmd - print 'Exception?!' - del cache[x] - -def playfile(name): - if G.mode <> 'mac': - tempname = name - elif cache.has_key(name): - tempname = cache[name] - else: - tempname = G.tempprefix + `rand.rand()` - cmd = HOME_BIN_SGI + 'macsound2sgi' - cmd = cmd + ' ' + commands.mkarg(name) - cmd = cmd + ' >' + tempname - if G.debug: print cmd - sts = posix.system(cmd) - if sts: - print cmd - print 'Exit status', sts - stdwin.fleep() - return - cache[name] = tempname - fp = open(tempname, 'r') - try: - hdr = sunaudio.gethdr(fp) - except sunaudio.error, msg: - hdr = () - if hdr: - data_size = hdr[0] - data = fp.read(data_size) - # XXX this doesn't work yet, need to convert from uLAW!!! - del fp - else: - del fp - data = readfile(tempname) - if G.debug: print len(data), 'bytes read from', tempname - if G.busy: - G.busy = 0 - dummy = audio.stop_playing() - # - # Completely reset the audio device - audio.setrate(G.rate) - audio.setduration(0) - audio.setoutgain(G.gain) - # - if G.synchronous: - audio.write(data) - audio.setoutgain(0) - else: - try: - audio.start_playing(data) - G.busy = 1 - except: - stdwin.fleep() - del data - -def readfile(filename): - return readfp(open(filename, 'r')) - -def readfp(fp): - data = '' - while 1: - buf = fp.read(102400) # Reads most samples in one fell swoop - if not buf: - return data - data = data + buf - -main() diff --git a/Demo/sgi/audio_stdwin/rec.py b/Demo/sgi/audio_stdwin/rec.py deleted file mode 100755 index 0caba89826..0000000000 --- a/Demo/sgi/audio_stdwin/rec.py +++ /dev/null @@ -1,268 +0,0 @@ -#! /ufs/guido/bin/sgi/python - -import sys -import audio -import stdwin - -import string -import getopt - -from stdwinevents import * -from Buttons import * -from Sliders import * -#from Soundogram import Soundogram -from VUMeter import VUMeter -from WindowParent import WindowParent, MainLoop -from HVSplit import HSplit, VSplit - -class TimeOutToggleButton(ToggleButton): - def define(self, parent): - self = ToggleButton.define(self, parent) - self.parent.need_timer(self) - self.timer_hook = 0 - return self - def timer(self): - if self.timer_hook: - self.timer_hook(self) - -K = 1024 -BUFSIZE = 30*8*K -Rates = [0, 32*K, 16*K, 8*K] -Magics = ['', '0032', '0016', '0008'] - -class Struct: pass -G = Struct() - -def main(): - # - # Turn off scroll bars - # - stdwin.setdefscrollbars(0, 0) - # - # Set default state - # - G.gain = 60 - G.rate = 3 - G.nomuting = 0 - G.savefile = '@rec' - # - # Set default values - # - G.data = '' - G.playing = 0 - G.recording = 0 - G.sogram = 0 - # - # Parse options - # - optlist, args = getopt.getopt(sys.argv[1:], 'mdg:r:') - # - for optname, optarg in optlist: - if 0: # (So all cases start with elif) - pass - elif optname == '-d': - G.debug = 1 - elif optname == '-g': - G.gain = string.atoi(optarg) - if not (0 < G.gain < 256): - raise optarg.error, '-g gain out of range' - elif optname == '-m': - G.nomuting = (not G.nomuting) - elif optname == '-r': - G.rate = string.atoi(optarg) - if not (1 <= G.rate <= 3): - raise optarg.error, '-r rate out of range' - # - if args: - G.savefile = args[0] - # - # Initialize the sound package - # - audio.setoutgain(G.nomuting * G.gain) # Silence the speaker - audio.setrate(G.rate) - # - # Create the WindowParent and VSplit - # - G.window = WindowParent().create('Recorder', (0, 0)) - w = G.vsplit = VSplit().create(G.window) - # - # VU-meter - # - G.vubtn = VUMeter().define(w) - # - # Radiobuttons for rates - # - r1btn = RadioButton().definetext(w, '32 K/sec') - r1btn.on_hook = rate_hook - r1btn.rate = 1 - # - r2btn = RadioButton().definetext(w, '16 K/sec') - r2btn.on_hook = rate_hook - r2btn.rate = 2 - # - r3btn = RadioButton().definetext(w, '8 K/sec') - r3btn.on_hook = rate_hook - r3btn.rate = 3 - # - radios = [r1btn, r2btn, r3btn] - r1btn.group = r2btn.group = r3btn.group = radios - for r in radios: - if r.rate == G.rate: r.select(1) - # - # Other controls - # - G.recbtn = TimeOutToggleButton().definetext(w, 'Record') - G.recbtn.on_hook = record_on_hook - G.recbtn.timer_hook = record_timer_hook - G.recbtn.off_hook = record_off_hook - # - G.mutebtn = CheckButton().definetext(w, 'Mute') - G.mutebtn.select(not G.nomuting) - G.mutebtn.hook = mute_hook - # - G.playbtn = TimeOutToggleButton().definetext(w, 'Playback') - G.playbtn.on_hook = play_on_hook - G.playbtn.timer_hook = play_timer_hook - G.playbtn.off_hook = play_off_hook - # - G.gainbtn = ComplexSlider().define(w) - G.gainbtn.settexts(' Volume: ', ' ') - G.gainbtn.setminvalmax(0, G.gain, 255) - G.gainbtn.sethook(gain_hook) - # - G.sizebtn = Label().definetext(w, `len(G.data)` + ' bytes') - # - #G.showbtn = PushButton().definetext(w, 'Sound-o-gram...') - #G.showbtn.hook = show_hook - # - G.savebtn = PushButton().definetext(w, 'Save...') - G.savebtn.hook = save_hook - # - G.quitbtn = PushButton().definetext(w, 'Quit') - G.quitbtn.hook = quit_hook - G.playbtn.enable(0) - G.savebtn.enable(0) - #G.showbtn.enable(0) - start_vu() - G.window.realize() - # - # Event loop - # - MainLoop() - -# XXX Disabled... -def show_hook(self): - savetext = self.text - self.settext('Be patient...') - close_sogram() - stdwin.setdefwinsize(400, 300) - win = stdwin.open('Sound-o-gram') - G.sogram = Soundogram().define(win, G.data) - win.buttons = [G.sogram] - self.settext(savetext) - -def close_sogram(): - if G.sogram: - # Break circular references - G.sogram.win.buttons[:] = [] - del G.sogram.win - G.sogram = 0 - -def mute_hook(self): - G.nomuting = (not self.selected) - audio.setoutgain(G.nomuting * G.gain) - -def rate_hook(self): - G.rate = self.rate - audio.setrate(G.rate) - -def record_on_hook(self): - stop_vu() - close_sogram() - audio.setrate(G.rate) - audio.setoutgain(G.nomuting * G.gain) - audio.start_recording(BUFSIZE) - G.recording = 1 - G.playbtn.enable(0) - G.window.settimer(10 * BUFSIZE / Rates[G.rate]) - -def record_timer_hook(self): - if G.recording: - if audio.poll_recording(): - self.hilite(0) - record_off_hook(self) - else: - self.parent.settimer(5) - -def record_off_hook(self): - if not G.recording: - return - G.data = audio.stop_recording() - G.recording = 0 - G.sizebtn.settext(`len(G.data)` + ' bytes') - audio.setoutgain(G.nomuting * G.gain) - G.playbtn.enable((len(G.data) > 0)) - G.savebtn.enable((len(G.data) > 0)) - #G.showbtn.enable((len(G.data) > 0)) - G.window.settimer(0) - start_vu() - -def play_on_hook(self): - stop_vu() - audio.setrate(G.rate) - audio.setoutgain(G.gain) - audio.start_playing(G.data) - G.playing = 1 - G.recbtn.enable(0) - G.window.settimer(max(10 * len(G.data) / Rates[G.rate], 1)) - -def play_timer_hook(self): - if G.playing: - if audio.poll_playing(): - self.hilite(0) - play_off_hook(self) - else: - self.parent.settimer(5) - -def play_off_hook(self): - if not G.playing: - return - x = audio.stop_playing() - G.playing = 0 - audio.setoutgain(G.nomuting * G.gain) - G.recbtn.enable(1) - G.window.settimer(0) - start_vu() - -def gain_hook(self): - G.gain = self.val - if G.playing or G.nomuting: audio.setoutgain(G.gain) - -def save_hook(self): - if not G.data: - stdwin.fleep() - else: - prompt = 'Store sampled data on file: ' - try: - G.savefile = stdwin.askfile(prompt, G.savefile, 1) - except KeyboardInterrupt: - return - try: - fp = open(G.savefile, 'w') - fp.write(Magics[G.rate] + G.data) - except: - stdwin.message('Cannot create ' + file) - -def stop_vu(): - G.vubtn.stop() - -def start_vu(): - G.vubtn.start() - -def quit_hook(self): - G.window.delayed_destroy() - -try: - main() -finally: - audio.setoutgain(0) diff --git a/Demo/sgi/audio_stdwin/vumeter.py b/Demo/sgi/audio_stdwin/vumeter.py deleted file mode 100755 index bfee66e86d..0000000000 --- a/Demo/sgi/audio_stdwin/vumeter.py +++ /dev/null @@ -1,35 +0,0 @@ -#! /usr/local/python - -import audio -import stdwin - -from VUMeter import VUMeter -from WindowParent import WindowParent -import MainLoop - -NBUFS=20 -BUFSIZE = NBUFS*48 -SCALE=128 - -class MyVUMeter(VUMeter): - def init_reactivity(self): - self.parent.need_mouse(self) - def mouse_down(self, detail): - if self.enabled: - self.stop() - else: - self.start() - def mouse_move(self, detail): pass - def mouse_up(self, detail): pass - -def main(): - audio.setrate(3) - audio.setoutgain(0) - w = WindowParent().create('VU Meter', (200, 100)) - v = MyVUMeter().define(w) - v.start() - w.realize() - while 1: - w.dispatch(stdwin.getevent()) - -main() diff --git a/Demo/sgi/cd/CD.doc b/Demo/sgi/cd/CD.doc deleted file mode 100755 index 67f6a028f0..0000000000 --- a/Demo/sgi/cd/CD.doc +++ /dev/null @@ -1,46 +0,0 @@ -Introduction. - -A number of programs have been written which access the Silicon -Graphics CD-ROM player. These programs all use the interface defined -in readcd.py (see readcd.doc for documentation). - -Specifying music stretches. - -The programs that are capable of reading music CD's all use the same -syntax to describe which part of the CD is to be read. The syntax -closely corresponds to the available methods in readcd.py. - -The music to be read is divided into stretches of music. Each stretch -must be specified as a separate argument on the command line. A -stretch can be a whole CD track, specified as a single number; or it -can be a start time and a end time. The start and end times must be -specified as a tuple, thus: ``(starttime, endtime)''. Don't forget to -quote the parenthesis to the shell. Both starttime and endtime can be -``None'', a simple number which refers to a CD track, or a tuple -consisting of either 3 or 4 elements. A starttime of ``None'' refers -to the start of the CD, an endtime of ``None'' refers to the end of -the CD. A tuple of 3 elements is an absolute time on the CD. The -three elements are (minutes, seconds, frames). A tuple of 4 elements -is a track-relative time. The four elements are (track, minutes, -seconds, frames). - -When one stretch ends at the end of a track and the following stretch -starts at the next track, there is the option of either playing or not -playing the pause between the two tracks. When either the end time of -the first stretch or the start time of the second stretch is specified -using absolute or track-relative times, the pause will not be played. -When both times are specified as simple track numbers, the pause will -be played. - -If no stretches are specified, the whole CD will be played. - -The programs. - -Currently, the following programs exist. -playcd [ stretch specification ] - Play (part of) a CD through the system loadspeaker or - headphone set. -cdaiff [ file [ stretch specification ] ] - Copy (part of) a CD to a file. The file will be written in - AIFF format. If no file is specified, cdaiff will write to - the file ``@'' in the current directory. diff --git a/Demo/sgi/cd/README b/Demo/sgi/cd/README deleted file mode 100644 index 016e4d1bb7..0000000000 --- a/Demo/sgi/cd/README +++ /dev/null @@ -1,28 +0,0 @@ -These are some programs to work with the SCSI CD-ROM player's audio -interface (see cdaudio(3) in IRIX 4.0 or higher; tested only on 4.0.2). - -See also the SGI-specific standard module 'readcd', documented as -"readcd.lib" in the library. - -cdwin.py A trivial window interface to play a CD over the CD - player's audio jack. More functionality is left as an - excersice to the reader. Needs module stdwin. - -listcd.py List the table-of-contents of a CD (data CDs will - appear as a single track). - -playcd.py Read audio data from the CD and play it over the - Indigo's built-in speker or audio jack. Needs module al. - -sendcd.py Read audio data from the CD and send it as UDP packets - over the network (to recvcd.py). - -recvcd.py Receive UDP packets containing CD audio data (from - sendcd.py) and play them over the Indigo's built-in - speaker or audio jack. Needs module al. (Doesn't - actually use module cd.) - -cdaiff.py Dump CD audio to disk in AIFF format. - -Note that to read *data* CD-ROMs you must open /dev/rdsk/dks0d4s7 or -some such special file... diff --git a/Demo/sgi/cd/cdaiff.py b/Demo/sgi/cd/cdaiff.py deleted file mode 100755 index 3f14bceda4..0000000000 --- a/Demo/sgi/cd/cdaiff.py +++ /dev/null @@ -1,33 +0,0 @@ -import sys -import readcd -import aifc -import AL -import CD - -Error = 'cdaiff.Error' - -def writeaudio(a, type, data): - a.writeframesraw(data) - -def main(): - if len(sys.argv) > 1: - a = aifc.open(sys.argv[1], 'w') - else: - a = aifc.open('@', 'w') - a.setsampwidth(AL.SAMPLE_16) - a.setnchannels(AL.STEREO) - a.setframerate(AL.RATE_44100) - r = readcd.Readcd().init() - for arg in sys.argv[2:]: - x = eval(arg) - try: - if len(x) <> 2: - raise Error, 'bad argument' - r.appendstretch(x[0], x[1]) - except TypeError: - r.appendtrack(x) - r.setcallback(CD.AUDIO, writeaudio, a) - r.play() - a.close() - -main() diff --git a/Demo/sgi/cd/cdwin.py b/Demo/sgi/cd/cdwin.py deleted file mode 100755 index 1a562c2a96..0000000000 --- a/Demo/sgi/cd/cdwin.py +++ /dev/null @@ -1,104 +0,0 @@ -# Window interface to (some of) the CD player's vital audio functions - -import cd -import CD -import stdwin -from stdwinevents import * -import mainloop - -def main(): - player = cd.open() - stdwin.setdefscrollbars(0, 0) - win = stdwin.open('CD') - win.player = player - win.dispatch = cddispatch - mainloop.register(win) - win.settimer(10) - mainloop.mainloop() - -def cddispatch(type, win, detail): - if type == WE_NULL: - pass - elif type == WE_CLOSE: - mainloop.unregister(win) - win.close() - elif type == WE_DRAW: - draw(win) - elif type == WE_TIMER: - update(win) - elif type == WE_MOUSE_UP: - left, top, right, bottom, v1, v2 = getgeo(win) - h, v = detail[0] - if left < h < right: - if top < v < v1: - but1(win) - elif v1 < v < v2: - but2(win) - elif v2 < v < bottom: - but3(win) - else: - stdwin.fleep() - -def but1(win): - update(win) - -def but2(win): - state = win.player.getstatus()[0] - if state == CD.READY: - win.player.play(1, 1) - elif state in (CD.PLAYING, CD.PAUSED): - win.player.togglepause() - else: - stdwin.fleep() - update(win) - -def but3(win): - win.player.stop() - update(win) - -def update(win): - d = win.begindrawing() - drawstatus(win, d) - d.enddrawing() - win.settimer(10) - -statedict = ['ERROR', 'NODISK', 'READY', 'PLAYING', 'PAUSED', 'STILL'] - -def draw(win): - left, top, right, bottom, v1, v2 = getgeo(win) - d = win.begindrawing() - drawstatus(win, d) - box(d, left, v1, right, v2, 'Play/Pause') - box(d, left, v2, right, bottom, 'Stop') - d.enddrawing() - -def drawstatus(win, d): - left, top, right, bottom, v1, v2 = getgeo(win) - state, track, curtime, abstime, totaltime, first, last, \ - scsi_audio, cur_block, dummy = win.player.getstatus() - if 0 <= state < len(statedict): - message = statedict[state] - else: - message = `status` - message = message + ' track ' + `track` + ' of ' + `last` - d.erase((left, top), (right, v1)) - box(d, left, top, right, v1, message) - -def box(d, left, top, right, bottom, label): - R = (left+1, top+1), (right-1, bottom-1) - width = d.textwidth(label) - height = d.lineheight() - h = (left + right - width) / 2 - v = (top + bottom - height) / 2 - d.box(R) - d.cliprect(R) - d.text((h, v), label) - d.noclip() - -def getgeo(win): - (left, top), (right, bottom) = (0, 0), win.getwinsize() - v1 = top + (bottom - top) / 3 - v2 = top + (bottom - top) * 2 / 3 - return left, top, right, bottom, v1, v2 - -main() diff --git a/Demo/sgi/cd/listcd.py b/Demo/sgi/cd/listcd.py deleted file mode 100755 index 2cfadb6b5e..0000000000 --- a/Demo/sgi/cd/listcd.py +++ /dev/null @@ -1,24 +0,0 @@ -# List track info from CD player. - -import cd - -def main(): - c = cd.open() - info = [] - while 1: - try: - info.append(c.gettrackinfo(len(info) + 1)) - except RuntimeError: - break - for i in range(len(info)): - start, total = info[i] - print 'Track', zfill(i+1), triple(start), triple(total) - -def triple((a, b, c)): - return zfill(a) + ':' + zfill(b) + ':' + zfill(c) - -def zfill(n): - s = `n` - return '0' * (2 - len(s)) + s - -main() diff --git a/Demo/sgi/cd/playcd.py b/Demo/sgi/cd/playcd.py deleted file mode 100755 index 1735ac17d5..0000000000 --- a/Demo/sgi/cd/playcd.py +++ /dev/null @@ -1,102 +0,0 @@ -# Play CD audio on speaker or headphones. - -callbacktypes = ['audio','pnum','index','ptime','atime','catalog','ident','control'] - -def playaudio(port, type, audio): - port.writesamps(audio) - -def prtrack(cdinfo, type, pnum): - if cdinfo.track[pnum] <> '': - print 'playing "' + cdinfo.track[pnum] + '"' - else: - print callbacktypes[type]+': '+`pnum` - -def callback(arg, type, data): - print callbacktypes[type]+': '+`data` - -def tcallback(arg, type, data): - print callbacktypes[type]+': '+triple(data) - -def triple((a, b, c)): - return zfill(a) + ':' + zfill(b) + ':' + zfill(c) - -def zfill(n): - s = `n` - return '0' * (2 - len(s)) + s - -def prtrackinfo(info): - for i in range(len(info)): - start, total = info[i] - print 'Track', zfill(i+1), triple(start), triple(total) - -statedict = ['ERROR', 'NODISK', 'READY', 'PLAYING', 'PAUSED', 'STILL'] - -def prstatus(status): - state, track, curtime, abstime, totaltime, first, last, \ - scsi_audio, cur_block, dummy = status - print 'Status:', - if 0 <= state < len(statedict): - print statedict[state] - else: - print state - print 'Track: ', track - print 'Time: ', triple(curtime) - print 'Abs: ', triple(abstime) - print 'Total: ', triple(totaltime) - print 'First: ', first - print 'Last: ', last - print 'SCSI: ', scsi_audio - print 'Block: ', cur_block - print 'Future:', dummy - -def main(): - import sys, readcd, al, AL, CD, cdplayer - verbose = 0 - r = readcd.Readcd().init() - prstatus(r.getstatus()) - prtrackinfo(r.gettrackinfo()) - cdinfo = cdplayer.Cdplayer().init(r.gettrackinfo()) - if cdinfo.title <> '': - print 'Title: "' + cdinfo.title + '"' - if cdinfo.artist <> '': - print 'Artist: ' + cdinfo.artist - for arg in sys.argv[1:]: - if arg == '-v': - verbose = 1 - continue - x = eval(arg) - try: - l = len(x) - r.appendstretch(x[0], x[1]) - except TypeError: - r.appendtrack(x) - try: - oldparams = [AL.OUTPUT_RATE, 0] - params = oldparams[:] - al.getparams(AL.DEFAULT_DEVICE, oldparams) - params[1] = AL.RATE_44100 - al.setparams(AL.DEFAULT_DEVICE, params) - config = al.newconfig() - config.setwidth(AL.SAMPLE_16) - config.setchannels(AL.STEREO) - port = al.openport('CD Player', 'w', config) - - for i in range(8): - r.setcallback(i, callback, None) - if verbose: - r.setcallback(CD.PTIME, tcallback, None) - r.setcallback(CD.ATIME, tcallback, None) - else: - r.removecallback(CD.PTIME) - r.removecallback(CD.ATIME) - r.setcallback(CD.PNUM, prtrack, cdinfo) - r.setcallback(CD.AUDIO, playaudio, port) - - data = r.play() - except KeyboardInterrupt: - status = r.getstatus() - print 'Interrupted at '+triple(status[2])+' into track '+ \ - `status[1]`+' (absolute time '+triple(status[3])+')' - al.setparams(AL.DEFAULT_DEVICE, oldparams) - -main() diff --git a/Demo/sgi/cd/recvcd.py b/Demo/sgi/cd/recvcd.py deleted file mode 100755 index db5cc412a2..0000000000 --- a/Demo/sgi/cd/recvcd.py +++ /dev/null @@ -1,36 +0,0 @@ -# Receive UDP packets from sendcd.py and play them on the speaker or -# audio jack. - -import al, AL -from socket import * -from CD import CDDA_DATASIZE - -PORT = 50505 # Must match the port in sendcd.py - -def main(): - s = socket(AF_INET, SOCK_DGRAM) - s.bind('', PORT) - - oldparams = [AL.OUTPUT_RATE, 0] - params = oldparams[:] - al.getparams(AL.DEFAULT_DEVICE, oldparams) - params[1] = AL.RATE_44100 - try: - al.setparams(AL.DEFAULT_DEVICE, params) - config = al.newconfig() - config.setwidth(AL.SAMPLE_16) - config.setchannels(AL.STEREO) - port = al.openport('CD Player', 'w', config) - - while 1: - data = s.recv(CDDA_DATASIZE) - if not data: - print 'EOF' - break - port.writesamps(data) - except KeyboardInterrupt: - pass - - al.setparams(AL.DEFAULT_DEVICE, oldparams) - -main() diff --git a/Demo/sgi/cd/sendcd.py b/Demo/sgi/cd/sendcd.py deleted file mode 100755 index 850f6a55e2..0000000000 --- a/Demo/sgi/cd/sendcd.py +++ /dev/null @@ -1,154 +0,0 @@ -# Read CD audio data from the SCSI CD player and send it as UDP -# packets to "recvcd.py" on another host. -# -# Usage: python sendcd.py [options] host [track | minutes seconds [frames]] -# -# Options: -# "-l" list track info and quit. -# "-s" display status and quit. -# -# Arguments: -# host host to send the audio data to (required unless -l or -s). -# track track number where to start; alternatively, -# min sec [frames] absolute address where to start; -# default is continue at current point according to status. - -import cd -import sys -from socket import * -import getopt - -PORT = 50505 # Must match the port in readcd.py - -def main(): - try: - optlist, args = getopt.getopt(sys.argv[1:], 'ls') - except getopt.error, msg: - sys.stderr.write(msg + '\n') - sys.exit(2) - - player = cd.open() - prstatus(player) - size = player.bestreadsize() - - if optlist: - for opt, arg in optlist: - if opt == '-l': - prtrackinfo(player) - elif opt == '-s': - prstatus(player) - return - - if not args: - sys.stderr.write('usage: ' + sys.argv[0] + ' host [track]\n') - sys.exit(2) - host, args = args[0], args[1:] - - sys.stdout.write('waiting for socket... ') - sys.stdout.flush() - port = socket(AF_INET, SOCK_DGRAM) - port.connect(host, PORT) - print 'socket connected' - - parser = cd.createparser() - parser.setcallback(0, audiocallback, port) - parser.setcallback(1, pnumcallback, player) - parser.setcallback(2, indexcallback, None) - ## 3 = ptime: too many calls - ## 4 = atime: too many calls - parser.setcallback(5, catalogcallback, None) - parser.setcallback(6, identcallback, None) - parser.setcallback(7, controlcallback, None) - - if len(args) >= 2: - if len(args) >= 3: - [min, sec, frame] = args[:3] - else: - [min, sec] = args - frame = '0' - min, sec, frame = eval(min), eval(sec), eval(frame) - print 'Seek to', triple(min, sec, frame) - dummy = player.seek(min, sec, frame) - elif len(args) == 1: - track = eval(args[0]) - print 'Seek to track', track - dummy = player.seektrack(track) - else: - min, sec, frame = player.getstatus()[3] - print 'Try to seek back to', triple(min, sec, frame) - try: - player.seek(min, sec, frame) - except RuntimeError: - print 'Seek failed' - - try: - while 1: - frames = player.readda(size) - if frames == '': - print 'END OF CD' - break - parser.parseframe(frames) - except KeyboardInterrupt: - print '[Interrupted]' - pass - -def prtrackinfo(player): - info = [] - while 1: - try: - info.append(player.gettrackinfo(len(info) + 1)) - except RuntimeError: - break - for i in range(len(info)): - start, total = info[i] - print 'Track', zfill(i+1), triple(start), triple(total) - -def audiocallback(port, type, data): -## sys.stdout.write('#') -## sys.stdout.flush() - port.send(data) - -def pnumcallback(player, type, data): - print 'pnum =', `data` - prstatus(player) - -def indexcallback(arg, type, data): - print 'index =', `data` - -def catalogcallback(arg, type, data): - print 'catalog =', `data` - -def identcallback(arg, type, data): - print 'ident =', `data` - -def controlcallback(arg, type, data): - print 'control =', `data` - -statedict = ['ERROR', 'NODISK', 'READY', 'PLAYING', 'PAUSED', 'STILL'] - -def prstatus(player): - state, track, curtime, abstime, totaltime, first, last, \ - scsi_audio, cur_block, dummy = player.getstatus() - print 'Status:', - if 0 <= state < len(statedict): - print statedict[state] - else: - print state - print 'Track: ', track - print 'Time: ', triple(curtime) - print 'Abs: ', triple(abstime) - print 'Total: ', triple(totaltime) - print 'First: ', first - print 'Last: ', last - print 'SCSI: ', scsi_audio - print 'Block: ', cur_block - print 'Future:', dummy - -def triple((a, b, c)): - return zfill(a) + ':' + zfill(b) + ':' + zfill(c) - -def zfill(n): - s = `n` - return '0' * (2 - len(s)) + s - -main() diff --git a/Demo/sgi/flp/test_cb.fd b/Demo/sgi/flp/test_cb.fd deleted file mode 100755 index e83fd1f46b..0000000000 --- a/Demo/sgi/flp/test_cb.fd +++ /dev/null @@ -1,75 +0,0 @@ -Magic: 12321 - -Internal Form Definition File - (do not change) - -Number of forms: 1 - -=============== FORM =============== -Name: main_form -Width: 170.000000 -Height: 190.000000 -Number of Objects: 4 - --------------------- -class: 1 -type: 1 -box: 0.000000 0.000000 170.000000 190.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: -callback: -argument: - --------------------- -class: 11 -type: 0 -box: 10.000000 140.000000 150.000000 40.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: Button 1 -name: button1 -callback: button1CB -argument: 0 - --------------------- -class: 11 -type: 0 -box: 10.000000 100.000000 150.000000 40.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: Button 2 -name: button2 -callback: button2CB -argument: 0 - --------------------- -class: 11 -type: 6 -box: 10.000000 10.000000 150.000000 40.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: EXIT -name: exitbutton -callback: exitbuttonCB -argument: 0 - -============================== -create_the_forms diff --git a/Demo/sgi/flp/test_cb.py b/Demo/sgi/flp/test_cb.py deleted file mode 100755 index 41635036d3..0000000000 --- a/Demo/sgi/flp/test_cb.py +++ /dev/null @@ -1,61 +0,0 @@ -# -# Example 2 - Using fl in python with callbacks. -# -# The form is named 'main_form' and resides on file 'test_cb.fd'. -# It has three objects named button1, button2 and exitbutton. -# All buttons have callbacks with the same names as their corresponding -# buttons but with CB appended. -# -import fl # The forms library -import FL # Symbolic constants for the above -import flp # The module to parse .fd files -import sys - -# The following struct is created to hold the instance variables -# main_form, button1, button2 and exitbutton. - -class myform: - # - # The constructor parses and creates the form, but doesn't - # display it (yet). - def __init__(self, number): - # - # First we parse the form - parsetree = flp.parse_form('test_cb', 'main_form') - # - # Next we create it - - flp.create_full_form(self, parsetree) - - # And keep our number - self.number = number - - # - # The show function displays the form. It doesn't do any interaction, - # though. - def show(self): - self.main_form.show_form(FL.PLACE_SIZE, 1, '') - - # The callback functions - def button1CB(self, obj, arg): - print 'Button 1 pressed on form', self.number - - def button2CB(self, obj, arg): - print 'Button 2 pressed on form', self.number - - def exitbuttonCB(self, obj, arg): - print 'Ok, bye bye' - sys.exit(0) - -# -# The main program. Instantiate two variables of the forms class -# and interact with them. - -form1 = myform(1) -form2 = myform(2) - -form1.show() -form2.show() - -obj = fl.do_forms() -print 'do_forms() returned. This should not happen. obj=', obj diff --git a/Demo/sgi/flp/test_nocb.fd b/Demo/sgi/flp/test_nocb.fd deleted file mode 100755 index 4d3f7ef925..0000000000 --- a/Demo/sgi/flp/test_nocb.fd +++ /dev/null @@ -1,75 +0,0 @@ -Magic: 12321 - -Internal Form Definition File - (do not change) - -Number of forms: 1 - -=============== FORM =============== -Name: main_form -Width: 170.000000 -Height: 190.000000 -Number of Objects: 4 - --------------------- -class: 1 -type: 1 -box: 0.000000 0.000000 170.000000 190.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: -callback: -argument: - --------------------- -class: 11 -type: 0 -box: 10.000000 140.000000 150.000000 40.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: Button 1 -name: button1 -callback: -argument: - --------------------- -class: 11 -type: 0 -box: 10.000000 100.000000 150.000000 40.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: Button 2 -name: button2 -callback: -argument: - --------------------- -class: 11 -type: 6 -box: 10.000000 10.000000 150.000000 40.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: EXIT -name: exitbutton -callback: -argument: - -============================== -create_the_forms diff --git a/Demo/sgi/flp/test_nocb.py b/Demo/sgi/flp/test_nocb.py deleted file mode 100755 index 6346da3ed9..0000000000 --- a/Demo/sgi/flp/test_nocb.py +++ /dev/null @@ -1,45 +0,0 @@ -# -# Example 1 - Using fl in python without callbacks. -# -# The form is named 'main_form' and resides on file 'test_nocb.fd'. -# It has three objects named button1, button2 and exitbutton. -# -import fl # The forms library -import FL # Symbolic constants for the above -import flp # The module to parse .fd files -import sys - -# The following struct is created to hold the instance variables -# main_form, button1, button2 and exitbutton. - -class struct: pass -container = struct() - -# -# We now first parse the forms file - -parsetree = flp.parse_form('test_nocb', 'main_form') - -# -# Next we create it - -flp.create_full_form(container, parsetree) - -# -# And display it - -container.main_form.show_form(FL.PLACE_MOUSE, 1, '') - -# -# And interact until the exit button is pressed -while 1: - selected_obj = fl.do_forms() - if selected_obj == container.button1: - print 'Button 1 selected' - elif selected_obj == container.button2: - print 'Button 2 selected' - elif selected_obj == container.exitbutton: - print 'Ok, bye bye' - sys.exit(0) - else: - print 'do_forms() returned unknown object ', selected_obj diff --git a/Demo/sgi/gl/README b/Demo/sgi/gl/README deleted file mode 100644 index a89a502138..0000000000 --- a/Demo/sgi/gl/README +++ /dev/null @@ -1,35 +0,0 @@ -These demos run only on SGI machines and require the 'gl' built-in module. -The demonstrate the abilities of SGI's GL library as well as the ease of -GL programming in Python. Most demos require the Z-buffer (aka -24-bitplane) option. Press ESC to get out of any of them. - -backface.py Demonstrates the 'backface' GL function. - -kites.py Show 3 flying kites. Demonstrates the rendering speed - obtainable by Python programs. - -kunst.py Cute demo showing a ball suspended on four cables in - the central room of the CWI building. You can specify - three functions Fx(t), Fy(t), Fz(t) which define the - movement of the ball. Try something like sin(t), - cos(t), sin(2*t). - -mclock.py A colorful clock with more options than you can - remember. Works on 8-bit machines, but allows more - colors on 24-bit machines. See mclock.doc for more - info. - -mixing.py Demonstrates the effect of color mixing: through - frequent color switching it gives the effect of white - light. - -nurbs.py A simple demonstration of the 'nurbs' GL functions. - Press left mouse button to toggle surface trimming. - -zrgb.py Displays a 3-D Gouraud-shaded figure which can be moved - around with the mouse. - -glstdwin/ This is quite different: a partial STDWIN emulation - using GL! Requires only small changes to Python - programs that use STDWIN. Some features not yet - implemented, e.g., scroll bars. diff --git a/Demo/sgi/gl/backface.py b/Demo/sgi/gl/backface.py deleted file mode 100755 index 39929bef0d..0000000000 --- a/Demo/sgi/gl/backface.py +++ /dev/null @@ -1,140 +0,0 @@ -#! /usr/local/bin/python - -# backface -# -# draw a cube that can run with backface() turned on or off. -# cube is moved when LEFTMOUSE is pressed and mouse itself is moved. - -from gl import * -from DEVICE import * -from GL import * - -CUBE_SIZE = 200.0 -CUBE_OBJ = 1 - -def main () : - # - x = 0 - y = 0 - moveit = 0 - # - initialize() - # - while (1) : - # - while (qtest()) : - dev, val = qread() - # - if dev == ESCKEY : - backface(0) - return - # - elif dev == REDRAW : - reshapeviewport() - drawcube(x,y) - # - elif dev == LEFTMOUSE : - # - # LEFTMOUSE down - moveit = val - # - elif dev == BKEY : - backface(1) - drawcube(x,y) - # - elif dev == FKEY : - backface(0) - drawcube(x,y) - # - if moveit : - x = getvaluator(MOUSEX) - y = getvaluator(MOUSEY) - drawcube(x,y) - - -def initialize () : - foreground () - keepaspect (1, 1) - gid = winopen('backface') - winset(gid) - winconstraints() - # - doublebuffer() - gconfig() - shademodel(FLAT) - # - ortho(-1024.0, 1024.0, -1024.0, 1024.0, -1024.0, 1024.0) - # - qdevice(ESCKEY) - qdevice(REDRAW) - qdevice(LEFTMOUSE) - qdevice(BKEY) - qdevice(FKEY) - qenter(REDRAW,gid) - # - backface(1) - -# -# define a cube -def cube () : - # - # front face - pushmatrix() - translate(0.0,0.0,CUBE_SIZE) - color(RED) - rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE) - popmatrix() - # - # right face - pushmatrix() - translate(CUBE_SIZE, 0.0, 0.0) - rotate(900, 'y') - color(GREEN) - rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE) - popmatrix() - # - # back face - pushmatrix() - translate(0.0, 0.0, -CUBE_SIZE) - rotate(1800, 'y') - color(BLUE) - rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE) - popmatrix() - # - # left face - pushmatrix() - translate(-CUBE_SIZE, 0.0, 0.0) - rotate(-900, 'y') - color(CYAN) - rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE) - popmatrix() - # - # top face - pushmatrix() - translate(0.0, CUBE_SIZE, 0.0) - rotate(-900, 'x') - color(MAGENTA) - rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE) - popmatrix() - # - # bottom face - pushmatrix() - translate(0.0, -CUBE_SIZE, 0.0) - rotate(900, 'x') - color(YELLOW) - rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE) - popmatrix() - -def drawcube(x,y) : - # - pushmatrix() - rotate(2*x, 'x') - rotate(2*y, 'y') - color(BLACK) - clear() - cube() - popmatrix() - swapbuffers() - - -main () diff --git a/Demo/sgi/gl/glstdwin/fontchart.py b/Demo/sgi/gl/glstdwin/fontchart.py deleted file mode 100644 index 6b58f12a9c..0000000000 --- a/Demo/sgi/gl/glstdwin/fontchart.py +++ /dev/null @@ -1,34 +0,0 @@ -import stdwingl - -import stdwin -from stdwinevents import * - -def main(): - size = 12 - w = stdwin.open('Font chart ' + `size`) - while 1: - type, window, detail = stdwin.getevent() - if type == WE_CLOSE: - break - if type == WE_DRAW: - width, height = w.getwinsize() - d = w.begindrawing() - d.setsize(size) - h, v = 0, 0 - for c in range(32, 256): - ch = chr(c) - chw = d.textwidth(ch) - if h + chw > width: - v = v + d.lineheight() - h = 0 - if v >= height: - break - d.text((h, v), ch) - h = h + chw - del d - if type == WE_MOUSE_UP: - size = size + 1 - w.settitle('Font chart ' + `size`) - w.change((0, 0), (2000, 2000)) - -main() diff --git a/Demo/sgi/gl/glstdwin/glstdwdraw.py b/Demo/sgi/gl/glstdwin/glstdwdraw.py deleted file mode 100644 index 4ddc7a67cb..0000000000 --- a/Demo/sgi/gl/glstdwin/glstdwdraw.py +++ /dev/null @@ -1,135 +0,0 @@ -# Define drawing operations for GL stdwin - -import gl -import fm -from GL import LO_XOR, LO_SRC -from glstdwin import MASK - -class DrawingObject: - # - def _init(self, win): - self.fg = win._fg - self.bg = win._bg - self.font = win._font - self.size = win._size - self.width, self.height = win._area[1] - gl.winset(win._gid) - gl.color(self.fg) - return self - # - def setfont(self, fontname): - self.font = fm.findfont(fontname).scalefont(self.size) - # - def setsize(self, size): - ratio = float(size) / float(self.size) - self.size = size - self.font = self.font.scalefont(ratio) - # - def setfgcolor(self, color): - self.fg = color - gl.color(self.fg) - # - def setbgcolor(self, color): - self.bg = color - # - def cliprect(self, area): - #print 'cliprect', area - (left, top), (right, bottom) = area - gl.scrmask(left, right, self.height-bottom, self.height-top) - # - def noclip(self): - #print 'noclip()' - gl.scrmask(0, self.width, 0, self.height) - # - def paint(self, ((left, top), (right, bottom))): - gl.rectf(left, top, right, bottom) - # - def box(self, ((left, top), (right, bottom))): - #print 'box', ((left, top), (right, bottom)) - gl.rect(left, top, right, bottom) - # - def circle(self, (h, v), radius): - gl.circ(h, v, radius) - # - def elarc(self, center, (rh, rv), (a1, a2)): - pass # XXX - # - def erase(self, ((left, top), (right, bottom))): - #print 'erase', ((left, top), (right, bottom)) - gl.color(self.bg) - gl.rectf(left, top, right, bottom) - gl.color(self.fg) - # - def invert(self, ((left, top), (right, bottom))): - #print 'invert', ((h0, v0), (h1, v1)) - gl.logicop(LO_XOR) - gl.color(self.bg) - gl.rectf(left, top, right, bottom) - gl.color(self.fg) - gl.logicop(LO_SRC) - # - def line(self, (h0, v0), (h1, v1)): - #print 'line', ((h0, v0), (h1, v1)) - gl.bgnline() - gl.v2i(h0, v0) - gl.v2i(h1, v1) - gl.endline() - # - def xorline(self, (h0, v0), (h1, v1)): - #print 'xorline', ((h0, v0), (h1, v1)) - gl.logicop(LO_XOR) - gl.color(self.bg) - gl.bgnline() - gl.v2i(h0, v0) - gl.v2i(h1, v1) - gl.endline() - gl.color(self.fg) - gl.logicop(LO_SRC) - # - def point(self, (h, v)): - #print 'point', (h, v) - gl.bgnpoint() - gl.v2i(h, v) - gl.endpoint() - # - def text(self, (h, v), string): - #print 'text', ((h, v), string) - if h < 0: - # If the point is outside the window - # the whole string isn't drawn. - # Skip the beginning of the string. - # XXX What if the font is bigger than 20 pixels? - i, n = 0, len(string) - while h < -MASK and i < n: - h = h + self.font.getstrwidth(string[i]) - i = i + 1 - string = string[i:] - gl.cmov2(h, v + self.baseline()) - self.font.setfont() - fm.prstr(string) - # - def shade(self, (h, v), percent): - pass # XXX - # - def baseline(self): - (printermatched, fixed_width, xorig, yorig, xsize, ysize, \ - height, nglyphs) = self.font.getfontinfo() - return height - yorig - # - def lineheight(self): - (printermatched, fixed_width, xorig, yorig, xsize, ysize, \ - height, nglyphs) = self.font.getfontinfo() - return height - # - def textbreak(self, string, width): - # XXX Slooooow! - n = len(string) - nwidth = self.textwidth(string[:n]) - while nwidth > width: - n = n-1 - nwidth = self.textwidth(string[:n]) - return n - # - def textwidth(self, string): - return self.font.getstrwidth(string) - # diff --git a/Demo/sgi/gl/glstdwin/glstdwin.py b/Demo/sgi/gl/glstdwin/glstdwin.py deleted file mode 100644 index 22285548cf..0000000000 --- a/Demo/sgi/gl/glstdwin/glstdwin.py +++ /dev/null @@ -1,400 +0,0 @@ -# GL STDWIN -# -# See stdwingl for a convenient hack to use this instead of built-in stdwin -# without modifying your application, except for one line in the main file. -# -# Intrinsic differences with built-in stdwin (hard or impossible to fix): -# - Need to call w.close() to close a window !!! -# - Need to call m.close() to remove a menu !!! -# - Doesn't enforce the existence of at most one drawing object -# - No textedit package -# - No X11 selections -# -# Not yet implemented: -# - shade drawing -# - elliptical arc drawing (need to play with transformation) -# - more than one mouse button -# - scroll bars (need to redo viewport handling to get this) -# - partial redraws -# - dialog boxes -# - timer events -# - cursors -# -# Extra features: -# - color (for now, you need to know the colormap index) - - -import gl -import fm -from GL import * -from DEVICE import * -from stdwinevents import * - - -# Customizable constants -# -DEF_FONT = 'Times-Roman' # Default font -DEF_SIZE = 12 # Default font size (points) -MASK = 20 # Viewport minus scrmask - - -# A structure to hold global variables -# -class Struct: pass -G = Struct() -# -G.queue = [] # Pending STDWIN events -G.drawqueue = [] # Windows that need WE_REDRAW -G.windowmap = {} # Map window id to window object -G.windowmap['0'] = None # For convenience -G.focus = None # Input focus -G.fg = BLACK # Foreground color -G.bg = WHITE # Background color -G.def_size = 0, 0 # Default window size -G.def_pos = 0, 0 # Default window position -# -G.size = DEF_SIZE -G.font = fm.findfont(DEF_FONT).scalefont(G.size) - - -# Initialize GL -# -gl.foreground() -gl.noport() -dummygid = gl.winopen('') - -# Ask for all sorts of events -# -# Both REDRAW (= resize and/or redraw!) and INPUTCHANGE are implicitly queued -#qdevice(REDRAW) -#qdevice(INPUTCHANGE) -# -# Keyboard -gl.qdevice(KEYBD) -gl.qdevice(LEFTARROWKEY) -gl.qdevice(RIGHTARROWKEY) -gl.qdevice(UPARROWKEY) -gl.qdevice(DOWNARROWKEY) -gl.qdevice(LEFTALTKEY) -gl.qdevice(RIGHTALTKEY) -# -# Mouse -gl.qdevice(LEFTMOUSE) -#gl.qdevice(MIDDLEMOUSE) -gl.qdevice(RIGHTMOUSE) # Menu button -# NB MOUSEX, MOUSEY events are queued on button down -# -# Window close requests -gl.qdevice(WINQUIT) -gl.qdevice(WINSHUT) -# -# These aren't needed -#gl.qdevice(TIMER0) -#gl.qdevice(WINFREEZE) -#gl.qdevice(WINTHAW) -#gl.qdevice(REDRAWICONIC) - - -# STDWIN: create a new window -# -def open(title): - h, v = G.def_pos - width, height = G.def_size - if h > 0 or v > 0: - # Choose arbitrary defaults - if h < 0: h = 10 - if v < 0: v = 30 - if width <= 0: width = 400 - if height <= 0: height = 300 - gl.prefposition(h, h+width, 1024-v, 1024-v-height) - elif width > 0 or height > 0: - if width <= 0: width = 400 - if height <= 0: height = 300 - gl.prefsize(width, height) - from glstdwwin import WindowObject - win = WindowObject()._init(title) - G.windowmap[`win._gid`] = win - return win - - -# STDWIN: set default initial window position (0 means use default) -# -def setdefwinpos(h, v): - G.def_pos = h, v - - -# STDWIN: set default window size (0 means use default) -# -def setdefwinsize(width, height): - G.def_size = width, height - - -# STDWIN: beep or ring the bell -# -def fleep(): - gl.ringbell() - - -# STDWIN: set default foreground color -# -def setfgcolor(color): - G.fg = color - - -# STDWIN: set default background color -# -def setbgcolor(color): - G.bg = color - - -# STDWIN: get default foreground color -# -def getfgcolor(): - return G.fgcolor - - -# STDWIN: get default background color -# -def getbgcolor(): - return G.bgcolor - - -# Table mapping characters to key codes -# -key2code = key = {} -key['A'] = AKEY -key['B'] = BKEY -key['C'] = CKEY -key['D'] = DKEY -key['E'] = EKEY -key['F'] = FKEY -key['G'] = GKEY -key['H'] = HKEY -key['I'] = IKEY -key['J'] = JKEY -key['K'] = KKEY -key['L'] = LKEY -key['M'] = MKEY -key['N'] = NKEY -key['O'] = OKEY -key['P'] = PKEY -key['Q'] = QKEY -key['R'] = RKEY -key['S'] = SKEY -key['T'] = TKEY -key['U'] = UKEY -key['V'] = VKEY -key['W'] = WKEY -key['X'] = XKEY -key['Y'] = YKEY -key['Z'] = ZKEY -key['0'] = ZEROKEY -key['1'] = ONEKEY -key['2'] = TWOKEY -key['3'] = THREEKEY -key['4'] = FOURKEY -key['5'] = FIVEKEY -key['6'] = SIXKEY -key['7'] = SEVENKEY -key['8'] = EIGHTKEY -key['9'] = NINEKEY -del key -# -code2key = {} -codelist = [] -for key in key2code.keys(): - code = key2code[key] - code2key[`code`] = key - codelist.append(code) -del key - - -# STDWIN: wait for the next event -# -commands = {} -commands['\r'] = WC_RETURN -commands['\b'] = WC_BACKSPACE -commands['\t'] = WC_TAB -# -def getevent(): - while 1: - # - # Get next event from the processed queue, if any - # - if G.queue: - event = G.queue[0] - del G.queue[0] - #print 'getevent from queue -->', event - return event - # - # Get next event from the draw queue, if any, - # but only if there is nothing in the system queue. - # - if G.drawqueue and not gl.qtest(): - win = G.drawqueue[0] - del G.drawqueue[0] - gl.winset(win._gid) - gl.color(win._bg) - gl.clear() - event = WE_DRAW, win, win._area - #print 'getevent from drawqueue -->', event - return event - # - # Get next event from system queue, blocking if necessary - # until one is available. - # Some cases immediately return the event, others do nothing - # or append one or more events to the processed queue. - # - dev, val = gl.qread() - # - if dev == REDRAW: - win = G.windowmap[`val`] - old_area = win._area - win._fixviewport() - win._needredraw() - if old_area <> win._area: - #print 'getevent --> WE_SIZE' - return WE_SIZE, win, None - elif dev == KEYBD: - if val == 3: - raise KeyboardInterrupt # Control-C in window - character = chr(val) - if commands.has_key(character): - return WE_COMMAND, G.focus, commands[character] - return WE_CHAR, G.focus, character - elif dev == LEFTARROWKEY: - if val: - return WE_COMMAND, G.focus, WC_LEFT - elif dev == RIGHTARROWKEY: - if val: - return WE_COMMAND, G.focus, WC_RIGHT - elif dev == UPARROWKEY: - if val: - return WE_COMMAND, G.focus, WC_UP - elif dev == DOWNARROWKEY: - if val: - return WE_COMMAND, G.focus, WC_DOWN - elif dev in (LEFTALTKEY, RIGHTALTKEY): - if val: - for code in codelist: - gl.qdevice(code) - else: - for code in codelist: - gl.unqdevice(code) - elif dev in codelist: - if val: - event = G.focus._doshortcut(code2key[`dev`]) - if event: - return event - elif dev == LEFTMOUSE: - G.mousex = gl.getvaluator(MOUSEX) - G.mousey = gl.getvaluator(MOUSEY) - if val: - type = WE_MOUSE_DOWN - gl.qdevice(MOUSEX) - gl.qdevice(MOUSEY) - else: - type = WE_MOUSE_UP - gl.unqdevice(MOUSEX) - gl.unqdevice(MOUSEY) - return _mouseevent(type) - elif dev == MOUSEX: - G.mousex = val - return _mouseevent(WE_MOUSE_MOVE) - elif dev == MOUSEY: - G.mousey = val - return _mouseevent(WE_MOUSE_MOVE) - elif dev == RIGHTMOUSE: # Menu button press/release - if val: # Press - event = G.focus._domenu() - if event: - return event - elif dev == INPUTCHANGE: - if G.focus: - G.queue.append(WE_DEACTIVATE, G.focus, None) - G.focus = G.windowmap[`val`] - if G.focus: - G.queue.append(WE_ACTIVATE, G.focus, None) - elif dev in (WINSHUT, WINQUIT): - return WE_CLOSE, G.windowmap[`val`], None - else: - print '*** qread() --> dev:', dev, 'val:', val - -# Helper routine to construct a mouse (up, move or down) event -# -def _mouseevent(type): - gl.winset(G.focus._gid) - orgx, orgy = gl.getorigin() - sizex, sizey = gl.getsize() - x = G.mousex - orgx - y = G.mousey - orgy - return type, G.focus, ((x, sizey-y), 1, 0, 0) - - - - -# STDWIN: text measuring functions - -def baseline(): - (printermatched, fixed_width, xorig, yorig, xsize, ysize, \ - height, nglyphs) = G.font.getfontinfo() - return height - yorig - -def lineheight(): - (printermatched, fixed_width, xorig, yorig, xsize, ysize, \ - height, nglyphs) = G.font.getfontinfo() - return height - -def textbreak(string, width): - # XXX Slooooow! - n = len(string) - nwidth = textwidth(string[:n]) - while nwidth > width: - n = n-1 - nwidth = textwidth(string[:n]) - return n - -def textwidth(string): - return G.font.getstrwidth(string) - - -# STDWIN: set default font and size - -def setfont(fontname): - G.font = fm.findfont(fontname).scalefont(G.size) - -def setsize(size): - ratio = float(size) / float(G.size) - G.size = size - G.font = G.font.scalefont(ratio) - - -# Utility functions - -# Exclusive-or of two BYTES -# -def xor(x, y): - a = bits(x) - b = bits(y) - c = [0, 0, 0, 0, 0, 0, 0, 0] - for i in range(8): - c[i] = (a[i] + b[i]) % 2 - return stib(c) - -# Return the bits of a byte as a list of 8 integers -# -def bits(x): - b = [0, 0, 0, 0, 0, 0, 0, 0] - for i in range(8): - x, b[i] = divmod(x, 2) - return b - -# Convert a list of 8 integers (0|1) to a byte -# -def stib(b): - x = 0 - shift = 1 - for i in range(8): - x = x + b[i]*shift - shift = shift*2 - return x diff --git a/Demo/sgi/gl/glstdwin/glstdwmenu.py b/Demo/sgi/gl/glstdwin/glstdwmenu.py deleted file mode 100644 index dd6d90b6ea..0000000000 --- a/Demo/sgi/gl/glstdwin/glstdwmenu.py +++ /dev/null @@ -1,62 +0,0 @@ -# Define menu operations for GL stdwin - -import gl -from glstdwin import key2code - -class MenuObject: - # - def _init(self, win, title): - self._win = win - self._title = title - self._items = [] - return self - # - def close(self): - self._win.remove(self) - del self._win - # - def additem(self, *args): - if len(args) == 2: - text, shortcut = args - elif len(args) == 1: - text, shortcut = args[0], None - else: - raise TypeError, 'arg count' - self._items.append([text, shortcut, 1, 0]) - # - def setitem(self, i, text): - self._items[i][0] = text - # - def enable(self, i, flag): - self._items[i][2] = flag - # - def check(self, i, flag): - self._items[i][3] = flag - # - def _makepup(self, firstitem): - pup = gl.newpup() - if self._title: - gl.addtopup(pup, self._title + '%t', 0) - for item in self._items: - text = item[0] - if not item[2]: # Disabled - text = ' ( ' + text + ' )%x-1' - else: - if item[3]: # Check mark - text = '-> ' + text - else: - text = ' ' + text - if key2code.has_key(item[1]): - text = text + ' [Alt-' + item[1] + ']' - text = text + '%x' + `firstitem` - gl.addtopup(pup, text, 0) - firstitem = firstitem + 1 - return pup - # - def _checkshortcut(self, char): - for i in range(len(self._items)): - item = self._items[i] - if item[2] and item[1] == char: - return i - return -1 - # diff --git a/Demo/sgi/gl/glstdwin/glstdwwin.py b/Demo/sgi/gl/glstdwin/glstdwwin.py deleted file mode 100644 index b880b9a1f9..0000000000 --- a/Demo/sgi/gl/glstdwin/glstdwwin.py +++ /dev/null @@ -1,139 +0,0 @@ -# Define window operations for STDWIN - -import gl -from stdwinevents import * -from glstdwin import G # Global variables -from glstdwin import MASK # Tunable constant - -class WindowObject: - # - def _init(self, title): - self._docsize = (0, 0) - self._fg = G.fg - self._bg = G.bg - self._title = title - self._font = G.font - self._size = G.size - self._menus = [] - self._gid = gl.winopen(title) - gl.winconstraints() # To remove prefsize() effect - self._fixviewport() - self._needredraw() - return self - # - def close(self): - del G.windowmap[`self._gid`] - gl.winclose(self._gid) - self._gid = 0 - # - def _needredraw(self): - if self in G.drawqueue: - G.drawqueue.remove(self) - G.drawqueue.append(self) - # - def begindrawing(self): - from glstdwdraw import DrawingObject - return DrawingObject()._init(self) - # - def change(self, area): - self._needredraw() - # XXX Should record the area to be drawn? - # - def gettitle(self): - return self._title - # - def getdocsize(self): - return self._docsize - # - def getorigin(self): - return self._area[0] - # - def getwinsize(self): - return self._area[1] - # - def scroll(self, area, by): - # XXX ought to use gl.rectcopy() - if by <> (0, 0): - self.change(area) - # - def setdocsize(self, docsize): - self._docsize = docsize - # - def setorigin(self, origin): - pass # XXX - # - def settimer(self, decisecs): - pass # XXX - # - def settitle(self, title): - self._title = title - gl.wintitle(title) - # - def show(self, area): - pass # XXX - # - def _fixviewport(self): - # - # Called after redraw or resize, and initially. - # - # Fix the coordinate system so that (0, 0) is top left, - # units are pixels, and positive axes point right and down. - # - # Make the viewport slightly larger than the window, - # and set the screenmask exactly to the window; this - # help fixing character clipping. - # - # Set self._area to the window rectangle in STDWIN coords. - # - gl.winset(self._gid) - gl.reshapeviewport() - x0, x1, y0, y1 = gl.getviewport() - width, height = x1-x0, y1-y0 - gl.viewport(x0-MASK, x1+MASK, y0-MASK, y1+MASK) - gl.scrmask(x0, x1, y0, y1) - gl.ortho2(-MASK, width+MASK, height+MASK, -MASK) - self._area = (0, 0), (width, height) - # - def menucreate(self, title): - from glstdwmenu import MenuObject - menu = MenuObject()._init(self, title) - self._menus.append(menu) - return menu - # - def _domenu(self): - if not self._menus: - return None - if len(self._menus) == 1: - pup = self._menus[0]._makepup(0) - val = gl.dopup(pup) - gl.freepup(pup) - if val < 0: - return None - return WE_MENU, self, (self._menus[0], val) - # - # More than one menu: use nested menus. - # - pups = [] - firstitem = 0 - for menu in self._menus: - pups.append(menu._makepup(firstitem)) - firstitem = firstitem + 100 - pup = gl.newpup() - for i in range(len(self._menus)): - gl.addtopup(pup, self._menus[i]._title + '%m', pups[i]) - val = gl.dopup(pup) - gl.freepup(pup) - for pup in pups: - gl.freepup(pup) - if val < 0: - return None - i_menu, i_item = divmod(val, 100) - return WE_MENU, self, (self._menus[i_menu], i_item) - # - def _doshortcut(self, char): - for menu in self._menus: - i = menu._checkshortcut(char) - if i >= 0: - return WE_MENU, self, (menu, i) - return None - # diff --git a/Demo/sgi/gl/glstdwin/stdwingl.py b/Demo/sgi/gl/glstdwin/stdwingl.py deleted file mode 100644 index 442759319b..0000000000 --- a/Demo/sgi/gl/glstdwin/stdwingl.py +++ /dev/null @@ -1,10 +0,0 @@ -# If you put 'import stdwin_gl' in front of the main program of a program -# using stdwin (before it has a chance to import the real stdwin!), -# it will use glstdwin and think it is stdwin. - -import sys -if sys.modules.has_key('stdwin'): - raise RuntimeError, 'too late -- stdwin has already been imported' - -import glstdwin -sys.modules['stdwin'] = glstdwin diff --git a/Demo/sgi/gl/glstdwin/tcolor.py b/Demo/sgi/gl/glstdwin/tcolor.py deleted file mode 100644 index d1c49e115d..0000000000 --- a/Demo/sgi/gl/glstdwin/tcolor.py +++ /dev/null @@ -1,43 +0,0 @@ -# Try colors -- display all 256 possible colors, with their color index - -import stdwingl - -import stdwin -from stdwinevents import * - -NROWS = 16 -NCOLS = 16 - -def main(): - stdwin.setdefwinsize(NCOLS * stdwin.textwidth('12345'), \ - NROWS * stdwin.lineheight() * 3) - w = stdwin.open('TestColors') - # - while 1: - type, window, detail = stdwin.getevent() - if type == WE_CLOSE: - print 'Bye.' - break - elif type == WE_SIZE: - w.change((0,0), (10000, 10000)) - elif type == WE_DRAW: - width, height = w.getwinsize() - d = w.begindrawing() - for row in range(NROWS): - for col in range(NCOLS): - color = row*NCOLS + col - d.setfgcolor(color) - p = col*width/NCOLS, row*height/NROWS - q = (col+1)*width/NCOLS, \ - (row+1)*height/NROWS - d.paint((p, q)) - d.setfgcolor(0) - d.box((p, q)) - d.text(p, `color`) - p = p[0] , p[1]+ d.lineheight() - d.setfgcolor(7) - d.text(p, `color`) - del d - # - -main() diff --git a/Demo/sgi/gl/glstdwin/tglsw.py b/Demo/sgi/gl/glstdwin/tglsw.py deleted file mode 100644 index 8854e98812..0000000000 --- a/Demo/sgi/gl/glstdwin/tglsw.py +++ /dev/null @@ -1,70 +0,0 @@ -import sys - -if len(sys.argv) < 2: - import stdwingl - color = 1 - needclose = 1 -else: - color = 0 - needclose = 0 - -import stdwin -import time -from stdwinevents import * -from GL import BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE - -def main(): - # - stdwin.setdefwinsize(300, 300) - stdwin.setdefwinpos(0, 0) - if color: stdwin.setbgcolor(YELLOW) - w1 = stdwin.open('Hello, world') - w1.box = (10, 10), (90, 90) - # - stdwin.setdefwinsize(0, 0) - stdwin.setdefwinpos(50, 50) - if color: stdwin.setbgcolor(GREEN) - w2 = stdwin.open('Second window') - w2.box = (10, 10), (90, 90) - # - while w1 or w2: - type, window, detail = stdwin.getevent() - if type == WE_DRAW: - d = window.begindrawing() - if window == w1: - if color: d.setfgcolor(BLACK) - d.box(((50, 50), (250, 250))) - if color: d.setfgcolor(RED) - d.cliprect(((50, 50), (250, 250))) - d.paint(w1.box) - d.noclip() - if color: d.setfgcolor(BLUE) - d.line((0, 0), w1.box[0]) - elif window == w2: - if color: d.setfgcolor(WHITE) - d.box(w2.box) - if color: d.setfgcolor(BLACK) - d.text(w2.box[0], 'Hello world') - else: - print 'Strange draw???', window, detail - del d - elif type == WE_CLOSE: - if needclose: window.close() - if window == w1: - w1 = None - elif window == w2: - w2 = None - else: - print 'weird close event???', window, detail - elif type in (WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP): - h, v = detail[0] - window.box = (h, v), (h+80, v+80) - window.change(((0,0), (2000, 2000))) - elif type == WE_CHAR: - print 'character', `detail` - else: - print type, window, detail - # - -main() -print 'Done.' diff --git a/Demo/sgi/gl/glstdwin/tmenu.py b/Demo/sgi/gl/glstdwin/tmenu.py deleted file mode 100644 index 233edae3c1..0000000000 --- a/Demo/sgi/gl/glstdwin/tmenu.py +++ /dev/null @@ -1,44 +0,0 @@ -# Test menus - -import stdwingl - -import stdwin -from stdwinevents import * - -def main(): - w = stdwin.open('TestMenus') - # - items1 = 'Aap', 'Noot', 'Mies' - m1 = w.menucreate('Menu-1') - for item in items1: - m1.additem(item, item[0]) - # - items2 = 'Wim', 'Zus', 'Jet', 'Teun', 'Vuur' - m2 = w.menucreate('Menu-2') - for item in items2: - m2.additem(item, `len(item)`) - # - m1.enable(1, 0) - m2.check(1, 1) - # - while 1: - type, window, detail = stdwin.getevent() - if type == WE_CLOSE: - break - elif type == WE_DRAW: - d = w.begindrawing() - d.box(((50,50), (100,100))) - del d - elif type == WE_MENU: - mp, i = detail - if mp == m1: - print 'Choice:', items1[i] - elif mp == m2: - print 'Choice:', items2[i] - else: - print 'Not one of my menus!' - elif type == WE_CHAR: - print 'Character', `detail` - # - -main() diff --git a/Demo/sgi/gl/kites.py b/Demo/sgi/gl/kites.py deleted file mode 100755 index 6e3dea6f49..0000000000 --- a/Demo/sgi/gl/kites.py +++ /dev/null @@ -1,194 +0,0 @@ -#! /usr/local/bin/python - -# *** This only works correctly on a 24 bit-plane machine. *** -# -# A simple Python program that tests the some parts of the -# GL library. It shows the speed that can be obtained when -# doing simple graphics. -# -# The bottleneck in this program is NOT Python but the graphics -# engine; i.e Python can feed the graphics pipeline fast enough -# on the 4D/25G. -# -# This program show 3 kites flying around the screen. It uses -# -# * bgnpolygon, endpolygon -# * v3, n3 -# * lmdef, lmbind -# -# Usage : -# -# ESC -> exit program -# MOUSE3 -> freeze toggle -# MOUSE2 -> one step (use this in freeze state) - -from GL import * -from gl import * -import DEVICE -from math import * - -# -# viewobj : sets the rotation, translation and scaling -# set appropiate material, call drawobject() -# -def viewobj (r, s, t, mat) : - pushmatrix() - rot (r * 10.0, 'X') - rot (r * 10.0, 'Y') - rot (r * 10.0, 'Z') - scale (s[0], s[1], s[2]) - translate (t[0], t[1], t[2]) - lmbind(MATERIAL, mat) - drawobject() - popmatrix() - -# -# makeobj : the contructor of the object -# -def mkobj () : - v0 = (-5.0 ,0.0, 0.0) - v1 = (0.0 ,5.0, 0.0) - v2 = (5.0 ,0.0, 0.0) - v3 = (0.0 ,2.0, 0.0) - n0 = (sqrt(2.0)/2.0, sqrt(2.0)/2.0, 0.0) - vn = ((v0, n0), (v1, n0), (v2, n0), (v3, n0)) - # - return vn - -# -# the object itself as an array of vertices and normals -# -kite = mkobj () - -# -# drawobject : draw a triangle. with bgnpolygon -# -def drawobject () : - # - bgnpolygon() - vnarray (kite) - endpolygon() - -# -# identity matrix -# -idmat=[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0] - -# -# the rgb-value of light-blue -# -LightBlue = (43,169,255) - -# -# the different materials. -# -m1=[SPECULAR,0.0,0.0,0.6,DIFFUSE,0.0,0.0,0.8,SHININESS,20.0,LMNULL] -m2=[SPECULAR,0.8,0.0,0.1,DIFFUSE,0.8,0.0,0.3,SHININESS,120.0,LMNULL] -m3=[SPECULAR,0.0,1.0,0.0,DIFFUSE,0.0,0.6,0.0,SHININESS,120.0,LMNULL] - -# -# lightsources -# -light1 = [LCOLOR,1.0,1.0,1.0,POSITION,15.0,15.0,0.0,1.0,LMNULL] -light2 = [LCOLOR,1.0,1.0,1.0,POSITION,-15.0,15.0,0.0,1.0,LMNULL] - -# -# the lightmodel -# -model = [AMBIENT,0.2,0.2,0.2,LMNULL] - -# -# initgl : opens the window, configures the pipeline to 2buf and zbuf, -# sets the viewing, defines and binds the materials -# -def initgl () : - # - # open window - # - foreground () - keepaspect (1, 1) - prefposition (100, 500, 100, 500) - w = winopen ('PYTHON lights') - keepaspect (1, 1) - winconstraints() - # - # configure pipeline (zbuf, 2buf, GOURAUD and RGBmode) - # - zbuffer (1) - doublebuffer () - shademodel (GOURAUD) - RGBmode () - gconfig () - # - # define and bind materials (set perspective BEFORE loadmat !) - # - mmode(MVIEWING) - perspective (900, 1.0, 1.0, 20.0) - loadmatrix(idmat) - lmdef(DEFMATERIAL, 1, m1) - lmdef(DEFMATERIAL, 2, m2) - lmdef(DEFMATERIAL, 3, m3) - lmdef(DEFLIGHT, 1, light1) - lmdef(DEFLIGHT, 2, light2) - lmdef(DEFLMODEL, 1, model) - lmbind(LIGHT0,1) - lmbind(LIGHT1,2) - lmbind(LMODEL,1) - # - # set viewing - # - lookat (0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0) - # - # ask for the REDRAW and ESCKEY events - # - qdevice(DEVICE.MOUSE3) - qdevice(DEVICE.MOUSE2) - qdevice(DEVICE.REDRAW) - qdevice(DEVICE.ESCKEY) - -# -# GoForIT : use 2buf to redraw the object 2n times. index i is used as -# the (smoothly changing) rotation angle -# -def GoForIt(i) : - freeze = 1 - while 1 : - if freeze <> 0 : - i = i + 1 - # - # clear z-buffer and clear background to light-blue - # - zclear() - c3i (LightBlue) - clear() - # - # draw the 3 traiangles scaled above each other. - # - viewobj(float(i),[1.0,1.0,1.0],[1.0,1.0,1.0],1) - viewobj(float(i),[0.75,0.75,0.75],[0.0,2.0,2.0],2) - viewobj(float(i),[0.5,0.5,0.5],[0.0,4.0,4.0],3) - # - swapbuffers() - # - if qtest() <> 0 : - dev, val = qread() - if dev == DEVICE.ESCKEY : - break - elif dev == DEVICE.REDRAW : - reshapeviewport () - elif dev == DEVICE.MOUSE3 and val <> 0 : - freeze = 1 - freeze - elif dev == DEVICE.MOUSE2 and val <> 0 : - i = i + 1 - - -# the main program -# -def main () : - initgl () - GoForIt (0) - -# -# exec main -# -main () diff --git a/Demo/sgi/gl/kunst.py b/Demo/sgi/gl/kunst.py deleted file mode 100755 index 2055e52e83..0000000000 --- a/Demo/sgi/gl/kunst.py +++ /dev/null @@ -1,426 +0,0 @@ -#! /usr/local/bin/python -# Simulate the artwork in the hall. -# Jack Jansen, Feb 91. - -from gl import * -from GL import * -from math import * -from DEVICE import * -import sys -import __main__ -main_dict = __main__.__dict__ - -SPOTDIRECTION = 103 -SPOTLIGHT = 104 - -# -# Make a cylinder paralel with the Z axis with center (X,Y,0) -# and radius 1 -def mkcyl(nslice, nparts, docircle): - cyl = [] - step = 2.0 / float(nslice) - z = -1.0 - for i in range(nslice): - cyl.append(mkslice(z, z+step, nparts, docircle)) - z = z + step - return drawcylinder(cyl) -# -# Make one part of a cylinder -# -def mkslice(z1, z2, nparts, docircle): - if docircle: - w1 = z1 - w2 = z2 - w1 = sqrt(1.0-w1*w1) - w2 = sqrt(1.0-w2*w2) - normalz = 1.0 - else: - w1 = 1.0 - w2 = 1.0 - normalz = 0.0 - slice = [] - step = (2.0*pi)/float(nparts) - angle = 0.0 - for i in range(nparts+1): - vx = cos(angle) - vy = sin(angle) - slice.append( ((vx*w1,vy*w1,z1), (vx*w1, vy*w1, z1*normalz)) ) - slice.append( ((vx*w2,vy*w2,z2), (vx*w2, vy*w2, z2*normalz)) ) - angle = angle + step - return slice -# -# Drawcylinder : draw the cylinder -# -class struct: pass -curobj = struct() -curobj.curobj = 1 -def drawcylinder(cyl): - obj = curobj.curobj - curobj.curobj = curobj.curobj+1 - makeobj(obj) - for slice in cyl: - bgntmesh() - vnarray(slice) - endtmesh() - closeobj() - return obj -# -def drawnormals(cyl): - for slice in cyl: - for triang in slice: - bgnline() - v3f(triang[0]) - v3f(triang[0][0] + triang[1][0], triang[0][1] + triang[1][1], triang[0][2] + triang[1][2]) - endline() -def drawfloors(): - obj = curobj.curobj - curobj.curobj = curobj.curobj+1 - makeobj(obj) - bgnpolygon() - v3i(4,6,-6) - v3i(-6,6,-6) - v3i(-6,-6,-6) - v3i(4,-6,-6) - endpolygon() - for floor in range(3): - pos = -1 + 5*floor - bgnpolygon() - v3i(4,4,pos) - v3i(-6,4,pos) - v3i(-6,6,pos) - v3i(4,6,pos) - endpolygon() - bgnpolygon() - v3i(-4,4,pos) - v3i(-4,-4,pos) - v3i(-6,-4,pos) - v3i(-6,4,pos) - endpolygon() - bgnpolygon() - v3i(-6,-4,pos) - v3i(-6,-6,pos) - v3i(4,-6,pos) - v3i(4,-4,pos) - endpolygon() - closeobj() - return obj -def drawdoors(): - obj = curobj.curobj - curobj.curobj = curobj.curobj+1 - makeobj(obj) - for floor in range(3): - pos = -1+5*floor - bgnpolygon() - v3i(-2,6,pos) - v3i(-2,6,pos+3) - v3i(0,6,pos+3) - v3i(0,6,pos) - endpolygon() - closeobj() - return obj -def drawrailing(): - obj = curobj.curobj - curobj.curobj = curobj.curobj+1 - makeobj(obj) - for floor in range(3): - pos = -1 + 5*floor - bgnpolygon() - v3i(4,4,pos) - v3i(4,4,pos-1) - v3i(-4,4,pos-1) - v3i(-4,4,pos) - endpolygon() - bgnpolygon() - v3i(-4,4,pos) - v3i(-4,4,pos-1) - v3i(-4,-4,pos-1) - v3i(-4,-4,pos) - endpolygon() - bgnpolygon() - v3i(-4,-4,pos) - v3i(-4,-4,pos-1) - v3i(4,-4,pos-1) - v3i(4,-4,pos) - endpolygon() - closeobj() - return obj -def drawwalls(): - obj = curobj.curobj - curobj.curobj = curobj.curobj+1 - makeobj(obj) - bgnpolygon() - v3i(4,6,-6) - v3i(4,6,18) - v3i(-6,6,18) - v3i(-6,6,-6) - endpolygon() - bgnpolygon() - v3i(-6,6,-6) - v3i(-6,6,18) - v3i(-6,-6,18) - v3i(-6,-6,-6) - endpolygon() - bgnpolygon() - v3i(-6,-6,-6) - v3i(-6,-6,18) - v3i(4,-6,18) - v3i(4,-6,-6) - endpolygon() - bgnpolygon() - v3i(4,-6,-6) - v3i(4,-6,18) - v3i(4,4,18) - v3i(4,4,-6) - endpolygon() - closeobj() - return obj -def axis(): - bgnline() - cpack(0xff0000) - v3i(-1,0,0) - v3i(1,0,0) - v3f(1.0, 0.1, 0.1) - endline() - bgnline() - cpack(0xff00) - v3i(0,-1,0) - v3i(0,1,0) - v3f(0.1, 1.0, 0.1) - endline() - bgnline() - cpack(0xff) - v3i(0,0,-1) - v3i(0,0,1) - v3f(0.1,0.1,1.0) - endline() -# -green_velvet = [ DIFFUSE, 0.05, 0.4, 0.05, LMNULL] -silver = [ DIFFUSE, 0.3, 0.3, 0.3, SPECULAR, 0.9, 0.9, 0.95, \ - SHININESS, 40.0, LMNULL] -floormat = [ AMBIENT, 0.5, 0.25, 0.15, DIFFUSE, 0.5, 0.25, 0.15, SPECULAR, 0.6, 0.3, 0.2, SHININESS, 20.0, LMNULL] -wallmat = [ DIFFUSE, 0.4, 0.2, 0.1, AMBIENT, 0.4, 0.20, 0.10, SPECULAR, 0.0, 0.0, 0.0, SHININESS, 20.0, LMNULL] -offwhite = [ DIFFUSE, 0.8, 0.8, 0.6, AMBIENT, 0.8, 0.8, 0.6, SPECULAR, 0.9, 0.9, 0.9, SHININESS, 30.0, LMNULL] -doormat = [ DIFFUSE, 0.1, 0.2, 0.5, AMBIENT, 0.2, 0.4, 1.0, SPECULAR, 0.2, 0.4, 1.0, SHININESS, 60.0, LMNULL] - -toplight = [ LCOLOR, 1.0, 1.0, 0.5, \ - POSITION, 0.0, 0.0, 11.0, 1.0, LMNULL] -floor1light = [ LCOLOR, 1.0, 1.0, 1.0, POSITION, 3.9, -3.9, 0.0, 1.0, \ - SPOTDIRECTION, 1.0, 1.0, 0.0, SPOTLIGHT, 10.0, 90.0, LMNULL] - -lmodel = [ AMBIENT, 0.92, 0.8, 0.5, LOCALVIEWER, 1.0, LMNULL] -# -def lighting(): - lmdef(DEFMATERIAL, 1, green_velvet) - lmdef(DEFMATERIAL, 2, silver) - lmdef(DEFMATERIAL, 3, floormat) - lmdef(DEFMATERIAL, 4, wallmat) - lmdef(DEFMATERIAL, 5, offwhite) - lmdef(DEFMATERIAL, 6, doormat) - lmdef(DEFLIGHT, 1, toplight) - lmdef(DEFLIGHT, 2, floor1light) - lmdef(DEFLMODEL, 1, lmodel) - lmbind(MATERIAL, 1) - lmbind(LIGHT0, 1) - lmbind(LIGHT1, 2) - lmbind(LMODEL, 1) -IdMat=[1.0,0.0,0.0,0.0, 0.0,1.0,0.0,0.0, 0.0,0.0,1.0,0.0, 0.0,0.0,0.0,1.0] -# -def defun(axis): - done = 0 - while not done: - print 'F'+axis+'(t) = ', - s = sys.stdin.readline(100) - print - try: - s = 'def f'+axis+'(t): return '+s - exec(s, main_dict) - done = 1 - except RuntimeError: - print 'Sorry, there is a syntax error in your expression' -def getfunctions(): - print 'Welcome to the CWI art simulator. You can now enter X, Y and Z' - print 'coordinates as a function of t.' - print 'Normal trig functions are available. Please use floating point' - print 'values only (so 0.0 for 0). Comments to jack@cwi.nl' - defun('x') - defun('y') - defun('z') - print 'Ok, here you go. Use mouse+right button to move up/down,' - print 'mouse+middle to speed up/slow down time. type ESC to quit simulation' -def main(): - getfunctions() - foreground() - prefposition(100,600,100,600) - void = winopen('cyl') - qdevice(ESCKEY) - qdevice(MOUSE1) - qdevice(MOUSE2) - qdevice(PKEY) - RGBmode() - doublebuffer() - gconfig() - zbuffer(1) - mmode(MVIEWING) - perspective(400, 1.0, 1.0, 20.0) - loadmatrix(IdMat) - vx = 0.0 - vy = -6.0 - vz = 0.0 - lookat(0.0, -6.0, 0.0, 0.0, 0.0, 0.0, 0) - lighting() - t = -1.0 - step = 1.0 - bol = mkcyl(12,24, 1) - cable = mkcyl(1, 6, 0) - floors = drawfloors() - walls = drawwalls() - pillar = mkcyl(1,4,0) - railing = drawrailing() - doors = drawdoors() - shademodel(GOURAUD) - mousing = -1 - pausing = 0 - while 1: - # - # Check for some user input - # - if qtest(): - dev, value = qread() - if dev == PKEY and value == 1: - pausing = 1 - if dev == ESCKEY: - break - elif (dev==MOUSE1 or dev==MOUSE2) and value == 1: - if mousing > 0: - vx = 0.0 - vy = -6.0 - vz = 0.0 - mousing = dev - oldx = getvaluator(MOUSEX) - oldy = getvaluator(MOUSEY) - elif (dev==MOUSE1 or dev==MOUSE2): - mousing = -1 - if mousing >= 0: - newx = getvaluator(MOUSEX) - newy = getvaluator(MOUSEY) - if newy <> oldy and mousing==MOUSE1: - vz = vz + float(newy - oldy)/100.0 - dist = sqrt(vx*vx + vy*vy + vz*vz) - perspective(400, 1.0, 1.0, dist+16.0) - loadmatrix(IdMat) - if vz < 0.0: - lookat(vx, vy, vz, 0.0, 0.0, 0.0, 1800) - else: - lookat(vx, vy, vz, 0.0, 0.0, 0.0, 0) - if newy <> oldy and mousing==MOUSE2: - step = step * exp(float(newy-oldy)/400.0) - if getbutton(CTRLKEY) == 0: - t = t + step - else: - t = t - step - if getbutton(LEFTSHIFTKEY) == 0: - shademodel(GOURAUD) - else: - shademodel(FLAT) - # - # Draw background and axis - cpack(0x105090) - clear() - zclear() - cpack(0x905010) - axis() - # - # Draw object - # - bolx = fx(t) - boly = fy(t) - bolz = fz(t) - err = '' - if bolx < -4.0 or bolx > 4.0: - err = 'X('+`bolx`+') out of range [-4,4]' - if boly < -4.0 or boly > 4.0: - err = 'Y('+`boly`+') out of range [-4,4]' - if bolz < -4.0 or bolz > 8.0: - err = 'Z('+`bolz`+') out of range [-4,8]' - if not err: - pushmatrix() - translate(bolx, boly, bolz) - scale(0.3, 0.3, 0.3) - lmbind(MATERIAL, 2) - callobj(bol) - popmatrix() - # - # Draw the cables - # - bolz = bolz + 0.3 - pushmatrix() - linesmooth(SML_ON) - bgnline() - v3i(-4,-4,9) - v3f(bolx, boly, bolz) - endline() - bgnline() - v3i(-4,4,9) - v3f(bolx, boly, bolz) - endline() - bgnline() - v3i(4,-4,9) - v3f(bolx, boly, bolz) - endline() - bgnline() - v3i(4,4,9) - v3f(bolx, boly, bolz) - endline() - popmatrix() - # - # draw the floors - # - lmbind(MATERIAL, 3) - callobj(floors) - lmbind(MATERIAL, 4) - callobj(walls) - lmbind(MATERIAL, 5) - pushmatrix() - translate(-4.5,4.5,3.0) - scale(0.2,0.2,9.0) - rotate(450,'z') - callobj(pillar) - popmatrix() - callobj(railing) - lmbind(MATERIAL, 6) - pushmatrix() - translate(0.0, -0.01, 0.0) - callobj(doors) - popmatrix() - if mousing == MOUSE2 or err: - cpack(0xff0000) - cmov(0.0, 0.0, 0.4) - charstr('t='+`t`) - if mousing == MOUSE2: - cpack(0xff0000) - cmov(0.0, 0.0, 0.2) - charstr('delta-t='+`step`) - if err: - cpack(0xff00) - cmov(0.0, 0.0, 0.2) - print err - charstr(err) - pausing = 1 - if pausing: - cpack(0xff00) - cmov(0.0, 0.0, 0.0) - charstr('Pausing, type P to continue') - swapbuffers() - if pausing: - while 1: - dv=qread() - if dv==(PKEY,1): - break - if dv==(ESCKEY,1): - sys.exit(0) - pausing = 0 -# -try: - main() -except KeyboardInterrupt: - sys.exit(1) diff --git a/Demo/sgi/gl/mclock.doc b/Demo/sgi/gl/mclock.doc deleted file mode 100755 index 2208f33fb3..0000000000 --- a/Demo/sgi/gl/mclock.doc +++ /dev/null @@ -1,60 +0,0 @@ -Newsgroups: cwi.sgi -Subject: Re: new clock -Distribution: cwi.sgi -References: <2246@charon.cwi.nl> - -Last week I wrote: - ->For your enjoyment I have implemented a colorful clock. - -The clock has now been extended with some new facilities: a menu, an -alarm and a gong. These may require some explanation beyond what's in -the usage message. - -Menu ----- -The right mouse button now pops up a menu that allows you to turn the -seconds hand on or off and to switch the alarm off. - -Alarm ------ - -The left and middle buttons set the alarm. When it is on, the alarm -time is displayed as a time on a 24 hour clock in the bottom left -corner. It is also indicated by two red triangles, corresponding to the -little (hours) and big (minutes) hand. These hands can be moved around: -the left mouse button moves the minutes hand, the middle button moves -the hourds hand. Watch out for differences of twelve hours (always -check the digital display); these can be corrected by dragging the hours -hand once around the dial. - -When the alarm goes off, two things happen: a shell command specified on -the command line with the -a option is executed (in the background), and -the clock's colors change every two seconds, for five minutes. You can -also turn the alarm off by using the menu accessible through the right -mouse button. - -There is no default command for the -a option; if it is not specified, -only the changing of the colors happens. If you have an 8 ohm speaker -connected to the audio output of your Personal Iris, a suitable command -would be: - - mclock -a '/ufs/guido/bin/sgi/play /ufs/guido/lib/sounds/alarm' - -Gong ----- - -Some people like a clock that makes noises every hour, or even more -often. This is supported by the -g and -G options. With -g you specify -a shell command to be executed to sound the gong; with -G you can -specify the interval between gong calls, in seconds (default is one hour). -The shell command is executed in the background. It is given two -arguments: the hours (on a 24 hour clock!) and the minutes. The -executable Python script /ufs/guido/bin/sgi/chime is a suitable example. -Again, this only works if you have installed a speaker (I bet 8 ohm -speakers are going to be in demand!) - --- -Guido van Rossum, Centre for Mathematics and Computer Science (CWI), Amsterdam -guido@cwi.nl or ..!hp4nl!cwi.nl!guido or guido%cwi.nl@uunet.uu.net -"A thing of beauty is a joy till sunrise" diff --git a/Demo/sgi/gl/mclock.py b/Demo/sgi/gl/mclock.py deleted file mode 100755 index ec39de9c8b..0000000000 --- a/Demo/sgi/gl/mclock.py +++ /dev/null @@ -1,736 +0,0 @@ -#! /usr/local/bin/python - -# "M Clock" -# -# An implementation in software of an original design by Rob Juda. -# Clock implementation: Guido van Rossum. -# Alarm and Gong features: Sape Mullender. -# -# XXX TO DO: -# add arguments to specify initial window position and size -# find out local time zone difference automatically -# add a date indicator -# allow multiple alarms -# allow the menu to change more parameters - -import sys - -from gl import * -from GL import * -from DEVICE import * -import time -import getopt -import string -import os -from math import pi -import math - -FULLC = 3600 # Full circle in 1/10-ths of a degree -MIDN = 900 # Angle of the 12 o'clock position -R, G, B = 0, 1, 2 # Indices of colors in RGB list - -HOUR = 3600 # Number of seconds per hour -MINUTE = 60 # Number of seconds per minute - -class struct: pass # Class to define featureless structures -Gl = struct() # Object to hold writable global variables - -# Default constants (used in multiple places) - -SCREENBG = 127, 156, 191 -NPARTS = 9 -TITLE = 'M Clock' - -# Set timezone, check for daylight saving time -TZDIFF = time.timezone -if time.localtime(time.time())[-1]: - TZDIFF = time.altzone - -# Default parameters - -Gl.foreground = 0 # If set, run in the foreground -Gl.fullscreen = 0 # If set, run on full screen -Gl.tzdiff = TZDIFF # Seconds west of Greenwich (winter time) -Gl.nparts = NPARTS # Number of parts each circle is divided in (>= 2) -Gl.debug = 0 # If set, print debug output -Gl.doublebuffer = 1 # If set, use double buffering -Gl.update = 0 # Update interval; seconds hand is suppressed if > 1 -Gl.colorsubset = 0 # If set, display only a subset of the colors -Gl.cyan = 0 # If set, display cyan overlay (big hand) -Gl.magenta = 0 # If set, display magenta overlay (little hand) -Gl.yellow = 0 # If set, display yellow overlay (fixed background) -Gl.black = 0 # If set, display black overlay (hands) -Gl.colormap = 0 # If set, use colormap mode instead of RGB mode -Gl.warnings = 0 # If set, print warnings -Gl.title = '' # Window title (default set later) -Gl.name = 'mclock' # Window title for resources -Gl.border = 1 # If set, use a window border (and title) -Gl.bg = 0, 0, 0 # Background color R, G, B value -Gl.iconic = 0 # Set in iconic state -Gl.fg = 255, 0, 0 # Alarm background RGB (either normal or alarm) -Gl.ox,Gl.oy = 0,0 # Window origin -Gl.cx,Gl.cy = 0,0 # Window size -Gl.alarm_set = 0 # Alarm on or off -Gl.alarm_on = 0 # Alarm is ringing -Gl.alarm_time = 0 # Alarm time in seconds after midnight -Gl.alarm_hours = 0 # Alarm hour setting, 24 hour clock -Gl.alarm_minutes = 0 # Alarm minutes setting -Gl.alarm_rgb = 0,0,0 # Alarm display RGB colors -Gl.alarm_cmd = '' # Command to execute when alarm goes off -Gl.mouse2down = 0 # Mouse button state -Gl.mouse3down = 0 # Mouse button state -Gl.gong_cmd = '' # Command to execute when chimes go off -Gl.gong_int = 3600 # Gong interval -Gl.indices = R, G, B # Colors (permuted when alarm is on) - -def main(): - # - sys.stdout = sys.stderr # All output is errors/warnings etc. - # - try: - args = getoptions() - except string.atoi_error, value: - usage(string.atoi_error, value) - except getopt.error, msg: - usage(getopt.error, msg) - # - if args: - realtime = 0 - hours = string.atoi(args[0]) - minutes = seconds = 0 - if args[1:]: minutes = string.atoi(args[1]) - if args[2:]: seconds = string.atoi(args[2]) - localtime = ((hours*60)+minutes)*60+seconds - else: - realtime = 1 - # - if Gl.title == '': - if realtime: - Gl.title = TITLE - else: - title = '' - for arg in args: title = title + ' ' + arg - Gl.title = title[1:] - del title - # - wid = makewindow() - Gl.ox,Gl.oy = getorigin() - Gl.cx,Gl.cy = getsize() - initmenu() - clearall() - # - if not Gl.update: - Gl.update = 60 - # - if Gl.update <= 1: - Gl.timernoise = 6 - else: - Gl.timernoise = 60 - noise(TIMER0, Gl.timernoise) - # - qdevice(WINSHUT) - qdevice(WINQUIT) - qdevice(ESCKEY) - if realtime: - qdevice(TIMER0) - qdevice(REDRAW) - qdevice(WINFREEZE) - qdevice(WINTHAW) - qdevice(MENUBUTTON) # MOUSE1 - qdevice(MOUSE3) # Left button - qdevice(MOUSE2) # Middle button - unqdevice(INPUTCHANGE) - # - lasttime = 0 - Gl.change = 1 - while 1: - if realtime: - localtime = int(time.time() - Gl.tzdiff) - if Gl.alarm_set: - if localtime%(24*HOUR) == Gl.alarm_time: - # Ring the alarm! - if Gl.debug: - print 'Rrrringg!' - Gl.alarm_on = 1 - if Gl.alarm_cmd <> '': - d = os.system(Gl.alarm_cmd+' '+`Gl.alarm_time/3600`+' '+`(Gl.alarm_time/60)%60` + ' &') - Gl.change = 1 - clearall() - if Gl.alarm_on: - if (localtime - Gl.alarm_time) % (24*HOUR) > 300: - # More than 5 minutes away from alarm - Gl.alarm_on = 0 - if Gl.debug: - print 'Alarm turned off' - Gl.change = 1 - clearall() - Gl.indices = R, G, B - else: - if localtime % 2 == 0: - # Permute color indices - Gl.indices = Gl.indices[2:] + Gl.indices[:2] - Gl.change = 1 - if Gl.gong_cmd <> '' and localtime%Gl.gong_int == 0: - d = os.system(Gl.gong_cmd+' '+`(localtime/3600)%24`+' '+`(localtime/60)%60` + ' &') - if localtime/Gl.update <> lasttime/Gl.update: - if Gl.debug: print 'new time' - Gl.change = 1 - if Gl.change: - if Gl.debug: print 'drawing' - doit(localtime) - lasttime = localtime - Gl.change = 0 - dev, data = qread() - if Gl.debug and dev <> TIMER0: - print dev, data - if dev == TIMER0: - if Gl.debug > 1: - print dev, data - elif dev == MOUSE3: - mousex = getvaluator(MOUSEX) - mousey = getvaluator(MOUSEY) - if mouseclick(3, data, mousex, mousey): - Gl.change = 1 - elif dev == MOUSE2: - mousex = getvaluator(MOUSEX) - mousey = getvaluator(MOUSEY) - if mouseclick(2, data, mousex, mousey): - Gl.change = 1 - elif dev == MOUSEX: - mousex = data - if Gl.mouse2down: - mouse2track(mousex, mousey) - if Gl.mouse3down: - mouse3track(mousex, mousey) - elif dev == MOUSEY: - mousey = data - if Gl.mouse2down: - mouse2track(mousex, mousey) - if Gl.mouse3down: - mouse3track(mousex, mousey) - elif dev == REDRAW or dev == REDRAWICONIC: - if Gl.debug: - if dev == REDRAW: print 'REDRAW' - else: print 'REDRAWICONIC' - reshapeviewport() - Gl.ox,Gl.oy = getorigin() - Gl.cx,Gl.cy = getsize() - Gl.change = 1 - clearall() - elif dev == MENUBUTTON: - if Gl.debug: print 'MENUBUTTON' - handlemenu() - elif dev == WINFREEZE: - if Gl.debug: print 'WINFREEZE' - Gl.iconic = 1 - noise(TIMER0, 60*60) # Redraw every 60 seconds only - elif dev == WINTHAW: - if Gl.debug: print 'WINTHAW' - Gl.iconic = 0 - noise(TIMER0, Gl.timernoise) - Gl.change = 1 - elif dev == ESCKEY or dev == WINSHUT or dev == WINQUIT: - if Gl.debug: print 'Exit' - sys.exit(0) - -def getoptions(): - optlist, args = getopt.getopt(sys.argv[1:], 'A:a:B:bc:dFfG:g:n:sT:t:u:wCMYK') - for optname, optarg in optlist: - if optname == '-A': - Gl.fg = eval(optarg) # Should be (r,g,b) - elif optname == '-a': - Gl.alarm_cmd = optarg - elif optname == '-B': - Gl.bg = eval(optarg) # Should be (r,g,b) - elif optname == '-b': - Gl.border = 0 - elif optname == '-c': - Gl.colormap = string.atoi(optarg) - elif optname == '-d': - Gl.debug = Gl.debug + 1 - Gl.warnings = 1 - elif optname == '-F': - Gl.foreground = 1 - elif optname == '-f': - Gl.fullscreen = 1 - elif optname == '-G': - Gl.gong_int = 60*string.atoi(optarg) - elif optname == '-g': - Gl.gong_cmd = optarg - elif optname == '-n': - Gl.nparts = string.atoi(optarg) - elif optname == '-s': - Gl.doublebuffer = 0 - elif optname == '-T': - Gl.title = Gl.name = optarg - elif optname == '-t': - Gl.tzdiff = string.atoi(optarg) - elif optname == '-u': - Gl.update = string.atoi(optarg) - elif optname == '-w': - Gl.warnings = 1 - elif optname == '-C': - Gl.cyan = Gl.colorsubset = 1 - elif optname == '-M': - Gl.magenta = Gl.colorsubset = 1 - elif optname == '-Y': - Gl.yellow = Gl.colorsubset = 1 - elif optname == '-K': - Gl.black = Gl.colorsubset = 1 - else: - print 'Unsupported option', optname - return args - -def usage(exc, msg): - if sys.argv: - progname = os.path.basename(sys.argv[0]) - else: - progname = 'mclock' - # - print progname + ':', - if exc == string.atoi_error: - print 'non-numeric argument:', - print msg - # - print 'usage:', progname, '[options] [hh [mm [ss]]]' - # - print '-A r,g,b : alarm background red,green,blue [255,0,0]' - print '-a cmd : shell command executed when alarm goes off' - print '-B r,g,b : background red,green,blue [0,0,0]' - print ' (-B SCREENBG uses the default screen background)' - print '-b : suppress window border and title' - print '-c cmapid : select explicit colormap' - print '-d : more debug output (implies -F, -w)' - print '-F : run in foreground' - print '-f : use full screen' - print '-G intrvl : interval between chimes in minutes [60]' - print '-g cmd : shell command executed when chimes go off' - print '-s : single buffer mode' - print '-w : print various warnings' - print '-n nparts : number of parts [' + `NPARTS` + ']' - print '-T title : alternate window title [\'' + TITLE + '\']' - print '-t tzdiff : time zone difference [' + `TZDIFF` + ']' - print '-u update : update interval [60]' - print '-CMYK : Cyan, Magenta, Yellow or blacK overlay only' - print 'if hh [mm [ss]] is specified, display that time statically' - print 'on machines with < 12 bitplanes, -s is forced on' - # - sys.exit(2) - -def doit(localtime): - hands = makehands(localtime) - list = makelist(hands) - render(list, hands) - -def makehands(localtime): - localtime = localtime % (12*HOUR) - seconds_hand = MIDN + FULLC - (localtime*60) % FULLC - big_hand = (MIDN + FULLC - (localtime%HOUR)) % FULLC - little_hand = (MIDN + FULLC - ((localtime/12) % HOUR)) % FULLC - return little_hand, big_hand, seconds_hand - -def makelist(hands): - little_hand, big_hand, seconds_hand = hands - total = [] - if Gl.cyan or not Gl.colorsubset: - total = total + makesublist(big_hand, Gl.indices[0]) - if Gl.magenta or not Gl.colorsubset: - total = total + makesublist(little_hand, Gl.indices[1]) - if Gl.yellow or not Gl.colorsubset: - total = total + makesublist(MIDN, Gl.indices[2]) - total.sort() - return total - -def makesublist(first, icolor): - list = [] - alpha = FULLC/Gl.nparts - a = first - alpha/2 - for i in range(Gl.nparts): - angle = (a + i*alpha + FULLC) % FULLC - value = 255*(Gl.nparts-1-i)/(Gl.nparts-1) - list.append(angle, icolor, value) - list.sort() - a, icolor, value = list[0] - if a <> 0: - a, icolor, value = list[len(list)-1] - t = 0, icolor, value - list.insert(0, t) - return list - -def rgb_fg(): - return Gl.fg - # Obsolete code: - if Gl.alarm_on: - return Gl.bg - else: - return Gl.fg - -def rgb_bg(): - return Gl.bg - # Obsolete code: - if Gl.alarm_on: - return Gl.fg - else: - return Gl.bg - -def clearall(): - Gl.c3i(rgb_bg()) - clear() - if Gl.doublebuffer: - swapbuffers() - clear() - -def draw_alarm(color): - frontbuffer(TRUE) - Gl.c3i(color) - pushmatrix() - rotate(-((Gl.alarm_time/12)%3600), 'z') - bgnpolygon() - v2f( 0.00,1.00) - v2f( 0.04,1.05) - v2f(-0.04,1.05) - endpolygon() - popmatrix() - # - pushmatrix() - rotate(-((Gl.alarm_time)%3600), 'z') - bgnpolygon() - v2f( 0.00,1.05) - v2f( 0.07,1.10) - v2f(-0.07,1.10) - endpolygon() - popmatrix() - # - cmov2(-1.06, -1.06) - charstr(string.rjust(`Gl.alarm_time/3600`,2)) - charstr(':') - charstr(string.zfill((Gl.alarm_time/60)%60,2)) - frontbuffer(FALSE) - -def render(list, (little_hand, big_hand, seconds_hand)): - # - if Gl.colormap: - resetindex() - # - if not list: - Gl.c3i((255, 255, 255)) # White - circf(0.0, 0.0, 1.0) - else: - list.append(3600, 0, 255) # Sentinel - # - rgb = [255, 255, 255] - a_prev = 0 - for a, icolor, value in list: - if a <> a_prev: - [r, g, b] = rgb - if Gl.debug > 1: - print rgb, a_prev, a - Gl.c3i((r, g, b)) - arcf(0.0, 0.0, 1.0, a_prev, a) - rgb[icolor] = value - a_prev = a - # - if Gl.black or not Gl.colorsubset: - # - # Draw the hands -- in black - # - Gl.c3i((0, 0, 0)) - # - if Gl.update == 1 and not Gl.iconic: - # Seconds hand is only drawn if we update every second - pushmatrix() - rotate(seconds_hand, 'z') - bgnline() - v2f(0.0, 0.0) - v2f(1.0, 0.0) - endline() - popmatrix() - # - pushmatrix() - rotate(big_hand, 'z') - rectf(0.0, -0.01, 0.97, 0.01) - circf(0.0, 0.0, 0.01) - circf(0.97, 0.0, 0.01) - popmatrix() - # - pushmatrix() - rotate(little_hand, 'z') - rectf(0.04, -0.02, 0.63, 0.02) - circf(0.04, 0.0, 0.02) - circf(0.63, 0.0, 0.02) - popmatrix() - # - # Draw the alarm time, if set or being set - # - if Gl.alarm_set: - draw_alarm(rgb_fg()) - # - if Gl.doublebuffer: swapbuffers() - -def makewindow(): - # - if Gl.debug or Gl.foreground: - foreground() - # - if Gl.fullscreen: - scrwidth, scrheight = getgdesc(GD_XPMAX), getgdesc(GD_YPMAX) - prefposition(0, scrwidth-1, 0, scrheight-1) - else: - keepaspect(1, 1) - prefsize(80, 80) - # - if not Gl.border: - noborder() - wid = winopen(Gl.name) - wintitle(Gl.title) - # - if not Gl.fullscreen: - keepaspect(1, 1) - minsize(10, 10) - maxsize(2000, 2000) - iconsize(66, 66) - winconstraints() - # - nplanes = getplanes() - nmaps = getgdesc(GD_NMMAPS) - if Gl.warnings: - print nplanes, 'color planes,', nmaps, 'color maps' - # - if Gl.doublebuffer and not Gl.colormap and nplanes < 12: - if Gl.warnings: print 'forcing single buffer mode' - Gl.doublebuffer = 0 - # - if Gl.colormap: - if not Gl.colormap: - Gl.colormap = nmaps - 1 - if Gl.warnings: - print 'not enough color planes available', - print 'for RGB mode; forcing colormap mode' - print 'using color map number', Gl.colormap - if not Gl.colorsubset: - needed = 3 - else: - needed = Gl.cyan + Gl.magenta + Gl.yellow - needed = needed*Gl.nparts - if Gl.bg <> (0, 0, 0): - needed = needed+1 - if Gl.fg <> (0, 0, 0): - needed = needed+1 - if Gl.doublebuffer: - if needed > available(nplanes/2): - Gl.doublebuffer = 0 - if Gl.warnings: - print 'not enough colors available', - print 'for double buffer mode;', - print 'forcing single buffer mode' - else: - nplanes = nplanes/2 - if needed > available(nplanes): - # Do this warning always - print 'still not enough colors available;', - print 'parts will be left white' - print '(needed', needed, 'but have only', - print available(nplanes), 'colors available)' - # - if Gl.doublebuffer: - doublebuffer() - gconfig() - # - if Gl.colormap: - Gl.c3i = pseudo_c3i - fixcolormap() - else: - Gl.c3i = c3i - RGBmode() - gconfig() - # - if Gl.fullscreen: - # XXX Should find out true screen size using getgdesc() - ortho2(-1.1*1.280, 1.1*1.280, -1.1*1.024, 1.1*1.024) - else: - ortho2(-1.1, 1.1, -1.1, 1.1) - # - return wid - -def available(nplanes): - return pow(2, nplanes) - 1 # Reserve one pixel for black - -def fixcolormap(): - multimap() - gconfig() - nplanes = getplanes() - if Gl.warnings: - print 'multimap mode has', nplanes, 'color planes' - imap = Gl.colormap - Gl.startindex = pow(2, nplanes) - 1 - Gl.stopindex = 1 - setmap(imap) - mapcolor(0, 0, 0, 0) # Fixed entry for black - if Gl.bg <> (0, 0, 0): - r, g, b = Gl.bg - mapcolor(1, r, g, b) # Fixed entry for Gl.bg - Gl.stopindex = 2 - if Gl.fg <> (0, 0, 0): - r, g, b = Gl.fg - mapcolor(2, r, g, b) # Fixed entry for Gl.fg - Gl.stopindex = 3 - Gl.overflow_seen = 0 - resetindex() - -def resetindex(): - Gl.index = Gl.startindex - -r0g0b0 = (0, 0, 0) - -def pseudo_c3i(rgb): - if rgb == r0g0b0: - index = 0 - elif rgb == Gl.bg: - index = 1 - elif rgb == Gl.fg: - index = 2 - else: - index = definecolor(rgb) - color(index) - -def definecolor(rgb): - index = Gl.index - if index < Gl.stopindex: - if Gl.debug: print 'definecolor hard case', rgb - # First see if we already have this one... - for index in range(Gl.stopindex, Gl.startindex+1): - if rgb == getmcolor(index): - if Gl.debug: print 'return', index - return index - # Don't clobber reserverd colormap entries - if not Gl.overflow_seen: - # Shouldn't happen any more, hence no Gl.warnings test - print 'mclock: out of colormap entries' - Gl.overflow_seen = 1 - return Gl.stopindex - r, g, b = rgb - if Gl.debug > 1: print 'mapcolor', (index, r, g, b) - mapcolor(index, r, g, b) - Gl.index = index - 1 - return index - -# Compute n**i -def pow(n, i): - x = 1 - for j in range(i): x = x*n - return x - -def mouseclick(mouse, updown, x, y): - if updown == 1: - # mouse button came down, start tracking - if Gl.debug: - print 'mouse', mouse, 'down at', x, y - if mouse == 2: - Gl.mouse2down = 1 - mouse2track(x, y) - elif mouse == 3: - Gl.mouse3down = 1 - mouse3track(x, y) - else: - print 'fatal error' - qdevice(MOUSEX) - qdevice(MOUSEY) - return 0 - else: - # mouse button came up, stop tracking - if Gl.debug: - print 'mouse', mouse, 'up at', x, y - unqdevice(MOUSEX) - unqdevice(MOUSEY) - if mouse == 2: - mouse2track(x, y) - Gl.mouse2down = 0 - elif mouse == 3: - mouse3track(x, y) - Gl.mouse3down = 0 - else: - print 'fatal error' - Gl.alarm_set = 1 - return 1 - -def mouse3track(x, y): - # first compute polar coordinates from x and y - cx, cy = Gl.ox + Gl.cx/2, Gl.oy + Gl.cy/2 - x, y = x - cx, y - cy - if (x, y) == (0, 0): return # would cause an exception - minutes = int(30.5 + 30.0*math.atan2(float(-x), float(-y))/pi) - if minutes == 60: minutes = 0 - a,b = Gl.alarm_minutes/15, minutes/15 - if (a,b) == (0,3): - # Moved backward through 12 o'clock: - Gl.alarm_hours = Gl.alarm_hours - 1 - if Gl.alarm_hours < 0: Gl.alarm_hours = Gl.alarm_hours + 24 - if (a,b) == (3,0): - # Moved forward through 12 o'clock: - Gl.alarm_hours = Gl.alarm_hours + 1 - if Gl.alarm_hours >= 24: Gl.alarm_hours = Gl.alarm_hours - 24 - Gl.alarm_minutes = minutes - seconds = Gl.alarm_hours * HOUR + Gl.alarm_minutes * MINUTE - if seconds <> Gl.alarm_time: - draw_alarm(rgb_bg()) - Gl.alarm_time = seconds - draw_alarm(rgb_fg()) - -def mouse2track(x, y): - # first compute polar coordinates from x and y - cx, cy = Gl.ox + Gl.cx/2, Gl.oy + Gl.cy/2 - x, y = x - cx, y - cy - if (x, y) == (0, 0): return # would cause an exception - hours = int(6.5 - float(Gl.alarm_minutes)/60.0 + 6.0*math.atan2(float(-x), float(-y))/pi) - if hours == 12: hours = 0 - if (Gl.alarm_hours,hours) == (0,11): - # Moved backward through midnight: - Gl.alarm_hours = 23 - elif (Gl.alarm_hours,hours) == (12,11): - # Moved backward through noon: - Gl.alarm_hours = 11 - elif (Gl.alarm_hours,hours) == (11,0): - # Moved forward through noon: - Gl.alarm_hours = 12 - elif (Gl.alarm_hours,hours) == (23,0): - # Moved forward through midnight: - Gl.alarm_hours = 0 - elif Gl.alarm_hours < 12: - Gl.alarm_hours = hours - else: - Gl.alarm_hours = hours + 12 - seconds = Gl.alarm_hours * HOUR + Gl.alarm_minutes * MINUTE - if seconds <> Gl.alarm_time: - draw_alarm(rgb_bg()) - Gl.alarm_time = seconds - draw_alarm(rgb_fg()) - -def initmenu(): - Gl.pup = pup = newpup() - addtopup(pup, 'M Clock%t|Alarm On/Off|Seconds Hand On/Off|Quit', 0) - -def handlemenu(): - item = dopup(Gl.pup) - if item == 1: - # Toggle alarm - if Gl.alarm_set: - Gl.alarm_set = 0 - Gl.alarm_on = 0 - else: - Gl.alarm_set = 1 - Gl.change = 1 - clearall() - elif item == 2: - # Toggle Seconds Hand - if Gl.update == 1: - Gl.update = 60 - Gl.timernoise = 60 - else: - Gl.update = 1 - Gl.timernoise = 6 - Gl.change = 1 - elif item == 3: - if Gl.debug: print 'Exit' - sys.exit(0) - -main() diff --git a/Demo/sgi/gl/mixing.py b/Demo/sgi/gl/mixing.py deleted file mode 100755 index 57dea9c865..0000000000 --- a/Demo/sgi/gl/mixing.py +++ /dev/null @@ -1,116 +0,0 @@ -#! /usr/local/bin/python - -# Use Gouraud shading to mix colors. Requires Z-buffer. -# It changes the color assignments so fast that you see white. -# Left button pauses, middle rotates the square. ESC to quit. -# Experiment with a larger window (too slow) or smaller window (really white). - -from GL import * -from gl import * -import DEVICE -from math import * - -# -# tekenvlak : draw a square. with bgnpolygon -# -def tekenvlak (vc) : - bgnpolygon() - #vcarray (vc) - for i in vc : - c3f (i[1]) - v3f (i[0]) - endpolygon() - -# -# tekendoos : draw a box -# -def tekendoos (col) : - v = [(-5.0,0.0,0.0),(0.0,5.0,0.0),(5.0,0.0,0.0),(0.0,-5.0,0.0)] - vc = [(v[0],col[0]),(v[1],col[1]),(v[2],col[2]),(v[3],col[1])] - tekenvlak (vc) - -# -# initialize gl -# -def initgl () : - # - # open window - # - foreground () - keepaspect (1, 1) - prefposition (100, 500, 100, 500) - w = winopen ('PYTHON RGB') - keepaspect (1, 1) - winconstraints() - # - # configure pipeline (2buf, GOURAUD and RGBmode) - # - doublebuffer () - zbuffer (1) - shademodel (GOURAUD) - RGBmode () - gconfig () - # - # set viewing - # - perspective (900, 1, 1.0, 10.0) - polarview (10.0, 0, 0, 0) - # - # ask for the REDRAW and ESCKEY events - # - qdevice(DEVICE.MOUSE2) - qdevice(DEVICE.MOUSE3) - qdevice(DEVICE.REDRAW) - qdevice(DEVICE.ESCKEY) - - -# -# the color black -# -black = 0 -# -# GoForIT : use 2buf to redraw the object 2n times. index i is used as -# the (smoothly changing) rotation angle -# -def GoForIt(i) : - col = [(255.0,0.0,0.0), (0.0,255.0,0.0), (0.0,0.0,255.0)] - twist = 0 - freeze = 1 - while 1 : - if freeze <> 0 : - col[0],col[1],col[2] = col[1],col[2],col[0] - # - # clear z-buffer and clear background to light-blue - # - zclear() - cpack (black) - clear() - # - tekendoos (col) - # - swapbuffers() - # - if qtest() <> 0 : - dev, val = qread() - if dev == DEVICE.ESCKEY : - break - elif dev == DEVICE.REDRAW : - reshapeviewport () - elif dev == DEVICE.MOUSE2 and val <> 0 : - twist = twist + 30 - perspective (900, 1, 1.0, 10.0) - polarview (10.0, 0, 0, twist) - elif dev == DEVICE.MOUSE3 and val <> 0 : - freeze = 1 - freeze - - -# the main program -# -def main () : - initgl () - GoForIt (0) - -# -# exec main -# -main () diff --git a/Demo/sgi/gl/nurbs.py b/Demo/sgi/gl/nurbs.py deleted file mode 100755 index af2039bc22..0000000000 --- a/Demo/sgi/gl/nurbs.py +++ /dev/null @@ -1,171 +0,0 @@ -#! /usr/local/bin/python - -# Rotate a 3D surface created using NURBS. -# -# Press left mouse button to toggle surface trimming. -# Press ESC to quit. -# -# See the GL manual for an explanation of NURBS. - -from gl import * -from GL import * -from DEVICE import * - -TRUE = 1 -FALSE = 0 -ORDER = 4 - -idmat = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1] - -surfknots = [-1, -1, -1, -1, 1, 1, 1, 1] - -def make_ctlpoints(): - c = [] - # - ci = [] - ci.append(-2.5, -3.7, 1.0) - ci.append(-1.5, -3.7, 3.0) - ci.append(1.5, -3.7, -2.5) - ci.append(2.5, -3.7, -0.75) - c.append(ci) - # - ci = [] - ci.append(-2.5, -2.0, 3.0) - ci.append(-1.5, -2.0, 4.0) - ci.append(1.5, -2.0, -3.0) - ci.append(2.5, -2.0, 0.0) - c.append(ci) - # - ci = [] - ci.append(-2.5, 2.0, 1.0) - ci.append(-1.5, 2.0, 0.0) - ci.append(1.5, 2.0, -1.0) - ci.append(2.5, 2.0, 2.0) - c.append(ci) - # - ci = [] - ci.append(-2.5, 2.7, 1.25) - ci.append(-1.5, 2.7, 0.1) - ci.append(1.5, 2.7, -0.6) - ci.append(2.5, 2.7, 0.2) - c.append(ci) - # - return c - -ctlpoints = make_ctlpoints() - -trimknots = [0., 0., 0., 1., 1., 2., 2., 3., 3., 4., 4., 4.] - -def make_trimpoints(): - c = [] - c.append(1.0, 0.0, 1.0) - c.append(1.0, 1.0, 1.0) - c.append(0.0, 2.0, 2.0) - c.append(-1.0, 1.0, 1.0) - c.append(-1.0, 0.0, 1.0) - c.append(-1.0, -1.0, 1.0) - c.append(0.0, -2.0, 2.0) - c.append(1.0, -1.0, 1.0) - c.append(1.0, 0.0, 1.0) - return c - -trimpoints = make_trimpoints() - -def main(): - init_windows() - setup_queue() - make_lights() - init_view() - # - set_scene() - setnurbsproperty( N_ERRORCHECKING, 1.0 ) - setnurbsproperty( N_PIXEL_TOLERANCE, 50.0 ) - trim_flag = 0 - draw_trim_surface(trim_flag) - # - while 1: - while qtest(): - dev, val = qread() - if dev == ESCKEY: - return - elif dev == WINQUIT: - dglclose(-1) # this for DGL only - return - elif dev == REDRAW: - reshapeviewport() - set_scene() - draw_trim_surface(trim_flag) - elif dev == LEFTMOUSE: - if val: - trim_flag = (not trim_flag) - set_scene() - draw_trim_surface(trim_flag) - -def init_windows(): - foreground() - #prefposition(0, 500, 0, 500) - wid = winopen('nurbs') - wintitle('NURBS Surface') - doublebuffer() - RGBmode() - gconfig() - lsetdepth(0x000, 0x7fffff) - zbuffer( TRUE ) - -def setup_queue(): - qdevice(ESCKEY) - qdevice(REDRAW) - qdevice(RIGHTMOUSE) - qdevice(WINQUIT) - qdevice(LEFTMOUSE) #trimming - -def init_view(): - mmode(MPROJECTION) - ortho( -4., 4., -4., 4., -4., 4. ) - # - mmode(MVIEWING) - loadmatrix(idmat) - # - lmbind(MATERIAL, 1) - -def set_scene(): - lmbind(MATERIAL, 0) - RGBcolor(150,150,150) - lmbind(MATERIAL, 1) - clear() - zclear() - # - rotate( 100, 'y' ) - rotate( 100, 'z' ) - -def draw_trim_surface(trim_flag): - bgnsurface() - nurbssurface(surfknots, surfknots, ctlpoints, ORDER, ORDER, N_XYZ) - if trim_flag: - bgntrim() - nurbscurve(trimknots, trimpoints, ORDER-1, N_STW) - endtrim() - endsurface() - swapbuffers() - -def make_lights(): - lmdef(DEFLMODEL,1,[]) - lmdef(DEFLIGHT,1,[]) - # - # define material #1 - # - a = [] - a = a + [EMISSION, 0.0, 0.0, 0.0] - a = a + [AMBIENT, 0.1, 0.1, 0.1] - a = a + [DIFFUSE, 0.6, 0.3, 0.3] - a = a + [SPECULAR, 0.0, 0.6, 0.0] - a = a + [SHININESS, 2.0] - a = a + [LMNULL] - lmdef(DEFMATERIAL, 1, a) - # - # turn on lighting - # - lmbind(LIGHT0, 1) - lmbind(LMODEL, 1) - -main() diff --git a/Demo/sgi/gl/zrgb.py b/Demo/sgi/gl/zrgb.py deleted file mode 100755 index 6561e11b78..0000000000 --- a/Demo/sgi/gl/zrgb.py +++ /dev/null @@ -1,168 +0,0 @@ -#! /usr/local/bin/python - -# zrgb (Requires Z buffer.) -# -# This program demostrates zbuffering 3 intersecting RGB polygons while -# in doublebuffer mode where, movement of the mouse with the LEFTMOUSE -# button depressed will, rotate the 3 polygons. This is done by compound -# rotations allowing continuous screen-oriented rotations. -# -# Press the "Esc" key to exit. - -from gl import * -from GL import * -from DEVICE import * - - -idmat=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1] - -def main() : - # - # old and new mouse position - # - # - mode = 0 - omx = 0 - mx = 0 - omy = 0 - my = 0 - # - objmat=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1] - # - initialize () - # - draw_scene (objmat) - # - while (1) : - # - dev, val = qread() - # - if dev == ESCKEY : - if val : - break - # exit when key is going up, not down - # this avoids the scenario where a window - # underneath this program's window - # would otherwise "eat up" the up- - # event of the Esc key being released - return - # - elif dev == REDRAW : - reshapeviewport() - draw_scene(objmat) - # - elif dev == LEFTMOUSE: - omx = mx - omy = my - if val : - mode = 1 - else : - mode = 0 - elif dev == MOUSEX : - omx = mx - mx = val - #print omx, mx - objmat = update_scene(objmat,mx,my,omx,omy,mode) - # - elif dev == MOUSEY : - omy = my - my = val - #print omy, my - objmat = update_scene(objmat,mx,my,omx,omy,mode) - # - - -def initialize () : - # - foreground () - keepaspect(5, 4) - w = winopen('Zbuffered RGB') - # - doublebuffer() - RGBmode() - gconfig() - zbuffer(1) - lsetdepth(0x0, 0x7FFFFF) - # - qdevice(ESCKEY) - qdevice(LEFTMOUSE) - qdevice(MOUSEX) - qdevice(MOUSEY) - -def update_scene (mat, mx, my, omx, omy, mode) : - # - if mode == 1 : - mat = orient(mat, mx, my, omx, omy) - draw_scene(mat) - return mat - -def orient (mat, mx, my, omx, omy) : - # - # - pushmatrix() - loadmatrix(idmat) - # - if mx - omx : rot (float (mx - omx), 'y') - if omy - my : rot (float (omy - my), 'x') - # - multmatrix(mat) - mat = getmatrix() - # - popmatrix() - # - return mat - -def draw_scene (mat) : - RGBcolor(40, 100, 200) - clear() - zclear() - # - perspective(400, 1.25, 30.0, 60.0) - translate(0.0, 0.0, -40.0) - multmatrix(mat) - # - # skews original view to show all polygons - # - rotate(-580, 'y') - draw_polys() - # - swapbuffers() - -polygon1 = [(-10.0,-10.0,0.0),(10.0,-10.0,0.0),(-10.0,10.0,0.0)] - -polygon2 = [(0.0,-10.0,-10.0),(0.0,-10.0,10.0),(0.0,5.0,-10.0)] - -polygon3 = [(-10.0,6.0,4.0),(-10.0,3.0,4.0),(4.0,-9.0,-10.0),(4.0,-6.0,-10.0)] - -def draw_polys(): - bgnpolygon() - cpack(0x0) - v3f(polygon1[0]) - cpack(0x007F7F7F) - v3f(polygon1[1]) - cpack(0x00FFFFFF) - v3f(polygon1[2]) - endpolygon() - # - bgnpolygon() - cpack(0x0000FFFF) - v3f(polygon2[0]) - cpack(0x007FFF00) - v3f(polygon2[1]) - cpack(0x00FF0000) - v3f(polygon2[2]) - endpolygon() - # - bgnpolygon() - cpack(0x0000FFFF) - v3f(polygon3[0]) - cpack(0x00FF00FF) - v3f(polygon3[1]) - cpack(0x00FF0000) - v3f(polygon3[2]) - cpack(0x00FF00FF) - v3f(polygon3[3]) - endpolygon() - - -main () diff --git a/Demo/sgi/sv/README b/Demo/sgi/sv/README deleted file mode 100644 index 38e51407fe..0000000000 --- a/Demo/sgi/sv/README +++ /dev/null @@ -1,23 +0,0 @@ -Demo programs for the SGI Video library for the Indigo (IRIX 4.0.5). - -These are more-or-less literal translations of the C programs from the -Indigo Video Programming Guide, by Sjoerd Mullender, with some changes -by Guido. - -Note that none of the example programs save any data to a file, -although this would be easy to do (e.g. individual grabbed frames -could be written as SGI image files using the imgfile module). - -We have written a Python program to record live video to file (within -the limits of the Indigo video board), and a suite of programs to -manipulate and display such files. At the moment we don't distribute -these programs, since the file format is, eh..., weird, to say the -least. However, if you are really interested we can mail you the -source. - -Also note that we haven't tried using video *output* yet. - -simpleinput.py Live video in a resizable window -rgbgrab.py Grab still frames -contcapt.py Continuous capturing -burstcapt.py Burst capturing diff --git a/Demo/sgi/sv/burstcapt.py b/Demo/sgi/sv/burstcapt.py deleted file mode 100755 index ce1e579f36..0000000000 --- a/Demo/sgi/sv/burstcapt.py +++ /dev/null @@ -1,52 +0,0 @@ -import sys -import sv, SV -import gl, GL, DEVICE - -def main(): - format = SV.RGB8_FRAMES - requestedwidth = SV.PAL_XMAX - queuesize = 30 - if sys.argv[1:]: - queuesize = eval(sys.argv[1]) - - v = sv.OpenVideo() - svci = (format, requestedwidth, 0, queuesize, 0) - - go = raw_input('Press return to capture ' + `queuesize` + ' frames: ') - result = v.CaptureBurst(svci) - svci, buffer, bitvec = result -## svci, buffer = result # XXX If bit vector not yet implemented - - print 'Captured', svci[3], 'frames, i.e.', len(buffer)/1024, 'K bytes' - - w, h = svci[1:3] - framesize = w * h - - gl.prefposition(300, 300+w-1, 100, 100+h-1) - gl.foreground() - win = gl.winopen('Burst Capture') - gl.RGBmode() - gl.gconfig() - gl.qdevice(DEVICE.LEFTMOUSE) - gl.qdevice(DEVICE.ESCKEY) - - print 'Click left mouse for next frame' - - for i in range(svci[3]): - inverted_frame = sv.RGB8toRGB32(1, \ - buffer[i*framesize:(i+1)*framesize], w, h) - gl.lrectwrite(0, 0, w-1, h-1, inverted_frame) - while 1: - dev, val = gl.qread() - if dev == DEVICE.LEFTMOUSE and val == 1: - break - if dev == DEVICE.REDRAW: - gl.lrectwrite(0, 0, w-1, h-1, inverted_frame) - if dev == DEVICE.ESCKEY: - v.CloseVideo() - gl.winclose(win) - return - v.CloseVideo() - gl.winclose(win) - -main() diff --git a/Demo/sgi/sv/contcapt.py b/Demo/sgi/sv/contcapt.py deleted file mode 100755 index 6c0a0003bb..0000000000 --- a/Demo/sgi/sv/contcapt.py +++ /dev/null @@ -1,107 +0,0 @@ -import sys -import sv, SV -import gl, GL, DEVICE - -def main(): - format = SV.RGB8_FRAMES - framerate = 25 - queuesize = 16 - samplingrate = 2 - - v = sv.OpenVideo() - # Determine maximum window size based on signal standard - param = [SV.BROADCAST, 0] - v.GetParam(param) - if param[1] == SV.PAL: - width = SV.PAL_XMAX - height = SV.PAL_YMAX - framefreq = 25 - else: - width = SV.NTSC_XMAX - height = SV.NTSC_YMAX - framefreq = 30 - - # Allow resizing window if capturing RGB frames, which can be scaled - if format == SV.RGB8_FRAMES: - gl.keepaspect(width, height) - gl.maxsize(width, height) - gl.stepunit(8, 6) - gl.minsize(120, 90) - else: - if format == SV.YUV411_FRAMES_AND_BLANKING_BUFFER: - height = height + SV.BLANKING_BUFFER_SIZE - gl.prefposition(300, 300+width-1, 100, 100+height-1) - - # Open the window - gl.foreground() - win = gl.winopen('Continuous Capture') - gl.RGBmode() - gl.gconfig() - if format == SV.RGB8_FRAMES: - width, height = gl.getsize() - gl.pixmode(GL.PM_SIZE, 8) - else: - gl.pixmode(GL.PM_SIZE, 32) - - svci = (format, width, height, queuesize, samplingrate) - [svci] - - svci = v.InitContinuousCapture(svci) - width, height = svci[1:3] - [svci] - - hz = gl.getgdesc(GL.GD_TIMERHZ) - gl.noise(DEVICE.TIMER0, hz / framerate) - gl.qdevice(DEVICE.TIMER0) - gl.qdevice(DEVICE.WINQUIT) - gl.qdevice(DEVICE.WINSHUT) - gl.qdevice(DEVICE.ESCKEY) - - ndisplayed = 0 - lastfieldID = 0 - - while 1: - dev, val = gl.qread() - if dev == DEVICE.REDRAW: - oldw = width - oldh = height - width, height = gl.getsize() - if oldw != width or oldh != height: - v.EndContinuousCapture() - gl.viewport(0, width-1, 0, height-1) - svci = (svci[0], width, height) + svci[3:] - svci = v.InitContinuousCapture(svci) - width, height = svci[1:3] - [svci] - if ndisplayed: - print 'lost', - print fieldID/(svci[4]*2) - ndisplayed, - print 'frames' - ndisplayed = 0 - elif dev == DEVICE.TIMER0: - try: - captureData, fieldID = v.GetCaptureData() - except sv.error, val: - if val <> 'no data available': - print val - continue - if fieldID - lastfieldID <> 2*samplingrate: - print lastfieldID, fieldID - lastfieldID = fieldID - if svci[0] == SV.RGB8_FRAMES: - rgbbuf = captureData.InterleaveFields(1) - else: - rgbbuf = captureData.YUVtoRGB(1) - captureData.UnlockCaptureData() - gl.lrectwrite(0, 0, width-1, height-1, rgbbuf) - ndisplayed = ndisplayed + 1 - elif dev in (DEVICE.ESCKEY, DEVICE.WINQUIT, DEVICE.WINSHUT): - v.EndContinuousCapture() - v.CloseVideo() - gl.winclose(win) - print fieldID, ndisplayed, svci[4] - print 'lost', fieldID/(svci[4]*2) - ndisplayed, - print 'frames' - return - -main() diff --git a/Demo/sgi/sv/rgbgrab.py b/Demo/sgi/sv/rgbgrab.py deleted file mode 100755 index 8013a531f4..0000000000 --- a/Demo/sgi/sv/rgbgrab.py +++ /dev/null @@ -1,81 +0,0 @@ -import sys -import sv, SV -import gl, GL, DEVICE -import time - -def main(): - v = sv.OpenVideo() - # Determine maximum window size based on signal standard - param = [SV.BROADCAST, 0] - v.GetParam(param) - if param[1] == SV.PAL: - width = SV.PAL_XMAX - height = SV.PAL_YMAX - elif param[1] == SV.NTSC: - width = SV.NTSC_XMAX - height = SV.NTSC_YMAX - else: - print 'Unknown video standard', param[1] - sys.exit(1) - - # Initially all windows are half size - grabwidth, grabheight = width/2, height/2 - - # Open still window - gl.foreground() - gl.prefsize(grabwidth, grabheight) - still_win = gl.winopen('Grabbed frame') - gl.keepaspect(width, height) - gl.maxsize(width, height) - gl.winconstraints() - gl.RGBmode() - gl.gconfig() - gl.clear() - gl.pixmode(GL.PM_SIZE, 8) - - # Open live window - gl.foreground() - gl.prefsize(grabwidth, grabheight) - live_win = gl.winopen('Live video') - gl.keepaspect(width, height) - gl.maxsize(width, height) - gl.winconstraints() - - # Bind live video - v.SetSize(gl.getsize()) - v.BindGLWindow(live_win, SV.IN_REPLACE) - - print 'Use leftmouse to grab frame' - - gl.qdevice(DEVICE.LEFTMOUSE) - gl.qdevice(DEVICE.WINQUIT) - gl.qdevice(DEVICE.WINSHUT) - gl.qdevice(DEVICE.ESCKEY) - frame = None - while 1: - dev, val = gl.qread() - if dev == DEVICE.LEFTMOUSE and val == 0: - w, h, fields = v.CaptureOneFrame(SV.RGB8_FRAMES, \ - grabwidth, grabheight) - frame = sv.InterleaveFields(1, fields, w, h) - gl.winset(still_win) - gl.lrectwrite(0, 0, w - 1, h - 1, frame) - gl.winset(live_win) - if dev in (DEVICE.ESCKEY, DEVICE.WINQUIT, DEVICE.WINSHUT): - v.CloseVideo() - gl.winclose(live_win) - gl.winclose(still_win) - break - if dev == DEVICE.REDRAW and val == still_win: - gl.winset(still_win) - gl.reshapeviewport() - gl.clear() - grabwidth, grabheight = gl.getsize() - if frame: - gl.lrectwrite(0, 0, w - 1, h - 1, frame) - gl.winset(live_win) - if dev == DEVICE.REDRAW and val == live_win: - v.SetSize(gl.getsize()) - v.BindGLWindow(live_win, SV.IN_REPLACE) - -main() diff --git a/Demo/sgi/sv/simpleinput.py b/Demo/sgi/sv/simpleinput.py deleted file mode 100755 index 97b75fafb0..0000000000 --- a/Demo/sgi/sv/simpleinput.py +++ /dev/null @@ -1,22 +0,0 @@ -import sv, SV -import gl, DEVICE - -def main(): - gl.foreground() - gl.prefsize(SV.PAL_XMAX, SV.PAL_YMAX) - win = gl.winopen('video test') - v = sv.OpenVideo() - params = [SV.VIDEO_MODE, SV.COMP, SV.BROADCAST, SV.PAL] - v.SetParam(params) - v.BindGLWindow(win, SV.IN_REPLACE) - gl.qdevice(DEVICE.ESCKEY) - gl.qdevice(DEVICE.WINQUIT) - gl.qdevice(DEVICE.WINSHUT) - while 1: - dev, val = gl.qread() - if dev in (DEVICE.ESCKEY, DEVICE.WINSHUT, DEVICE.WINQUIT): - v.CloseVideo() - gl.winclose(win) - return - -main() diff --git a/Demo/sgi/video/.cvsignore b/Demo/sgi/video/.cvsignore deleted file mode 100755 index fb9700bf02..0000000000 --- a/Demo/sgi/video/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -i2v -v2i diff --git a/Demo/sgi/video/DisplayVideoIn.py b/Demo/sgi/video/DisplayVideoIn.py deleted file mode 100755 index 6dbc7bcc38..0000000000 --- a/Demo/sgi/video/DisplayVideoIn.py +++ /dev/null @@ -1,99 +0,0 @@ -# Live video input from display class. - -import gl -import GL - -# The live video input class. -# Only instantiate this if have_video is true! - -class DisplayVideoIn: - - # Initialize an instance. Arguments: - # vw, vh: size of the video window data to be captured. - # position defaults to 0, 0 but can be set later - def __init__(self, pktmax, vw, vh, type): - self.pktmax = pktmax - self.realwidth, self.realheight = vw, vh - if type <> 'rgb': - raise 'Incorrent video data type', type - self.type = type - self.width = vw - self.height = vh - # - # Open dummy window - # - gl.foreground() - gl.noport() - self.wid = gl.winopen('DisplayVideoIn') - - self.x0 = 0 - self.x1 = self.x0 + self.width - 1 - self.y0 = 0 - self.y1 = self.y0 + self.height - 1 - # Compute # full lines per packet - self.lpp = pktmax / self.linewidth() - if self.lpp <= 0: - raise 'No lines in packet', self.linewidth() - self.pktsize = self.lpp*self.linewidth() - self.data = None - self.old_data = None - self.dataoffset = 0 - self.lpos = 0 - self.hints = 0 - - # Change the size of the video being displayed. - - def resizevideo(self, vw, vh): - self.width = vw - self.height = vh - self.x1 = self.x0 + self.width - 1 - self.y1 = self.y0 + self.height - 1 - - def positionvideo(self, x, y): - self.x0 = x - self.y0 = y - self.x1 = self.x0 + self.width - 1 - self.y1 = self.y0 + self.height - 1 - - # Remove an instance. - # This turns off continuous capture. - - def close(self): - gl.winclose(self.wid) - - # Get the length in bytes of a video line - def linewidth(self): - return self.width*4 - - # Get the next video packet. - # This returns (lpos, data) where: - # - lpos is the line position - # - data is a piece of data - # The dimensions of data are: - # - pixel depth = 1 byte - # - scan line width = self.width (the vw argument to __init__()) - # - number of scan lines = self.lpp (PKTMAX / vw) - - def getnextpacket(self): - if not self.data or self.dataoffset >= len(self.data): - self.old_data = self.data - self.data = gl.readdisplay(self.x0, self.y0, \ - self.x1, self.y1, self.hints) - self.dataoffset = 0 - self.lpos = 0 - data = self.data[self.dataoffset:self.dataoffset+self.pktsize] - while self.old_data and \ - self.dataoffset+self.pktsize < len(self.data): - odata = self.old_data[self.dataoffset: \ - self.dataoffset+self.pktsize] - if odata <> data: - break - print 'skip', self.lpos - self.lpos = self.lpos + self.lpp - self.dataoffset = self.dataoffset + self.pktsize - data = self.data[self.dataoffset:\ - self.dataoffset+self.pktsize] - lpos = self.lpos - self.dataoffset = self.dataoffset + self.pktsize - self.lpos = self.lpos + self.lpp - return lpos, data diff --git a/Demo/sgi/video/Dsend.py b/Demo/sgi/video/Dsend.py deleted file mode 100755 index c4ed84214e..0000000000 --- a/Demo/sgi/video/Dsend.py +++ /dev/null @@ -1,188 +0,0 @@ -#!/ufs/guido/bin/sgi/python - -# Send live video UDP packets. -# Usage: Vsend [-b] [-h height] [-p port] [-s size] [-t ttl] [-w width] -# [host] .. - -import sys -import time -import struct -import string -import math -from socket import * -from SOCKET import * -import gl, GL, DEVICE -sys.path.append('/ufs/guido/src/video') -import DisplayVideoIn -import LiveVideoOut -import SV -import getopt -from IN import * - -from senddefs import * - -def usage(msg): - print msg - print 'usage: Vsend [-b] [-h height] [-p port] [-s size] [-t ttl] [-c type] [-m]', - print '[-w width] [host] ...' - print '-b : broadcast on local net' - print '-h height : window height (default ' + `DEFHEIGHT` + ')' - print '-p port : port to use (default ' + `DEFPORT` + ')' - print '-t ttl : time-to-live (multicast only; default 1)' - print '-s size : max packet size (default ' + `DEFPKTMAX` + ')' - print '-S size : use this packet size/window size' - print '-w width : window width (default ' + `DEFWIDTH` + ')' - print '-v : print packet rate' - print '-x xpos : set x position' - print '-y ypos : set y position' - print '[host] ...: host(s) to send to (default multicast to ' + \ - DEFMCAST + ')' - sys.exit(2) - - -def main(): - sys.stdout = sys.stderr - - hosts = [] - port = DEFPORT - ttl = -1 - pktmax = DEFPKTMAX - width = DEFWIDTH - height = DEFHEIGHT - vtype = 'rgb' - verbose = 0 - xpos = ypos = 0 - - try: - opts, args = getopt.getopt(sys.argv[1:], 'bh:p:s:S:t:w:vx:y:') - except getopt.error, msg: - usage(msg) - - try: - for opt, optarg in opts: - if opt == '-p': - port = string.atoi(optarg) - if opt == '-b': - host = '' - if opt == '-t': - ttl = string.atoi(optarg) - if opt == '-S': - pktmax = string.atoi(optarg) - vidmax = SV.PAL_XMAX*SV.PAL_YMAX - if vidmax <= pktmax: - width = SV.PAL_XMAX - height = SV.PAL_YMAX - pktmax = vidmax - else: - factor = float(vidmax)/float(pktmax) - factor = math.sqrt(factor) - width = int(SV.PAL_XMAX/factor)-7 - height = int(SV.PAL_YMAX/factor)-5 - print 'video:',width,'x',height, - print 'pktsize',width*height,'..', - print pktmax - if opt == '-s': - pktmax = string.atoi(optarg) - if opt == '-w': - width = string.atoi(optarg) - if opt == '-h': - height = string.atoi(optarg) - if opt == '-c': - vtype = optarg - if opt == '-v': - verbose = 1 - if opt == '-x': - xpos = string.atoi(optarg) - if opt == '-y': - ypos = string.atoi(optarg) - except string.atoi_error, msg: - usage('bad integer: ' + msg) - - for host in args: - hosts.append(gethostbyname(host)) - - if not hosts: - hosts.append(gethostbyname(DEFMCAST)) - - gl.foreground() - gl.prefsize(width, height) - gl.stepunit(8, 6) - wid = gl.winopen('Vsend') - gl.keepaspect(width, height) - gl.stepunit(8, 6) - gl.maxsize(SV.PAL_XMAX, SV.PAL_YMAX) - gl.winconstraints() - gl.qdevice(DEVICE.ESCKEY) - gl.qdevice(DEVICE.WINSHUT) - gl.qdevice(DEVICE.WINQUIT) - gl.qdevice(DEVICE.WINFREEZE) - gl.qdevice(DEVICE.WINTHAW) - width, height = gl.getsize() - - lvo = LiveVideoOut.LiveVideoOut(wid, width, height, vtype) - - lvi = DisplayVideoIn.DisplayVideoIn(pktmax, width, height, vtype) - - if xpos or ypos: - lvi.positionvideo(xpos, ypos) - - s = socket(AF_INET, SOCK_DGRAM) - s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1) - if ttl >= 0: - s.setsockopt(IPPROTO_IP, IP_MULTICAST_TTL, chr(ttl)) - - frozen = 0 - - lasttime = int(time.time()) - nframe = 0 - while 1: - - if gl.qtest(): - dev, val = gl.qread() - if dev in (DEVICE.ESCKEY, \ - DEVICE.WINSHUT, DEVICE.WINQUIT): - break - if dev == DEVICE.WINFREEZE: - frozen = 1 - if dev == DEVICE.WINTHAW: - frozen = 0 - if dev == DEVICE.REDRAW: - w, h = gl.getsize() - x, y = gl.getorigin() - if (w, h) <> (width, height): - width, height = w, h - lvi.resizevideo(width, height) - lvo.resizevideo(width, height) - - rv = lvi.getnextpacket() - if not rv: - time.millisleep(10) - continue - - pos, data = rv - print pos, len(data) # DBG - - if not frozen: - lvo.putnextpacket(pos, data) - - hdr = struct.pack('hhh', pos, width, height) - for host in hosts: - try: - # print len(hdr+data) # DBG - s.sendto(hdr + data, (host, port)) - except error, msg: # really socket.error - if msg[0] <> 121: # no buffer space available - raise error, msg # re-raise it - print 'Warning:', msg[1] - if pos == 0 and verbose: - nframe = nframe+1 - if int(time.time()) <> lasttime: - print nframe / (time.time()-lasttime), 'fps' - nframe = 0 - lasttime = int(time.time()) - - lvi.close() - lvo.close() - - -main() diff --git a/Demo/sgi/video/IN.py b/Demo/sgi/video/IN.py deleted file mode 100755 index ffc2852596..0000000000 --- a/Demo/sgi/video/IN.py +++ /dev/null @@ -1,54 +0,0 @@ -IPPROTO_IP = 0 -IPPROTO_ICMP = 1 -IPPROTO_IGMP = 2 -IPPROTO_GGP = 3 -IPPROTO_TCP = 6 -IPPROTO_EGP = 8 -IPPROTO_PUP = 12 -IPPROTO_UDP = 17 -IPPROTO_IDP = 22 -IPPROTO_TP = 29 -IPPROTO_XTP = 36 -IPPROTO_EON = 80 -IPPROTO_RAW = 255 -IPPROTO_MAX = 256 -IPPORT_RESERVED = 1024 -IPPORT_USERRESERVED = 5000 -IN_CLASSA_NET = 0xff000000 -IN_CLASSA_NSHIFT = 24 -IN_CLASSA_HOST = 0x00ffffff -IN_CLASSA_MAX = 128 -IN_CLASSB_NET = 0xffff0000 -IN_CLASSB_NSHIFT = 16 -IN_CLASSB_HOST = 0x0000ffff -IN_CLASSB_MAX = 65536 -IN_CLASSC_NET = 0xffffff00 -IN_CLASSC_NSHIFT = 8 -IN_CLASSC_HOST = 0x000000ff -IN_CLASSD_NET = 0xf0000000 -IN_CLASSD_NSHIFT = 28 -IN_CLASSD_HOST = 0x0fffffff -INADDR_ANY = 0x00000000 -INADDR_BROADCAST = 0xffffffff -INADDR_LOOPBACK = 0x7F000001 -INADDR_UNSPEC_GROUP = 0xe0000000 -INADDR_ALLHOSTS_GROUP = 0xe0000001 -INADDR_MAX_LOCAL_GROUP = 0xe00000ff -INADDR_NONE = 0xffffffff -IN_LOOPBACKNET = 127 -IP_OPTIONS = 1 -IP_HDRINCL = 7 -IP_TOS = 8 -IP_TTL = 9 -IP_RECVOPTS = 10 -IP_RECVRETOPTS = 11 -IP_RECVDSTADDR = 12 -IP_RETOPTS = 13 -IP_MULTICAST_IF = 2 -IP_MULTICAST_TTL = 3 -IP_MULTICAST_LOOP = 4 -IP_ADD_MEMBERSHIP = 5 -IP_DROP_MEMBERSHIP = 6 -IP_DEFAULT_MULTICAST_TTL = 1 -IP_DEFAULT_MULTICAST_LOOP = 1 -IP_MAX_MEMBERSHIPS = 20 diff --git a/Demo/sgi/video/LiveVideoIn.py b/Demo/sgi/video/LiveVideoIn.py deleted file mode 100755 index 661ea738b2..0000000000 --- a/Demo/sgi/video/LiveVideoIn.py +++ /dev/null @@ -1,139 +0,0 @@ -# Live video input class. -# Note that importing this module attempts to initialize video. - - -# Check if video is available. -# There are three reasons for failure here: -# (1) this version of Python may not have the sv or imageop modules; -# (2) this machine may not have a video board; -# (3) initializing the video board may fail for another reason. -# The global variable have_video is set to true iff we reall do have video. - -try: - import sv - import SV - import imageop - try: - v = sv.OpenVideo() - have_video = 1 - except sv.error: - have_video = 0 -except ImportError: - have_video = 0 - - -# The live video input class. -# Only instantiate this if have_video is true! - -class LiveVideoIn: - - # Initialize an instance. Arguments: - # vw, vh: size of the video window data to be captured. - # For some reason, vw MUST be a multiple of 4. - # Note that the data has to be cropped unless vw and vh are - # just right for the video board (vw:vh == 4:3 and vh even). - - def __init__(self, pktmax, vw, vh, type): - if not have_video: - raise RuntimeError, 'no video available' - if vw % 4 != 0: - raise ValueError, 'vw must be a multiple of 4' - self.pktmax = pktmax - realvw = vh*SV.PAL_XMAX/SV.PAL_YMAX - if realvw < vw: - realvw = vw - self.realwidth, self.realheight = v.QuerySize(realvw, vh) - if not type in ('rgb8', 'grey', 'mono', 'grey2', 'grey4'): - raise 'Incorrent video data type', type - self.type = type - if type in ('grey', 'grey4', 'grey2', 'mono'): - v.SetParam([SV.COLOR, SV.MONO, SV.INPUT_BYPASS, 1]) - else: - v.SetParam([SV.COLOR, SV.DEFAULT_COLOR, \ - SV.INPUT_BYPASS, 0]) - # Initialize capture - (mode, self.realwidth, self.realheight, qsize, rate) = \ - v.InitContinuousCapture(SV.RGB8_FRAMES, \ - self.realwidth, self.realheight, 1, 2) - self.width = vw - self.height = vh - self.x0 = (self.realwidth-self.width)/2 - self.x1 = self.x0 + self.width - 1 - self.y0 = (self.realheight-self.height)/2 - self.y1 = self.y0 + self.height - 1 - # Compute # full lines per packet - self.lpp = pktmax / self.linewidth() - self.pktsize = self.lpp*self.linewidth() - self.data = None - self.dataoffset = 0 - self.lpos = 0 - self.justright = (self.realwidth == self.width and \ - self.realheight == self.height) -## if not self.justright: -## print 'Want:', self.width, 'x', self.height, -## print '; grab:', self.realwidth, 'x', self.realheight - - # Change the size of the video being displayed. - - def resizevideo(self, vw, vh): - self.close() - self.__init__(self.pktmax, vw, vh, self.type) - - # Remove an instance. - # This turns off continuous capture. - - def close(self): - v.EndContinuousCapture() - - # Get the length in bytes of a video line - def linewidth(self): - if self.type == 'mono': - return (self.width+7)/8 - elif self.type == 'grey2': - return (self.width+3)/4 - elif self.type == 'grey4': - return (self.width+1)/2 - else: - return self.width - - # Get the next video packet. - # This returns (lpos, data) where: - # - lpos is the line position - # - data is a piece of data - # The dimensions of data are: - # - pixel depth = 1 byte - # - scan line width = self.width (the vw argument to __init__()) - # - number of scan lines = self.lpp (PKTMAX / vw) - - def getnextpacket(self): - if not self.data or self.dataoffset >= len(self.data): - try: - cd, id = v.GetCaptureData() - except sv.error: - return None - data = cd.InterleaveFields(1) - cd.UnlockCaptureData() - if self.justright: - self.data = data - else: - self.data = imageop.crop(data, 1, \ - self.realwidth, \ - self.realheight, \ - self.x0, self.y0, \ - self.x1, self.y1) - self.lpos = 0 - self.dataoffset = 0 - if self.type == 'mono': - self.data = imageop.dither2mono(self.data, \ - self.width, self.height) - elif self.type == 'grey2': - self.data = imageop.dither2grey2(self.data, \ - self.width, self.height) - elif self.type == 'grey4': - self.data = imageop.grey2grey4(self.data, \ - self.width, self.height) - data = self.data[self.dataoffset:self.dataoffset+self.pktsize] - lpos = self.lpos - self.dataoffset = self.dataoffset + self.pktsize - self.lpos = self.lpos + self.lpp - return lpos, data diff --git a/Demo/sgi/video/LiveVideoOut.py b/Demo/sgi/video/LiveVideoOut.py deleted file mode 100755 index 6ee1846d41..0000000000 --- a/Demo/sgi/video/LiveVideoOut.py +++ /dev/null @@ -1,130 +0,0 @@ -# Live video output (display video on the screen, presumably from the net) - -import gl -from VFile import Displayer - - -# Video output (displayer) class. - -class LiveVideoOut: - - # Call this to initialize things. Arguments: - # wid: the window id where the video is to be displayed (centered) - # vw, vh: size of the video image to be displayed - - def __init__(self, wid, vw, vh, type): - ##print 'Init', wid, xywh - ##print 'video', vw, vw - self.vw = vw - self.vh = vh - self.disp = Displayer() - if not type in ('rgb', 'rgb8', 'grey', 'mono', 'grey2', \ - 'grey4'): - raise 'Incorrent live video output type', type - if type == 'rgb': - info = (type, vw, vh, 0, 32, 0, 0, 0, 0) - else: - info = (type, vw, vh, 1, 8, 0, 0, 0, 0) - self.disp.setinfo(info) - self.wid = wid - oldwid = gl.winget() - gl.winset(wid) - self.disp.initcolormap() - self.reshapewindow() - gl.winset(oldwid) - - # Call this in response to every REDRAW event for the window - # or if the window size has changed for other reasons. - - def reshapewindow(self): - oldwid = gl.winget() - gl.winset(self.wid) - gl.reshapeviewport() - w, h = gl.getsize() - self.disp.xorigin = (w-self.vw)/2 - self.disp.yorigin = (h-self.vh)/2 - self.disp.clear() - gl.winset(oldwid) - - # Call this to change the size of the video images being displayed. - # Implies reshapewindow(). - - def resizevideo(self, vw, vh): - self.vw, self.vh = vw, vh - self.disp.setsize(vw, vh) - self.reshapewindow() - - # Return the number of bytes in one video line - def linewidth(self): - if self.disp.format == 'rgb': - return self.vw*4 - if self.disp.format == 'mono': - return (self.vw+7)/8 - elif self.disp.format == 'grey2': - return (self.vw+3)/4 - elif self.disp.format == 'grey4': - return (self.vw+1)/2 - else: - return self.vw - - # Call this to display the next video packet. Arguments: - # pos: line number where the packet begins - # data: image data of the packet - # (these correspond directly to the return values from - # LiveVideoIn.getnextpacket()). - - def putnextpacket(self, pos, data): - nline = len(data)/self.linewidth() - if nline*self.linewidth() <> len(data): - print 'Incorrect-sized video fragment ignored' - return - oldwid = gl.winget() - gl.winset(self.wid) - self.disp.showpartframe(data, None, (0, pos, self.vw, nline)) - gl.winset(oldwid) - - # Call this to close the window. - - def close(self): - pass - - # Call this to set optional mirroring of video - def setmirror(self, mirrored): - f, w, h, pf, c0, c1, c2, o, cp = self.disp.getinfo() - if type(pf) == type(()): - xpf, ypf = pf - else: - xpf = ypf = pf - xpf = abs(xpf) - if mirrored: - xpf = -xpf - info = (f, w, h, (xpf, ypf), c0, c1, c2, o, cp) - self.disp.setinfo(info) - self.disp.initcolormap() - self.disp.clear() - -# -# This derived class has one difference with the base class: the video is -# not displayed until an entire image has been gotten -# -class LiveVideoOutSlow(LiveVideoOut): - - # Reshapewindow - Realloc buffer. - # (is also called by __init__() indirectly) - - def reshapewindow(self): - LiveVideoOut.reshapewindow(self) - self.buffer = '\0'*self.linewidth()*self.vh - self.isbuffered = [] - - # putnextpacket - buffer incoming data until a complete - # image has been received - - def putnextpacket(self, pos, data): - if pos in self.isbuffered or pos == 0: - LiveVideoOut.putnextpacket(self, 0, self.buffer) - self.isbuffered = [] - self.isbuffered.append(pos) - bpos = pos * self.linewidth() - epos = bpos + len(data) - self.buffer = self.buffer[:bpos] + data + self.buffer[epos:] diff --git a/Demo/sgi/video/Makefile b/Demo/sgi/video/Makefile deleted file mode 100755 index 266ea52587..0000000000 --- a/Demo/sgi/video/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: v2i i2v - -v2i: v2i.o - $(CC) v2i.o -limage -o v2i - -i2v: i2v.o - $(CC) i2v.o -limage -o i2v diff --git a/Demo/sgi/video/OldVcopy.py b/Demo/sgi/video/OldVcopy.py deleted file mode 100755 index 61461f40a6..0000000000 --- a/Demo/sgi/video/OldVcopy.py +++ /dev/null @@ -1,148 +0,0 @@ -#! /ufs/guido/bin/sgi/python - -# Copy a video file, interactively, frame-by-frame. - -import sys -import getopt -from gl import * -from DEVICE import * -import VFile -import VGrabber -import string -import imageop - -def report(time, iframe): - print 'Frame', iframe, ': t =', time - -def usage(): - sys.stderr.write('usage: Vcopy [-t type] [-m treshold] [-a] infile outfile\n') - sys.stderr.write('-t Convert to other type\n') - sys.stderr.write('-a Automatic\n') - sys.stderr.write('-m Convert grey to mono with treshold\n') - sys.stderr.write('-d Convert grey to mono with dithering\n') - sys.exit(2) - -def help(): - print 'Command summary:' - print 'n get next image from input' - print 'w write current image to output' - -class GrabbingVoutFile(VFile.VoutFile, VGrabber.VGrabber): - pass - -def main(): - foreground() - try: - opts, args = getopt.getopt(sys.argv[1:], 't:am:d') - except getopt.error, msg: - print msg - usage() - if len(args) <> 2: - usage() - [ifile, ofile] = args - print 'open film ', ifile - ifilm = VFile.VinFile(ifile) - print 'open output ', ofile - ofilm = GrabbingVoutFile(ofile) - - ofilm.setinfo(ifilm.getinfo()) - - use_grabber = 0 - continuous = 0 - tomono = 0 - tomonodither = 0 - for o, a in opts: - if o == '-t': - ofilm.format = a - use_grabber = 1 - if o == '-a': - continuous = 1 - if o == '-m': - if ifilm.format <> 'grey': - print '-m only supported for greyscale' - sys.exit(1) - tomono = 1 - treshold = string.atoi(a) - ofilm.format = 'mono' - if o == '-d': - if ifilm.format <> 'grey': - print '-m only supported for greyscale' - sys.exit(1) - tomonodither = 1 - ofilm.format = 'mono' - - ofilm.writeheader() - # - prefsize(ifilm.width, ifilm.height) - w = winopen(ifile) - qdevice(KEYBD) - qdevice(ESCKEY) - qdevice(WINQUIT) - qdevice(WINSHUT) - print 'qdevice calls done' - # - help() - # - time, data, cdata = ifilm.getnextframe() - ifilm.showframe(data, cdata) - iframe = 1 - report(time, iframe) - # - while 1: - if continuous: - dev = KEYBD - else: - dev, val = qread() - if dev in (ESCKEY, WINQUIT, WINSHUT): - break - if dev == REDRAW: - reshapeviewport() - elif dev == KEYBD: - if continuous: - c = '0' - else: - c = chr(val) - #XXX Debug - if c == 'R': - c3i(255,0,0) - clear() - if c == 'G': - c3i(0,255,0) - clear() - if c == 'B': - c3i(0,0,255) - clear() - if c == 'w' or continuous: - if use_grabber: - try: - data, cdata = ofilm.grabframe() - except VFile.Error, msg: - print msg - break - if tomono: - data = imageop.grey2mono(data, \ - ifilm.width, ifilm.height, \ - treshold) - if tomonodither: - data = imageop.dither2mono(data, \ - ifilm.width, ifilm.height) - ofilm.writeframe(time, data, cdata) - print 'Frame', iframe, 'written.' - if c == 'n' or continuous: - try: - time,data,cdata = ifilm.getnextframe() - ifilm.showframe(data, cdata) - iframe = iframe+1 - report(time, iframe) - except EOFError: - print 'EOF' - if continuous: - break - ringbell() - elif dev == INPUTCHANGE: - pass - else: - print '(dev, val) =', (dev, val) - ofilm.close() - -main() diff --git a/Demo/sgi/video/README b/Demo/sgi/video/README deleted file mode 100644 index 6abe698795..0000000000 --- a/Demo/sgi/video/README +++ /dev/null @@ -1,113 +0,0 @@ -CMIF video tools -================ - -This directory contains Python and C programs to manipulate files -containing digitized video in the "CMIF video format". - -An introduction to using the basic tools is in the file "video.doc". - -A description of the video file format is in the file "cmif-film.ms" -(troff/nroff -ms input). - - -History -------- - -We started this in October 1991, when we had a large framegrabber -board on loan from SGI for a few weeks: we developed a movie recording -program and added numerous features, including still frame capture and -synchronous sound recording using a second machine (the machine -holding the framegrabber board didn't have audio). - -During the following months, when we started using and processing the -recorded film fragments, the "CMIF video format" was revised several -times, and we eventually created an object-oriented interface for -reading and writing various incarnations of these files, called VFile. -(This module is also used by our flagship application, the CMIF -editor, not in this directory but in /ufs/guido/mm/.) - -When we got our own Indigo entry-level video board (in June 1992) and -a version of the Irix video library that supported capturing PAL -format (in August 1992), Sjoerd added an interface to the video -library to Python (sv) and Guido wrote Vrec.py (based upon a still -frame grabber by Sjoerd, in turn based upon SGI demo code in C) to -record a movie using it. Vrec was soon followed by modernized -versions of the other programs (Vinfo, Vplay, Vtime) and an -interactive editor (Vedit). Finally, VFile was rewritten for more -modularity, functionality and robustness, and various other tools were -added as needed. Also, new options were added to existing tools, and -several new video file formats were added. - - Guido van Rossum - Jack Jansen - Sjoerd Mullender - - -Overview of files ------------------ - -cmif-film.ms description of the CMIF video file format (more than a - little out of date -- read the source for VFile for - more info about new file formats) - - -These are programs with a command line interface: - -Vrec.py record video movies using the Indigo video library and - board - -Vplay.py play video movies - -Vinfo.py show statistics on movies - -Vtime.py Copy a video file, manipulating the time codes (e.g. - faster/slower, or regenerate time codes, or drop - frames too close apart) - -Vcopy.py Universal video file copying tool. Can manipulate the - time codes, change the type, size, and packfactor. - Subsumes Vtime.py. - -Vmkjpeg.py compress an rgb or grey video file to jpeg[grey] format - -Vunjpeg.py expand a jpeg[grey] video file to rgb or grey format - -Vfix.py truncate the scan line width of a video file to - a multiple of 4 ('grey' images only) - -Vedit.py interactive video editing program (uses the FORMS library) - -Vsend.py unicast or multicast live video as UDP packets - -Vreceive.py receive transmissions from Vsend - -Vaddcache.py add a "cached index" to a video file, for faster playing - -Vrecb.py like Vrec.py but uses "burst capture" -- somewhat specialized - -Dsend.py like Vsend.py but sends screen snapshots (to Vreceive.py) - -DisplayVideoIn.py Like LiveVideoIn.py but reads screen snapshots - -rgb2video.py combine a sequence of rgb image files into a CMIF video file - -video2rgb.py split a CMIF video file into a sequence of rgb image files - - -These modules and files are used by the above programs: - -VFile.py classes that read and write CMIF video files - -Viewer.py two viewer classes used by Vedit - -LiveVideoIn.py live video input class, used by Vsend - -LiveVideoOut.py live video output class, used by Vsend and Vreceive - -imgconv.py Image conversion subroutines for rgb2video.py - -senddefs.py Defaults shared by Vsend and Vreceice - -watchcursor.py Generally useful module to define a watch cursor in GL - -VeditForm.fd FORMS' fdesign definition for Vedit's form diff --git a/Demo/sgi/video/VCR.py b/Demo/sgi/video/VCR.py deleted file mode 100755 index 0e2edc63ab..0000000000 --- a/Demo/sgi/video/VCR.py +++ /dev/null @@ -1,534 +0,0 @@ -import fcntl -import IOCTL -from IOCTL import * -import sys -import struct -import select -import posix -import time - -DEVICE='/dev/ttyd2' - -class UnixFile: - def open(self, name, mode): - self.fd = posix.open(name, mode) - return self - - def read(self, len): - return posix.read(self.fd, len) - - def write(self, data): - dummy = posix.write(self.fd, data) - - def flush(self): - pass - - def fileno(self): - return self.fd - - def close(self): - dummy = posix.close(self.fd) - -def packttyargs(*args): - if type(args) <> type(()): - raise 'Incorrect argtype for packttyargs' - if type(args[0]) == type(1): - iflag, oflag, cflag, lflag, line, chars = args - elif type(args[0]) == type(()): - if len(args) <> 1: - raise 'Only 1 argument expected' - iflag, oflag, cflag, lflag, line, chars = args[0] - elif type(args[0]) == type([]): - if len(args) <> 1: - raise 'Only 1 argument expected' - [iflag, oflag, cflag, lflag, line, chars] = args[0] - str = struct.pack('hhhhb', iflag, oflag, cflag, lflag, line) - for c in chars: - str = str + c - return str - -def nullttyargs(): - chars = ['\0']*IOCTL.NCCS - return packttyargs(0, 0, 0, 0, 0, chars) - -def unpackttyargs(str): - args = str[:-IOCTL.NCCS] - rawchars = str[-IOCTL.NCCS:] - chars = [] - for c in rawchars: - chars.append(c) - iflag, oflag, cflag, lflag, line = struct.unpack('hhhhb', args) - return (iflag, oflag, cflag, lflag, line, chars) - -def initline(name): - fp = UnixFile().open(name, 2) - ofp = fp - fd = fp.fileno() - rv = fcntl.ioctl(fd, IOCTL.TCGETA, nullttyargs()) - iflag, oflag, cflag, lflag, line, chars = unpackttyargs(rv) - iflag = iflag & ~(INPCK|ISTRIP|INLCR|IUCLC|IXON|IXOFF) - oflag = oflag & ~OPOST - cflag = B9600|CS8|CREAD|CLOCAL - lflag = lflag & ~(ISIG|ICANON|ECHO|TOSTOP) - chars[VMIN] = chr(1) - chars[VTIME] = chr(0) - arg = packttyargs(iflag, oflag, cflag, lflag, line, chars) - dummy = fcntl.ioctl(fd, IOCTL.TCSETA, arg) - return fp, ofp - -# -# -error = 'VCR.error' - -# Commands/replies: -COMPLETION = '\x01' -ACK ='\x0a' -NAK ='\x0b' - -NUMBER_N = 0x30 -ENTER = '\x40' - -EXP_7= '\xde' -EXP_8= '\xdf' - -CL ='\x56' -CTRL_ENABLE = EXP_8 + '\xc6' -SEARCH_DATA = EXP_8 + '\x93' -ADDR_SENSE = '\x60' - -PLAY ='\x3a' -STOP ='\x3f' -EJECT='\x2a' -FF ='\xab' -REW ='\xac' -STILL='\x4f' -STEP_FWD ='\x2b' # Was: '\xad' -FM_SELECT=EXP_8 + '\xc8' -FM_STILL=EXP_8 + '\xcd' -PREVIEW=EXP_7 + '\x9d' -REVIEW=EXP_7 + '\x9e' -DM_OFF=EXP_8 + '\xc9' -DM_SET=EXP_8 + '\xc4' -FWD_SHUTTLE='\xb5' -REV_SHUTTLE='\xb6' -EM_SELECT=EXP_8 + '\xc0' -N_FRAME_REC=EXP_8 + '\x92' -SEARCH_PREROLL=EXP_8 + '\x90' -EDIT_PB_STANDBY=EXP_8 + '\x96' -EDIT_PLAY=EXP_8 + '\x98' -AUTO_EDIT=EXP_7 + '\x9c' - -IN_ENTRY=EXP_7 + '\x90' -IN_ENTRY_RESET=EXP_7 + '\x91' -IN_ENTRY_SET=EXP_7 + '\x98' -IN_ENTRY_INC=EXP_7 + '\x94' -IN_ENTRY_DEC=EXP_7 + '\x95' -IN_ENTRY_SENSE=EXP_7 + '\x9a' - -OUT_ENTRY=EXP_7 + '\x92' -OUT_ENTRY_RESET=EXP_7 + '\x93' -OUT_ENTRY_SET=EXP_7 + '\x99' -OUT_ENTRY_INC=EXP_7 + '\x96' -OUT_ENTRY_DEC=EXP_7 + '\x98' -OUT_ENTRY_SENSE=EXP_7 + '\x9b' - -MUTE_AUDIO = '\x24' -MUTE_AUDIO_OFF = '\x25' -MUTE_VIDEO = '\x26' -MUTE_VIDEO_OFF = '\x27' -MUTE_AV = EXP_7 + '\xc6' -MUTE_AV_OFF = EXP_7 + '\xc7' - -DEBUG=0 - -class VCR: - def __init__(self): - self.ifp, self.ofp = initline(DEVICE) - self.busy_cmd = None - self.async = 0 - self.cb = None - self.cb_arg = None - - def _check(self): - if self.busy_cmd: - raise error, 'Another command active: '+self.busy_cmd - - def _endlongcmd(self, name): - if not self.async: - self.waitready() - return 1 - self.busy_cmd = name - return 'VCR BUSY' - - def fileno(self): - return self.ifp.fileno() - - def setasync(self, async): - self.async = async - - def setcallback(self, cb, arg): - self.setasync(1) - self.cb = cb - self.cb_arg = arg - - def poll(self): - if not self.async: - raise error, 'Can only call poll() in async mode' - if not self.busy_cmd: - return - if self.testready(): - if self.cb: - apply(self.cb, self.cb_arg) - - def _cmd(self, cmd): - if DEBUG: - print '>>>',`cmd` - self.ofp.write(cmd) - self.ofp.flush() - - def _waitdata(self, len, tout): - rep = '' - while len > 0: - if tout == None: - ready, d1, d2 = select.select( \ - [self.ifp], [], []) - else: - ready, d1, d2 = select.select( \ - [self.ifp], [], [], tout) - if ready == []: -## if rep: -## print 'FLUSHED:', `rep` - return None - data = self.ifp.read(1) - if DEBUG: - print '<<<',`data` - if data == NAK: - return NAK - rep = rep + data - len = len - 1 - return rep - - def _reply(self, len): - data = self._waitdata(len, 10) - if data == None: - raise error, 'Lost contact with VCR' - return data - - def _getnumber(self, len): - data = self._reply(len) - number = 0 - for c in data: - digit = ord(c) - NUMBER_N - if digit < 0 or digit > 9: - raise error, 'Non-digit in number'+`c` - number = number*10 + digit - return number - - def _iflush(self): - dummy = self._waitdata(10000, 0) -## if dummy: -## print 'IFLUSH:', dummy - - def simplecmd(self,cmd): - self._iflush() - for ch in cmd: - self._cmd(ch) - rep = self._reply(1) - if rep == NAK: - return 0 - elif rep <> ACK: - raise error, 'Unexpected reply:' + `rep` - return 1 - - def replycmd(self, cmd): - if not self.simplecmd(cmd[:-1]): - return 0 - self._cmd(cmd[-1]) - - def _number(self, number, digits): - if number < 0: - raise error, 'Unexpected negative number:'+ `number` - maxnum = pow(10, digits) - if number > maxnum: - raise error, 'Number too big' - while maxnum > 1: - number = number % maxnum - maxnum = maxnum / 10 - digit = number / maxnum - ok = self.simplecmd(chr(NUMBER_N + digit)) - if not ok: - raise error, 'Error while transmitting number' - - def initvcr(self, *optarg): - timeout = None - if optarg <> (): - timeout = optarg[0] - starttime = time.time() - self.busy_cmd = None - self._iflush() - while 1: -## print 'SENDCL' - self._cmd(CL) - rep = self._waitdata(1, 2) -## print `rep` - if rep in ( None, CL, NAK ): - if timeout: - if time.time() - starttime > timeout: - raise error, \ - 'No reply from VCR' - continue - break - if rep <> ACK: - raise error, 'Unexpected reply:' + `rep` - dummy = self.simplecmd(CTRL_ENABLE) - - def waitready(self): - rep = self._waitdata(1, None) - if rep == None: - raise error, 'Unexpected None reply from waitdata' - if rep not in (COMPLETION, ACK): - self._iflush() - raise error, 'Unexpected waitready reply:' + `rep` - self.busy_cmd = None - - def testready(self): - rep = self._waitdata(1, 0) - if rep == None: - return 0 - if rep not in (COMPLETION, ACK): - self._iflush() - raise error, 'Unexpected waitready reply:' + `rep` - self.busy_cmd = None - return 1 - - def play(self): return self.simplecmd(PLAY) - def stop(self): return self.simplecmd(STOP) - def ff(self): return self.simplecmd(FF) - def rew(self): return self.simplecmd(REW) - def eject(self):return self.simplecmd(EJECT) - def still(self):return self.simplecmd(STILL) - def step(self): return self.simplecmd(STEP_FWD) - - def goto(self, (h, m, s, f)): - if not self.simplecmd(SEARCH_DATA): - return 0 - self._number(h, 2) - self._number(m, 2) - self._number(s, 2) - self._number(f, 2) - if not self.simplecmd(ENTER): - return 0 - return self._endlongcmd('goto') - - # XXXX TC_SENSE doesn't seem to work - def faulty_where(self): - self._check() - self._cmd(TC_SENSE) - h = self._getnumber(2) - m = self._getnumber(2) - s = self._getnumber(2) - f = self._getnumber(2) - return (h, m, s, f) - - def where(self): - return self.addr2tc(self.sense()) - - def sense(self): - self._check() - self._cmd(ADDR_SENSE) - num = self._getnumber(5) - return num - - def addr2tc(self, num): - f = num % 25 - num = num / 25 - s = num % 60 - num = num / 60 - m = num % 60 - h = num / 60 - return (h, m, s, f) - - def tc2addr(self, (h, m, s, f)): - return ((h*60 + m)*60 + s)*25 + f - - def fmmode(self, mode): - self._check() - if mode == 'off': - arg = 0 - elif mode == 'buffer': - arg = 1 - elif mode == 'dnr': - arg = 2 - else: - raise error, 'fmmode arg should be off, buffer or dnr' - if not self.simplecmd(FM_SELECT): - return 0 - self._number(arg, 1) - if not self.simplecmd(ENTER): - return 0 - return 1 - - def mute(self, mode, value): - self._check() - if mode == 'audio': - cmds = (MUTE_AUDIO_OFF, MUTE_AUDIO) - elif mode == 'video': - cmds = (MUTE_VIDEO_OFF, MUTE_VIDEO) - elif mode == 'av': - cmds = (MUTE_AV_OFF, MUTE_AV) - else: - raise error, 'mute type should be audio, video or av' - cmd = cmds[value] - return self.simplecmd(cmd) - - def editmode(self, mode): - self._check() - if mode == 'off': - a0 = a1 = a2 = 0 - elif mode == 'format': - a0 = 4 - a1 = 7 - a2 = 4 - elif mode == 'asmbl': - a0 = 1 - a1 = 7 - a2 = 4 - elif mode == 'insert-video': - a0 = 2 - a1 = 4 - a2 = 0 - else: - raise 'editmode should be off,format,asmbl or insert-video' - if not self.simplecmd(EM_SELECT): - return 0 - self._number(a0, 1) - self._number(a1, 1) - self._number(a2, 1) - if not self.simplecmd(ENTER): - return 0 - return 1 - - def autoedit(self): - self._check() - return self._endlongcmd(AUTO_EDIT) - - def nframerec(self, num): - if not self.simplecmd(N_FRAME_REC): - return 0 - self._number(num, 4) - if not self.simplecmd(ENTER): - return 0 - return self._endlongcmd('nframerec') - - def fmstill(self): - if not self.simplecmd(FM_STILL): - return 0 - return self._endlongcmd('fmstill') - - def preview(self): - if not self.simplecmd(PREVIEW): - return 0 - return self._endlongcmd('preview') - - def review(self): - if not self.simplecmd(REVIEW): - return 0 - return self._endlongcmd('review') - - def search_preroll(self): - if not self.simplecmd(SEARCH_PREROLL): - return 0 - return self._endlongcmd('search_preroll') - - def edit_pb_standby(self): - if not self.simplecmd(EDIT_PB_STANDBY): - return 0 - return self._endlongcmd('edit_pb_standby') - - def edit_play(self): - if not self.simplecmd(EDIT_PLAY): - return 0 - return self._endlongcmd('edit_play') - - def dmcontrol(self, mode): - self._check() - if mode == 'off': - return self.simplecmd(DM_OFF) - if mode == 'multi freeze': - num = 1000 - elif mode == 'zoom freeze': - num = 2000 - elif mode == 'digital slow': - num = 3000 - elif mode == 'freeze': - num = 4011 - else: - raise error, 'unknown dmcontrol argument: ' + `mode` - if not self.simplecmd(DM_SET): - return 0 - self._number(num, 4) - if not self.simplecmd(ENTER): - return 0 - return 1 - - def fwdshuttle(self, num): - if not self.simplecmd(FWD_SHUTTLE): - return 0 - self._number(num, 1) - return 1 - - def revshuttle(self, num): - if not self.simplecmd(REV_SHUTTLE): - return 0 - self._number(num, 1) - return 1 - - def getentry(self, which): - self._check() - if which == 'in': - cmd = IN_ENTRY_SENSE - elif which == 'out': - cmd = OUT_ENTRY_SENSE - self.replycmd(cmd) - h = self._getnumber(2) - m = self._getnumber(2) - s = self._getnumber(2) - f = self._getnumber(2) - return (h, m, s, f) - - def inentry(self, arg): - return self.ioentry(arg, (IN_ENTRY, IN_ENTRY_RESET, \ - IN_ENTRY_SET, IN_ENTRY_INC, IN_ENTRY_DEC)) - - def outentry(self, arg): - return self.ioentry(arg, (OUT_ENTRY, OUT_ENTRY_RESET, \ - OUT_ENTRY_SET, OUT_ENTRY_INC, OUT_ENTRY_DEC)) - - def ioentry(self, arg, (Load, Clear, Set, Inc, Dec)): - self._check() - if type(arg) == type(()): - h, m, s, f = arg - if not self.simplecmd(Set): - return 0 - self._number(h,2) - self._number(m,2) - self._number(s,2) - self._number(f,2) - if not self.simplecmd(ENTER): - return 0 - return 1 - elif arg == 'reset': - cmd = Clear - elif arg == 'load': - cmd = Load - elif arg == '+': - cmd = Inc - elif arg == '-': - cmd = Dec - else: - raise error, 'Arg should be +,-,reset,load or (h,m,s,f)' - return self.simplecmd(cmd) - - def cancel(self): - d = self.simplecmd(CL) - self.busy_cmd = None diff --git a/Demo/sgi/video/VFile.py b/Demo/sgi/video/VFile.py deleted file mode 100755 index 3cb7506ac4..0000000000 --- a/Demo/sgi/video/VFile.py +++ /dev/null @@ -1,1194 +0,0 @@ -# Classes to read and write CMIF video files. -# (For a description of the CMIF video format, see cmif-file.ms.) - - -# Layers of functionality: -# -# VideoParams: maintain essential parameters of a video file -# Displayer: display a frame in a window (with some extra parameters) -# BasicVinFile: read a CMIF video file -# BasicVoutFile: write a CMIF video file -# VinFile: BasicVinFile + Displayer -# VoutFile: BasicVoutFile + Displayer -# -# XXX Future extension: -# BasicVinoutFile: supports overwriting of individual frames - - -# Imported modules - -import sys -try: - import gl - import GL - no_gl = 0 -except ImportError: - no_gl = 1 -import GET -import colorsys -import imageop - - -# Exception raised for various occasions - -Error = 'VFile.Error' # file format errors -CallError = 'VFile.CallError' # bad call -AssertError = 'VFile.AssertError' # internal malfunction - - -# Max nr. of colormap entries to use - -MAXMAP = 4096 - 256 - - -# Parametrizations of colormap handling based on color system. -# (These functions are used via eval with a constructed argument!) - -def conv_grey(l, x, y): - return colorsys.yiq_to_rgb(l, 0, 0) - -def conv_grey4(l, x, y): - return colorsys.yiq_to_rgb(l*17, 0, 0) - -def conv_mono(l, x, y): - return colorsys.yiq_to_rgb(l*255, 0, 0) - -def conv_yiq(y, i, q): - return colorsys.yiq_to_rgb(y, (i-0.5)*1.2, q-0.5) - -def conv_hls(l, h, s): - return colorsys.hls_to_rgb(h, l, s) - -def conv_hsv(v, h, s): - return colorsys.hsv_to_rgb(h, s, v) - -def conv_rgb(r, g, b): - raise Error, 'Attempt to make RGB colormap' - -def conv_rgb8(rgb, d1, d2): - rgb = int(rgb*255.0) - r = (rgb >> 5) & 0x07 - g = (rgb ) & 0x07 - b = (rgb >> 3) & 0x03 - return (r/7.0, g/7.0, b/3.0) - -def conv_jpeg(r, g, b): - raise Error, 'Attempt to make RGB colormap (jpeg)' - -conv_jpeggrey = conv_grey -conv_grey2 = conv_grey - - -# Choose one of the above based upon a color system name - -def choose_conversion(format): - try: - return eval('conv_' + format) - except: - raise Error, 'Unknown color system: ' + `format` - - -# Inverses of the above - -def inv_grey(r, g, b): - y, i, q = colorsys.rgb_to_yiq(r, g, b) - return y, 0, 0 - -def inv_yiq(r, g, b): - y, i, q = colorsys.rgb_to_yiq(r, g, b) - return y, i/1.2 + 0.5, q + 0.5 - -def inv_hls(r, g, b): - h, l, s = colorsys.rgb_to_hls(r, g, b) - return l, h, s - -def inv_hsv(r, g, b): - h, s, v = colorsys.rgb_to_hsv(r, g, b) - return v, h, s - -def inv_rgb(r, g, b): - raise Error, 'Attempt to invert RGB colormap' - -def inv_rgb8(r, g, b): - r = int(r*7.0) - g = int(g*7.0) - b = int(b*7.0) - rgb = ((r&7) << 5) | ((b&3) << 3) | (g&7) - return rgb / 255.0, 0, 0 - -def inv_jpeg(r, g, b): - raise Error, 'Attempt to invert RGB colormap (jpeg)' - -inv_jpeggrey = inv_grey - - -# Choose one of the above based upon a color system name - -def choose_inverse(format): - try: - return eval('inv_' + format) - except: - raise Error, 'Unknown color system: ' + `format` - - -# Predicate to see whether this is an entry level (non-XS) Indigo. -# If so we can lrectwrite 8-bit wide pixels into a window in RGB mode - -def is_entry_indigo(): - # XXX hack, hack. We should call gl.gversion() but that doesn't - # exist in earlier Python versions. Therefore we check the number - # of bitplanes *and* the size of the monitor. - xmax = gl.getgdesc(GL.GD_XPMAX) - if xmax <> 1024: return 0 - ymax = gl.getgdesc(GL.GD_YPMAX) - if ymax != 768: return 0 - r = gl.getgdesc(GL.GD_BITS_NORM_SNG_RED) - g = gl.getgdesc(GL.GD_BITS_NORM_SNG_GREEN) - b = gl.getgdesc(GL.GD_BITS_NORM_SNG_BLUE) - return (r, g, b) == (3, 3, 2) - - -# Predicate to see whether this machine supports pixmode(PM_SIZE) with -# values 1 or 4. -# -# XXX Temporarily disabled, since it is unclear which machines support -# XXX which pixelsizes. -# -# XXX The XS appears to support 4 bit pixels, but (looking at osview) it -# XXX seems as if the conversion is done by the kernel (unpacking ourselves -# XXX is faster than using PM_SIZE=4) - -def support_packed_pixels(): - return 0 # To be architecture-dependent - - - -# Tables listing bits per pixel for some formats - -bitsperpixel = { \ - 'rgb': 32, \ - 'rgb8': 8, \ - 'grey': 8, \ - 'grey4': 4, \ - 'grey2': 2, \ - 'mono': 1, \ - 'compress': 32, \ -} - -bppafterdecomp = {'jpeg': 32, 'jpeggrey': 8} - - -# Base class to manage video format parameters - -class VideoParams: - - # Initialize an instance. - # Set all parameters to something decent - # (except width and height are set to zero) - - def __init__(self): - # Essential parameters - self.frozen = 0 # if set, can't change parameters - self.format = 'grey' # color system used - # Choose from: grey, rgb, rgb8, hsv, yiq, hls, jpeg, jpeggrey, - # mono, grey2, grey4 - self.width = 0 # width of frame - self.height = 0 # height of frame - self.packfactor = 1, 1 # expansion using rectzoom - # Colormap info - self.c0bits = 8 # bits in first color dimension - self.c1bits = 0 # bits in second color dimension - self.c2bits = 0 # bits in third color dimension - self.offset = 0 # colormap index offset (XXX ???) - self.chrompack = 0 # set if separate chrominance data - self.setderived() - self.decompressor = None - - # Freeze the parameters (disallow changes) - - def freeze(self): - self.frozen = 1 - - # Unfreeze the parameters (allow changes) - - def unfreeze(self): - self.frozen = 0 - - # Set some values derived from the standard info values - - def setderived(self): - if self.frozen: raise AssertError - if bitsperpixel.has_key(self.format): - self.bpp = bitsperpixel[self.format] - else: - self.bpp = 0 - xpf, ypf = self.packfactor - self.xpf = abs(xpf) - self.ypf = abs(ypf) - self.mirror_image = (xpf < 0) - self.upside_down = (ypf < 0) - self.realwidth = self.width / self.xpf - self.realheight = self.height / self.ypf - - # Set colormap info - - def setcmapinfo(self): - stuff = 0, 0, 0, 0, 0 - if self.format in ('rgb8', 'grey'): - stuff = 8, 0, 0, 0, 0 - if self.format == 'grey4': - stuff = 4, 0, 0, 0, 0 - if self.format == 'grey2': - stuff = 2, 0, 0, 0, 0 - if self.format == 'mono': - stuff = 1, 0, 0, 0, 0 - self.c0bits, self.c1bits, self.c2bits, \ - self.offset, self.chrompack = stuff - - # Set the frame width and height (e.g. from gl.getsize()) - - def setsize(self, width, height): - if self.frozen: raise CallError - width = (width/self.xpf)*self.xpf - height = (height/self.ypf)*self.ypf - self.width, self.height = width, height - self.setderived() - - # Retrieve the frame width and height (e.g. for gl.prefsize()) - - def getsize(self): - return (self.width, self.height) - - # Set the format - - def setformat(self, format): - if self.frozen: raise CallError - self.format = format - self.setderived() - self.setcmapinfo() - - # Get the format - - def getformat(self): - return self.format - - # Set the packfactor - - def setpf(self, pf): - if self.frozen: raise CallError - if type(pf) == type(1): - pf = (pf, pf) - if type(pf) is not type(()) or len(pf) <> 2: raise CallError - self.packfactor = pf - self.setderived() - - # Get the packfactor - - def getpf(self): - return self.packfactor - - # Set all parameters - - def setinfo(self, values): - if self.frozen: raise CallError - self.setformat(values[0]) - self.setpf(values[3]) - self.setsize(values[1], values[2]) - (self.c0bits, self.c1bits, self.c2bits, \ - self.offset, self.chrompack) = values[4:9] - if self.format == 'compress' and len(values) > 9: - self.compressheader = values[9] - self.setderived() - - # Retrieve all parameters in a format suitable for a subsequent - # call to setinfo() - - def getinfo(self): - return (self.format, self.width, self.height, self.packfactor,\ - self.c0bits, self.c1bits, self.c2bits, self.offset, \ - self.chrompack) - - def getcompressheader(self): - return self.compressheader - - def setcompressheader(self, ch): - self.compressheader = ch - - # Write the relevant bits to stdout - - def printinfo(self): - print 'Format: ', self.format - print 'Size: ', self.width, 'x', self.height - print 'Pack: ', self.packfactor, '; chrom:', self.chrompack - print 'Bpp: ', self.bpp - print 'Bits: ', self.c0bits, self.c1bits, self.c2bits - print 'Offset: ', self.offset - - # Calculate data size, if possible - # (Not counting frame header or cdata size) - - def calcframesize(self): - if not self.bpp: raise CallError - size = self.width/self.xpf * self.height/self.ypf - size = (size * self.bpp + 7) / 8 - return size - - # Decompress a possibly compressed frame. This method is here - # since you sometimes want to use it on a VFile instance and sometimes - # on a Displayer instance. - # - # XXXX This should also handle jpeg. Actually, the whole mechanism - # should be much more of 'ihave/iwant' style, also allowing you to - # read, say, greyscale images from a color movie. - - def decompress(self, data): - if self.format <> 'compress': - return data - if not self.decompressor: - import cl, CL - scheme = cl.QueryScheme(self.compressheader) - self.decompressor = cl.OpenDecompressor(scheme) - headersize = self.decompressor.ReadHeader(self.compressheader) - width = self.decompressor.GetParam(CL.IMAGE_WIDTH) - height = self.decompressor.GetParam(CL.IMAGE_HEIGHT) - params = [CL.ORIGINAL_FORMAT, CL.RGBX, \ - CL.ORIENTATION, CL.BOTTOM_UP, \ - CL.FRAME_BUFFER_SIZE, width*height*CL.BytesPerPixel(CL.RGBX)] - self.decompressor.SetParams(params) - data = self.decompressor.Decompress(1, data) - return data - - -# Class to display video frames in a window. -# It is the caller's responsibility to ensure that the correct window -# is current when using showframe(), initcolormap(), clear() and clearto() - -class Displayer(VideoParams): - - # Initialize an instance. - # This does not need a current window - - def __init__(self): - if no_gl: - raise RuntimeError, \ - 'no gl module available, so cannot display' - VideoParams.__init__(self) - # User-settable parameters - self.magnify = 1.0 # frame magnification factor - self.xorigin = 0 # x frame offset - self.yorigin = 0 # y frame offset (from bottom) - self.quiet = 0 # if set, don't print messages - self.fallback = 1 # allow fallback to grey - # Internal flags - self.colormapinited = 0 # must initialize window - self.skipchrom = 0 # don't skip chrominance data - self.color0 = None # magic, used by clearto() - self.fixcolor0 = 0 # don't need to fix color0 - self.mustunpack = (not support_packed_pixels()) - return self - - # setinfo() must reset some internal flags - - def setinfo(self, values): - VideoParams.setinfo(self, values) - self.colormapinited = 0 - self.skipchrom = 0 - self.color0 = None - self.fixcolor0 = 0 - - # Show one frame, initializing the window if necessary - - def showframe(self, data, chromdata): - self.showpartframe(data, chromdata, \ - (0,0,self.width,self.height)) - - def showpartframe(self, data, chromdata, (x,y,w,h)): - pmsize = self.bpp - xpf, ypf = self.xpf, self.ypf - if self.upside_down: - gl.pixmode(GL.PM_TTOB, 1) - if self.mirror_image: - gl.pixmode(GL.PM_RTOL, 1) - if self.format in ('jpeg', 'jpeggrey'): - import jpeg - data, width, height, bytes = jpeg.decompress(data) - pmsize = bytes*8 - elif self.format == 'compress': - data = self.decompress(data) - pmsize = 32 - elif self.format in ('mono', 'grey4'): - if self.mustunpack: - if self.format == 'mono': - data = imageop.mono2grey(data, \ - w/xpf, h/ypf, 0x20, 0xdf) - elif self.format == 'grey4': - data = imageop.grey42grey(data, \ - w/xpf, h/ypf) - pmsize = 8 - elif self.format == 'grey2': - data = imageop.grey22grey(data, w/xpf, h/ypf) - pmsize = 8 - if not self.colormapinited: - self.initcolormap() - if self.fixcolor0: - gl.mapcolor(self.color0) - self.fixcolor0 = 0 - xfactor = yfactor = self.magnify - xfactor = xfactor * xpf - yfactor = yfactor * ypf - if chromdata and not self.skipchrom: - cp = self.chrompack - cx = int(x*xfactor*cp) + self.xorigin - cy = int(y*yfactor*cp) + self.yorigin - cw = (w+cp-1)/cp - ch = (h+cp-1)/cp - gl.rectzoom(xfactor*cp, yfactor*cp) - gl.pixmode(GL.PM_SIZE, 16) - gl.writemask(self.mask - ((1 << self.c0bits) - 1)) - gl.lrectwrite(cx, cy, cx + cw - 1, cy + ch - 1, \ - chromdata) - # - if pmsize < 32: - gl.writemask((1 << self.c0bits) - 1) - gl.pixmode(GL.PM_SIZE, pmsize) - w = w/xpf - h = h/ypf - x = x/xpf - y = y/ypf - gl.rectzoom(xfactor, yfactor) - x = int(x*xfactor)+self.xorigin - y = int(y*yfactor)+self.yorigin - gl.lrectwrite(x, y, x + w - 1, y + h - 1, data) - gl.gflush() - - # Initialize the window: set RGB or colormap mode as required, - # fill in the colormap, and clear the window - - def initcolormap(self): - self.colormapinited = 1 - self.color0 = None - self.fixcolor0 = 0 - if self.format in ('rgb', 'jpeg', 'compress'): - self.set_rgbmode() - gl.RGBcolor(200, 200, 200) # XXX rather light grey - gl.clear() - return - # This only works on an Entry-level Indigo from IRIX 4.0.5 - if self.format == 'rgb8' and is_entry_indigo() and \ - gl.gversion() == 'GL4DLG-4.0.': # Note trailing '.'! - self.set_rgbmode() - gl.RGBcolor(200, 200, 200) # XXX rather light grey - gl.clear() - gl.pixmode(GL.PM_SIZE, 8) - return - self.set_cmode() - self.skipchrom = 0 - if self.offset == 0: - self.mask = 0x7ff - else: - self.mask = 0xfff - if not self.quiet: - sys.stderr.write('Initializing color map...') - self._initcmap() - gl.clear() - if not self.quiet: - sys.stderr.write(' Done.\n') - - # Set the window in RGB mode (may be overridden for Glx window) - - def set_rgbmode(self): - gl.RGBmode() - gl.gconfig() - - # Set the window in colormap mode (may be overridden for Glx window) - - def set_cmode(self): - gl.cmode() - gl.gconfig() - - # Clear the window to a default color - - def clear(self): - if not self.colormapinited: raise CallError - if gl.getdisplaymode() in (GET.DMRGB, GET.DMRGBDOUBLE): - gl.RGBcolor(200, 200, 200) # XXX rather light grey - gl.clear() - return - gl.writemask(0xffffffff) - gl.clear() - - # Clear the window to a given RGB color. - # This may steal the first color index used; the next call to - # showframe() will restore the intended mapping for that index - - def clearto(self, r, g, b): - if not self.colormapinited: raise CallError - if gl.getdisplaymode() in (GET.DMRGB, GET.DMRGBDOUBLE): - gl.RGBcolor(r, g, b) - gl.clear() - return - index = self.color0[0] - self.fixcolor0 = 1 - gl.mapcolor(index, r, g, b) - gl.writemask(0xffffffff) - gl.clear() - gl.gflush() - - # Do the hard work for initializing the colormap (internal). - # This also sets the current color to the first color index - # used -- the caller should never change this since it is used - # by clear() and clearto() - - def _initcmap(self): - map = [] - if self.format in ('mono', 'grey4') and self.mustunpack: - convcolor = conv_grey - else: - convcolor = choose_conversion(self.format) - maxbits = gl.getgdesc(GL.GD_BITS_NORM_SNG_CMODE) - if maxbits > 11: - maxbits = 11 - c0bits = self.c0bits - c1bits = self.c1bits - c2bits = self.c2bits - if c0bits+c1bits+c2bits > maxbits: - if self.fallback and c0bits < maxbits: - # Cannot display frames in this mode, use grey - self.skipchrom = 1 - c1bits = c2bits = 0 - convcolor = choose_conversion('grey') - else: - raise Error, 'Sorry, '+`maxbits`+ \ - ' bits max on this machine' - maxc0 = 1 << c0bits - maxc1 = 1 << c1bits - maxc2 = 1 << c2bits - if self.offset == 0 and maxbits == 11: - offset = 2048 - else: - offset = self.offset - if maxbits <> 11: - offset = offset & ((1< type(()): - raise Error, filename + ': Bad (w,h,pf) info' - if len(x) == 3: - width, height, packfactor = x - if packfactor == 0 and version < 3.0: - format = 'rgb' - c0bits = 0 - elif len(x) == 2 and version <= 1.0: - width, height = x - packfactor = 2 - else: - raise Error, filename + ': Bad (w,h,pf) info' - if type(packfactor) is type(0): - if packfactor == 0: packfactor = 1 - xpf = ypf = packfactor - else: - xpf, ypf = packfactor - if upside_down: - ypf = -ypf - packfactor = (xpf, ypf) - xpf = abs(xpf) - ypf = abs(ypf) - width = (width/xpf) * xpf - height = (height/ypf) * ypf - # - # Return (version, values) - # - values = (format, width, height, packfactor, \ - c0bits, c1bits, c2bits, offset, chrompack, compressheader) - return (version, values) - - -# Read a *frame* header -- separate functions per version. -# Return (timecode, datasize, chromdatasize). -# Raise EOFError if end of data is reached. -# Raise Error if data is bad. - -def readv0frameheader(fp): - line = fp.readline() - if not line or line == '\n': raise EOFError - try: - t = eval(line[:-1]) - except: - raise Error, 'Bad 0.0 frame header' - return (t, 0, 0) - -def readv1frameheader(fp): - line = fp.readline() - if not line or line == '\n': raise EOFError - try: - t, datasize = eval(line[:-1]) - except: - raise Error, 'Bad 1.0 frame header' - return (t, datasize, 0) - -def readv2frameheader(fp): - line = fp.readline() - if not line or line == '\n': raise EOFError - try: - t, datasize = eval(line[:-1]) - except: - raise Error, 'Bad 2.0 frame header' - return (t, datasize, 0) - -def readv3frameheader(fp): - line = fp.readline() - if not line or line == '\n': raise EOFError - try: - t, datasize, chromdatasize = x = eval(line[:-1]) - except: - raise Error, 'Bad 3.[01] frame header' - return x - - -# Write a CMIF video file header (always version 3.1) - -def writefileheader(fp, values): - (format, width, height, packfactor, \ - c0bits, c1bits, c2bits, offset, chrompack) = values - # - # Write identifying header - # - fp.write('CMIF video 3.1\n') - # - # Write color encoding info - # - if format in ('rgb', 'jpeg'): - data = (format, 0) - elif format in ('grey', 'jpeggrey', 'mono', 'grey2', 'grey4'): - data = (format, c0bits) - else: - data = (format, (c0bits, c1bits, c2bits, chrompack, offset)) - fp.write(`data`+'\n') - # - # Write frame geometry info - # - data = (width, height, packfactor) - fp.write(`data`+'\n') - -def writecompressfileheader(fp, cheader, values): - (format, width, height, packfactor, \ - c0bits, c1bits, c2bits, offset, chrompack) = values - # - # Write identifying header - # - fp.write('CMIF video 3.1\n') - # - # Write color encoding info - # - data = (format, cheader) - fp.write(`data`+'\n') - # - # Write frame geometry info - # - data = (width, height, packfactor) - fp.write(`data`+'\n') - - -# Basic class for reading CMIF video files - -class BasicVinFile(VideoParams): - - def __init__(self, filename): - if type(filename) != type(''): - fp = filename - filename = '???' - elif filename == '-': - fp = sys.stdin - else: - fp = open(filename, 'r') - self.initfp(fp, filename) - - def initfp(self, fp, filename): - VideoParams.__init__(self) - self.fp = fp - self.filename = filename - self.version, values = readfileheader(fp, filename) - self.setinfo(values) - self.freeze() - if self.version == 0.0: - w, h, pf = self.width, self.height, self.packfactor - if pf == 0: - self._datasize = w*h*4 - else: - self._datasize = (w/pf) * (h/pf) - self._readframeheader = self._readv0frameheader - elif self.version == 1.0: - self._readframeheader = readv1frameheader - elif self.version == 2.0: - self._readframeheader = readv2frameheader - elif self.version in (3.0, 3.1): - self._readframeheader = readv3frameheader - else: - raise Error, \ - filename + ': Bad version: ' + `self.version` - self.framecount = 0 - self.atframeheader = 1 - self.eofseen = 0 - self.errorseen = 0 - try: - self.startpos = self.fp.tell() - self.canseek = 1 - except IOError: - self.startpos = -1 - self.canseek = 0 - - def _readv0frameheader(self, fp): - t, ds, cs = readv0frameheader(fp) - ds = self._datasize - return (t, ds, cs) - - def close(self): - self.fp.close() - del self.fp - del self._readframeheader - - def rewind(self): - if not self.canseek: - raise Error, self.filename + ': can\'t seek' - self.fp.seek(self.startpos) - self.framecount = 0 - self.atframeheader = 1 - self.eofseen = 0 - self.errorseen = 0 - - def warmcache(self): - print '[BasicVinFile.warmcache() not implemented]' - - def printinfo(self): - print 'File: ', self.filename - print 'Size: ', getfilesize(self.filename) - print 'Version: ', self.version - VideoParams.printinfo(self) - - def getnextframe(self): - t, ds, cs = self.getnextframeheader() - data, cdata = self.getnextframedata(ds, cs) - return (t, data, cdata) - - def skipnextframe(self): - t, ds, cs = self.getnextframeheader() - self.skipnextframedata(ds, cs) - return t - - def getnextframeheader(self): - if self.eofseen: raise EOFError - if self.errorseen: raise CallError - if not self.atframeheader: raise CallError - self.atframeheader = 0 - try: - return self._readframeheader(self.fp) - except Error, msg: - self.errorseen = 1 - # Patch up the error message - raise Error, self.filename + ': ' + msg - except EOFError: - self.eofseen = 1 - raise EOFError - - def getnextframedata(self, ds, cs): - if self.eofseen: raise EOFError - if self.errorseen: raise CallError - if self.atframeheader: raise CallError - if ds: - data = self.fp.read(ds) - if len(data) < ds: - self.eofseen = 1 - raise EOFError - else: - data = '' - if cs: - cdata = self.fp.read(cs) - if len(cdata) < cs: - self.eofseen = 1 - raise EOFError - else: - cdata = '' - self.atframeheader = 1 - self.framecount = self.framecount + 1 - return (data, cdata) - - def skipnextframedata(self, ds, cs): - if self.eofseen: raise EOFError - if self.errorseen: raise CallError - if self.atframeheader: raise CallError - # Note that this won't raise EOFError for a partial frame - # since there is no easy way to tell whether a seek - # ended up beyond the end of the file - if self.canseek: - self.fp.seek(ds + cs, 1) # Relative seek - else: - dummy = self.fp.read(ds + cs) - del dummy - self.atframeheader = 1 - self.framecount = self.framecount + 1 - - -# Subroutine to return a file's size in bytes - -def getfilesize(filename): - import os, stat - try: - st = os.stat(filename) - return st[stat.ST_SIZE] - except os.error: - return 0 - - -# Derived class implementing random access and index cached in the file - -class RandomVinFile(BasicVinFile): - - def initfp(self, fp, filename): - BasicVinFile.initfp(self, fp, filename) - self.index = [] - - def warmcache(self): - if len(self.index) == 0: - try: - self.readcache() - except Error: - self.buildcache() - else: - print '[RandomVinFile.warmcache(): too late]' - self.rewind() - - def buildcache(self): - self.index = [] - self.rewind() - while 1: - try: dummy = self.skipnextframe() - except EOFError: break - self.rewind() - - def writecache(self): - # Raises IOerror if the file is not seekable & writable! - import marshal - if len(self.index) == 0: - self.buildcache() - if len(self.index) == 0: - raise Error, self.filename + ': No frames' - self.fp.seek(0, 2) - self.fp.write('\n/////CMIF/////\n') - pos = self.fp.tell() - data = `pos` - data = '\n-*-*-CMIF-*-*-\n' + data + ' '*(15-len(data)) + '\n' - try: - marshal.dump(self.index, self.fp) - self.fp.write(data) - self.fp.flush() - finally: - self.rewind() - - def readcache(self): - # Raises Error if there is no cache in the file - import marshal - if len(self.index) <> 0: - raise CallError - self.fp.seek(-32, 2) - data = self.fp.read() - if data[:16] <> '\n-*-*-CMIF-*-*-\n' or data[-1:] <> '\n': - self.rewind() - raise Error, self.filename + ': No cache' - pos = eval(data[16:-1]) - self.fp.seek(pos) - try: - self.index = marshal.load(self.fp) - except TypeError: - self.rewind() - raise Error, self.filename + ': Bad cache' - self.rewind() - - def getnextframeheader(self): - if self.framecount < len(self.index): - return self._getindexframeheader(self.framecount) - if self.framecount > len(self.index): - raise AssertError, \ - 'managed to bypass index?!?' - rv = BasicVinFile.getnextframeheader(self) - if self.canseek: - pos = self.fp.tell() - self.index.append(rv, pos) - return rv - - def getrandomframe(self, i): - t, ds, cs = self.getrandomframeheader(i) - data, cdata = self.getnextframedata(ds, cs) - return t, data, cdata - - def getrandomframeheader(self, i): - if i < 0: raise ValueError, 'negative frame index' - if not self.canseek: - raise Error, self.filename + ': can\'t seek' - if i < len(self.index): - return self._getindexframeheader(i) - if len(self.index) > 0: - rv = self.getrandomframeheader(len(self.index)-1) - else: - self.rewind() - rv = self.getnextframeheader() - while i > self.framecount: - self.skipnextframedata() - rv = self.getnextframeheader() - return rv - - def _getindexframeheader(self, i): - (rv, pos) = self.index[i] - self.fp.seek(pos) - self.framecount = i - self.atframeheader = 0 - self.eofseen = 0 - self.errorseen = 0 - return rv - - -# Basic class for writing CMIF video files - -class BasicVoutFile(VideoParams): - - def __init__(self, filename): - if type(filename) != type(''): - fp = filename - filename = '???' - elif filename == '-': - fp = sys.stdout - else: - fp = open(filename, 'w') - self.initfp(fp, filename) - - def initfp(self, fp, filename): - VideoParams.__init__(self) - self.fp = fp - self.filename = filename - self.version = 3.1 # In case anyone inquries - - def flush(self): - self.fp.flush() - - def close(self): - self.fp.close() - del self.fp - - def prealloc(self, nframes): - if not self.frozen: raise CallError - data = '\xff' * (self.calcframesize() + 64) - pos = self.fp.tell() - for i in range(nframes): - self.fp.write(data) - self.fp.seek(pos) - - def writeheader(self): - if self.frozen: raise CallError - if self.format == 'compress': - writecompressfileheader(self.fp, self.compressheader, \ - self.getinfo()) - else: - writefileheader(self.fp, self.getinfo()) - self.freeze() - self.atheader = 1 - self.framecount = 0 - - def rewind(self): - self.fp.seek(0) - self.unfreeze() - self.atheader = 1 - self.framecount = 0 - - def printinfo(self): - print 'File: ', self.filename - VideoParams.printinfo(self) - - def writeframe(self, t, data, cdata): - if data: ds = len(data) - else: ds = 0 - if cdata: cs = len(cdata) - else: cs = 0 - self.writeframeheader(t, ds, cs) - self.writeframedata(data, cdata) - - def writeframeheader(self, t, ds, cs): - if not self.frozen: self.writeheader() - if not self.atheader: raise CallError - data = `(t, ds, cs)` - n = len(data) - if n < 63: data = data + ' '*(63-n) - self.fp.write(data + '\n') - self.atheader = 0 - - def writeframedata(self, data, cdata): - if not self.frozen or self.atheader: raise CallError - if data: self.fp.write(data) - if cdata: self.fp.write(cdata) - self.atheader = 1 - self.framecount = self.framecount + 1 - - -# Classes that combine files with displayers: - -class VinFile(RandomVinFile, Displayer): - - def initfp(self, fp, filename): - Displayer.__init__(self) - RandomVinFile.initfp(self, fp, filename) - - def shownextframe(self): - t, data, cdata = self.getnextframe() - self.showframe(data, cdata) - return t - - -class VoutFile(BasicVoutFile, Displayer): - - def initfp(self, fp, filename): - Displayer.__init__(self) -## Grabber.__init__(self) # XXX not needed - BasicVoutFile.initfp(self, fp, filename) - - -# Simple test program (VinFile only) - -def test(): - import time - if sys.argv[1:]: filename = sys.argv[1] - else: filename = 'film.video' - vin = VinFile(filename) - vin.printinfo() - gl.foreground() - gl.prefsize(vin.getsize()) - wid = gl.winopen(filename) - vin.initcolormap() - t0 = time.millitimer() - while 1: - try: t, data, cdata = vin.getnextframe() - except EOFError: break - dt = t0 + t - time.millitimer() - if dt > 0: time.millisleep(dt) - vin.showframe(data, cdata) - time.sleep(2) diff --git a/Demo/sgi/video/VGrabber.py b/Demo/sgi/video/VGrabber.py deleted file mode 100755 index 242ebf2231..0000000000 --- a/Demo/sgi/video/VGrabber.py +++ /dev/null @@ -1,80 +0,0 @@ -# Class to grab frames from a window. -# (This has fewer user-settable parameters than Displayer.) -# It is the caller's responsibility to initialize the window and to -# ensure that it is current when using grabframe() - -import gl, GL -import VFile -import GET -from VFile import Error - -class VGrabber(VFile.VideoParams): - - # XXX The constructor of VideoParams is just fine, for now - - # Grab a frame. - # Return (data, chromdata) just like getnextframe(). - - def grabframe(self): - grabber = choose_grabber(self.format) - return grabber(self.width, self.height, self.packfactor) - - -# Choose one of the grabber functions below based upon a color system name - -def choose_grabber(format): - try: - return eval('grab_' + format) - except: - raise Error, 'Unknown color system: ' + `format` - - -# Routines to grab data, per color system (only a few really supported). -# (These functions are used via eval with a constructed argument!) - -def grab_rgb(w, h, pf): - if gl.getdisplaymode() <> GET.DMRGB: - raise Error, 'Sorry, can only grab rgb in single-buf rgbmode' - if pf <> (1, 1): - raise Error, 'Sorry, only grab rgb with packfactor (1,1)' - return gl.lrectread(0, 0, w-1, h-1), None - -def grab_rgb8(w, h, pf): - if gl.getdisplaymode() <> GET.DMRGB: - raise Error, 'Sorry, can only grab rgb8 in single-buf rgbmode' - if pf <> (1, 1): - raise Error, 'Sorry, can only grab rgb8 with packfactor (1,1)' - if not VFile.is_entry_indigo(): - raise Error, 'Sorry, can only grab rgb8 on entry level Indigo' - # XXX Dirty Dirty here. - # XXX Set buffer to cmap mode, grab image and set it back. - gl.cmode() - gl.gconfig() - gl.pixmode(GL.PM_SIZE, 8) - data = gl.lrectread(0, 0, w-1, h-1) - data = data[:w*h] # BUG FIX for python lrectread - gl.RGBmode() - gl.gconfig() - gl.pixmode(GL.PM_SIZE, 32) - return data, None - -def grab_grey(w, h, pf): - raise Error, 'Sorry, grabbing grey not implemented' - -def grab_yiq(w, h, pf): - raise Error, 'Sorry, grabbing yiq not implemented' - -def grab_hls(w, h, pf): - raise Error, 'Sorry, grabbing hls not implemented' - -def grab_hsv(w, h, pf): - raise Error, 'Sorry, grabbing hsv not implemented' - -def grab_jpeg(w, h, pf): - data, dummy = grab_rgb(w, h, pf) - import jpeg - data = jpeg.compress(data, w, h, 4) - return data, None - -def grab_jpeggrey(w, h, pf): - raise Error, 'sorry, grabbing jpeggrey not implemented' diff --git a/Demo/sgi/video/Vaddcache.py b/Demo/sgi/video/Vaddcache.py deleted file mode 100755 index 6428fcbce3..0000000000 --- a/Demo/sgi/video/Vaddcache.py +++ /dev/null @@ -1,80 +0,0 @@ -#! /ufs/guido/bin/sgi/python - -# Add a cache to each of the files given as command line arguments - - -# Usage: -# -# Vaddcache [file] ... - - -# Options: -# -# file ... : file(s) to modify; default film.video - - -import sys -sys.path.append('/ufs/guido/src/video') -import VFile -import getopt - - -# Global options - -# None - - -# Main program -- mostly command line parsing - -def main(): - opts, args = getopt.getopt(sys.argv[1:], '') - if not args: - args = ['film.video'] - sts = 0 - for filename in args: - if process(filename): - sts = 1 - sys.exit(sts) - - -# Process one file - -def process(filename): - try: - fp = open(filename, 'r+') - vin = VFile.RandomVinFile(fp) - vin.filename = filename - except IOError, msg: - sys.stderr.write(filename + ': I/O error: ' + `msg` + '\n') - return 1 - except VFile.Error, msg: - sys.stderr.write(msg + '\n') - return 1 - except EOFError: - sys.stderr.write(filename + ': EOF in video file\n') - return 1 - - try: - vin.readcache() - hascache = 1 - except VFile.Error: - hascache = 0 - - if hascache: - sys.stderr.write(filename + ': already has a cache\n') - vin.close() - return 1 - - vin.printinfo() - vin.warmcache() - vin.writecache() - vin.close() - return 0 - - -# Don't forget to call the main program - -try: - main() -except KeyboardInterrupt: - print '[Interrupt]' diff --git a/Demo/sgi/video/Vb.py b/Demo/sgi/video/Vb.py deleted file mode 100755 index 093bcf7ed0..0000000000 --- a/Demo/sgi/video/Vb.py +++ /dev/null @@ -1,963 +0,0 @@ -#! /ufs/guido/bin/sgi/python - -# Video bag of tricks: record video(+audio) in various formats and modes - -# XXX To do: -# - audio -# - improve user interface -# - help button? -# - command line options to set initial settings -# - save settings in a file -# - ...? - -import sys -import time -import getopt -import string -import os -sts = os.system('makemap') # Must be before "import fl" to work -import sgi -import gl -import GL -import DEVICE -import fl -import FL -import flp -import watchcursor -import sv -import SV -import VFile -import VGrabber -import imageop -sys.path.append('/ufs/jack/src/av/vcr') -import VCR -try: - import cl - import CL -except ImportError: - cl = None - -ARROW = 0 -WATCH = 1 -watchcursor.defwatch(WATCH) - -def main(): -## fl.set_graphics_mode(0, 1) - vb = VideoBagOfTricks() - while 1: - dummy = fl.do_forms() - [dummy] - -StopCapture = 'StopCapture' - -VideoFormatLabels = ['Video off', 'rgb8', 'grey8', 'grey4', 'grey2', \ - 'grey2 dith', 'mono dith', 'mono thresh', 'rgb24', 'rgb24-jpeg', \ - 'compress'] -VideoFormats = ['', 'rgb8', 'grey', 'grey4', 'grey2', \ - 'grey2', 'mono', 'mono', 'rgb', 'jpeg', 'compress'] - -VideoModeLabels = ['Continuous', 'Burst', 'Single frame', 'VCR sync'] -[VM_CONT, VM_BURST, VM_SINGLE, VM_VCR] = range(1, 5) - -AudioFormatLabels = ['Audio off', \ - '16 bit mono', '16 bit stereo', '8 bit mono', '8 bit stereo'] -[A_OFF, A_16_MONO, A_16_STEREO, A_8_MONO, A_8_STEREO] = range(1, 6) - -VcrSpeedLabels = ['normal', '1/3', '1/5', '1/10', '1/30', 'single-step'] -VcrSpeeds = [None, 5, 4, 3, 2, 1, 0] - -RgbSizeLabels = ['full', 'quarter', 'sixteenth'] - -# init file stuff: -if os.environ.has_key('HOME'): - HOME=os.environ['HOME'] -else: - HOME='.' -VB_INIT_FILE=HOME + '/.Vb_init' - -VB_INIT_KEYS=['vfile', 'vmode', 'mono_thresh', 'vformat', 'comp_scheme', \ - 'rgb24_size', 'afile', 'aformat'] - -class VideoBagOfTricks: - - # Init/close stuff - - def __init__(self): - self.window = None - formdef = flp.parse_form('VbForm', 'form') - flp.create_full_form(self, formdef) - self.setdefaults() - if self.vmode <> VM_CONT: - self.g_cont.hide_object() - if self.vmode <> VM_BURST: - self.g_burst.hide_object() - if self.vmode <> VM_SINGLE: - self.g_single.hide_object() - if self.vmode <> VM_VCR: - self.g_vcr.hide_object() - if self.vformat <> 'compress': - self.g_compress.hide_object() - - self.openvideo() - self.makewindow() - self.bindvideo() - if self.use_24: - self.optfullsizewindow() - self.showform() - fl.set_event_call_back(self.do_event) - - def close(self): - self.close_video() - self.close_audio() - self.savedefaults() - raise SystemExit, 0 - - def showform(self): - # Get position of video window - gl.winset(self.window) - x, y = gl.getorigin() - width, height = gl.getsize() - # Calculate position of form window - x1 = x + width + 10 - x2 = x1 + int(self.form.w) - 1 - y2 = y + height - 1 - y1 = y2 - int(self.form.h) + 1 - # Position and show form window - gl.prefposition(x1, x2, y1, y2) - self.form.show_form(FL.PLACE_FREE, FL.TRUE, 'Vb Control') - - def getdefaultdefaults(self): - # Video defaults - self.vfile = 'film.video' - self.vmode = VM_CONT - self.mono_thresh = 128 - self.vformat = 'rgb8' - self.comp_scheme = 'Uncompressed' - self.rgb24_size = 1 - # Missing: drop, rate, maxmem, nframes, rate, vcrspeed - # Audio defaults: - self.afile = 'film.aiff' - self.aformat = A_OFF - - def getdefaults(self): - self.getdefaultdefaults() - # XXXX Read defaults file and override. - try: - fp = open(VB_INIT_FILE, 'r') - except IOError: - print 'Vb: no init file' - self.initcont = {} - return - data = fp.read(1000000) - try: - self.initcont = eval(data) - except: - print 'Vb: Ill-formatted init file' - self.initcont = {} - for k in self.initcont.keys(): - if hasattr(self, k): - setattr(self, k, self.initcont[k]) - - def savedefaults(self): - newdb = {} - for k in VB_INIT_KEYS: - newdb[k] = getattr(self, k) - if newdb <> self.initcont: - try: - fp = open(VB_INIT_FILE, 'w') - except IOError: - print 'Vb: Cannot create', VB_INIT_FILE - return - fp.write(`newdb`) - fp.close() - - def setdefaults(self): - self.getdefaults() - self.vcr = None - self.vout = None - self.capturing = 0 - self.c_vformat.clear_choice() - for label in VideoFormatLabels: - self.c_vformat.addto_choice(label) - self.c_vformat.set_choice(1 + VideoFormats.index(self.vformat)) - self.c_vmode.clear_choice() - for label in VideoModeLabels: - self.c_vmode.addto_choice(label) - self.c_vmode.set_choice(self.vmode) - self.get_vformat() - self.b_drop.set_button(1) - self.in_rate.set_input('2') - self.in_maxmem.set_input('1.0') - self.in_nframes.set_input('0') - self.in_nframes_vcr.set_input('1') - self.in_rate_vcr.set_input('1') - self.c_vcrspeed.clear_choice() - for label in VcrSpeedLabels: - self.c_vcrspeed.addto_choice(label) - self.c_vcrspeed.set_choice(4) - self.c_rgb24_size.clear_choice() - for label in RgbSizeLabels: - self.c_rgb24_size.addto_choice(label) - self.c_rgb24_size.set_choice(self.rgb24_size) - if cl: - algs = cl.QueryAlgorithms(CL.VIDEO) - self.all_comp_schemes = [] - for i in range(0, len(algs), 2): - if algs[i+1] in (CL.COMPRESSOR, CL.CODEC): - self.all_comp_schemes.append(algs[i]) - self.c_cformat.clear_choice() - for label in self.all_comp_schemes: - self.c_cformat.addto_choice(label) - i = self.all_comp_schemes.index(self.comp_scheme) - self.c_cformat.set_choice(i+1) - # Audio defaults - self.aout = None - self.aport = None - self.c_aformat.clear_choice() - for label in AudioFormatLabels: - self.c_aformat.addto_choice(label) - self.c_aformat.set_choice(self.aformat) - self.get_aformat() - - def openvideo(self): - try: - self.video = sv.OpenVideo() - except sv.error, msg: - print 'Error opening video:', msg - self.video = None - param = [SV.BROADCAST, SV.PAL] - if self.video: self.video.GetParam(param) - if param[1] == SV.PAL: - x = SV.PAL_XMAX - y = SV.PAL_YMAX - elif param[1] == SV.NTSC: - x = SV.NTSC_XMAX - y = SV.NTSC_YMAX - else: - print 'Unknown video standard:', param[1] - sys.exit(1) - self.maxx, self.maxy = x, y - self.curx = 256 - self.cury = 256*3/4 - - def makewindow(self): - x, y = self.maxx, self.maxy - gl.foreground() - gl.maxsize(x, y) - gl.keepaspect(x, y) - gl.stepunit(8, 6) - width = self.curx - height = self.cury - if width and height: - # Place the window at (150, 150) from top left - # (the video board likes this location...) - x1 = 150 - x2 = x1+width-1 - SCRHEIGHT = 768 - y2 = SCRHEIGHT-1-150 - y1 = y2-height+1 - gl.prefposition(x1, x2, y1, y2) - self.window = gl.winopen('Vb video') - self.settitle() - if width: - gl.maxsize(x, y) - gl.keepaspect(x, y) - gl.stepunit(8, 6) - gl.winconstraints() - gl.qdevice(DEVICE.LEFTMOUSE) - gl.qdevice(DEVICE.WINQUIT) - gl.qdevice(DEVICE.WINSHUT) - - def optfullsizewindow(self): - if not self.window: - return - gl.winset(self.window) - if self.use_24: - x, y = self.maxx, self.maxy - else: - x, y = self.curx, self.cury - left, bottom = gl.getorigin() - width, height = gl.getsize() - bottom = bottom+height-y - gl.prefposition(left, left+x-1, bottom, bottom+y-1) - gl.winconstraints() - if not self.use_24: - gl.keepaspect(x, y) - gl.stepunit(8, 6) - gl.maxsize(self.maxx, self.maxy) - gl.winconstraints() - self.bindvideo() - - def bindvideo(self): - if not self.video: return - x, y = gl.getsize() - if not self.use_24: - self.curx, self.cury = x, y - self.video.SetSize(x, y) - drop = self.b_drop.get_button() - if drop: - param = [SV.FIELDDROP, 1, SV.GENLOCK, SV.GENLOCK_OFF] - else: - param = [SV.FIELDDROP, 0, SV.GENLOCK, SV.GENLOCK_ON] - if self.rgb: - param = param+[SV.COLOR, SV.DEFAULT_COLOR, \ - SV.DITHER, 1, \ - SV.INPUT_BYPASS, 0] - else: - param = param+[SV.COLOR, SV.MONO, SV.DITHER, 0, \ - SV.INPUT_BYPASS, 1] - self.video.BindGLWindow(self.window, SV.IN_REPLACE) - self.video.SetParam(param) - - def rebindvideo(self): - gl.winset(self.window) - self.bindvideo() - - def reset(self): - self.close_video() - self.close_audio() - if self.vcr: - try: - ok = self.vcr.still() - except VCR.error: - pass - self.vcr = None - self.b_capture.set_button(0) - - # Event handler (catches resize of video window) - - def do_event(self, dev, val): - #print 'Event:', dev, val - if dev in (DEVICE.WINSHUT, DEVICE.WINQUIT): - self.close() - if dev == DEVICE.REDRAW and val == self.window: - self.rebindvideo() - self.settitle() - - # Video controls: format, mode, file - - def cb_vformat(self, *args): - self.reset() - self.get_vformat() - if self.mono_use_thresh: - s = `self.mono_thresh` - s = fl.show_input('Please enter mono threshold', s) - if s: - try: - self.mono_thresh = string.atoi(s) - except string.atoi_error: - fl.show_message('Bad input, using', \ - `self.mono_thresh`, '') - self.rebindvideo() - - def cb_cformat(self, *args): - i = self.c_cformat.get_choice() - self.comp_scheme = self.all_comp_schemes[i-1] - - - def cb_vmode(self, *args): - if self.vcr: - self.vcr = None - self.vmode = self.c_vmode.get_choice() - self.form.freeze_form() - self.g_cont.hide_object() - self.g_burst.hide_object() - self.g_single.hide_object() - self.g_vcr.hide_object() - if self.vmode == VM_CONT: - self.g_cont.show_object() - elif self.vmode == VM_BURST: - self.g_burst.show_object() - elif self.vmode == VM_SINGLE: - self.g_single.show_object() - elif self.vmode == VM_VCR: - self.g_vcr.show_object() - self.form.unfreeze_form() - - def cb_vfile(self, *args): - filename = self.vfile - hd, tl = os.path.split(filename) - filename = fl.file_selector('Video save file:', hd, '', tl) - if filename: - self.reset() - hd, tl = os.path.split(filename) - if hd == os.getcwd(): - filename = tl - self.vfile = filename - - # Video mode specific video controls - - def cb_rate(self, *args): - pass - - def cb_drop(self, *args): - self.rebindvideo() - - def cb_maxmem(self, *args): - pass - - def cb_nframes(self, *args): - pass - - def cb_fps(self, *args): - pass - - def cb_nframes_vcr(self, *args): - pass - - def cb_rate_vcr(self, *args): - pass - - def cb_vcrspeed(self, *args): - pass - - def cb_rgb24_size(self, *args): - i = self.c_rgb24_size.get_choice() - if i: - self.rgb24_size = i - - # Audio controls: format, file - - def cb_aformat(self, *args): - self.get_aformat() - - def cb_afile(self, *args): - filename = self.afile - hd, tl = os.path.split(filename) - filename = fl.file_selector('Audio save file:', hd, '', tl) - if filename: - self.reset() - hd, tl = os.path.split(filename) - if hd == os.getcwd(): - filename = tl - self.afile = filename - - # General controls: capture, reset, play, quit - - def cb_capture(self, *args): - if self.capturing: - raise StopCapture - if not self.b_capture.get_button(): - return - if not self.video or not self.vformat: - gl.ringbell() - return - if self.vmode == VM_CONT: - self.cont_capture() - elif self.vmode == VM_BURST: - self.burst_capture() - elif self.vmode == VM_SINGLE: - self.single_capture(None, None) - elif self.vmode == VM_VCR: - self.vcr_capture() - - def cb_reset(self, *args): - self.reset() - - def cb_play(self, *args): - self.reset() - sts = os.system('Vplay -q ' + self.vfile + ' &') - - def cb_quit(self, *args): - self.close() - - # Capture routines - - def burst_capture(self): - self.setwatch() - gl.winset(self.window) - x, y = gl.getsize() - if self.use_24: - fl.show_message('Sorry, no 24 bit continuous capture yet', '', '') - return - vformat = SV.RGB8_FRAMES - nframes = self.getint(self.in_nframes, 0) - if nframes == 0: - maxmem = self.getint(self.in_maxmem, 1.0) - memsize = int(maxmem * 1024 * 1024) - nframes = self.calcnframes(memsize) - info = (vformat, x, y, nframes, 1) - try: - info2, data, bitvec = self.video.CaptureBurst(info) - except sv.error, msg: - self.b_capture.set_button(0) - self.setarrow() - fl.show_message('Capture error:', str(msg), '') - return - if info <> info2: print info, '<>', info2 - self.save_burst(info2, data, bitvec) - self.setarrow() - - def calcnframes(self, memsize): - gl.winset(self.window) - x, y = gl.getsize() - pixels = x*y - pixels = pixels/2 # XXX always assume fields - if self.mono or self.grey: - n = memsize/pixels - else: - n = memsize/(4*pixels) - return max(1, n) - - def save_burst(self, info, data, bitvec): - (vformat, x, y, nframes, rate) = info - self.open_if_closed() - fieldsize = x*y/2 - nskipped = 0 - realframeno = 0 - tpf = 1000 / 50.0 # XXX - for frameno in range(0, nframes*2): - if frameno <> 0 and \ - bitvec[frameno] == bitvec[frameno-1]: - nskipped = nskipped + 1 - continue - # - # Save field. - # XXX Works only for fields and top-to-bottom - # - start = frameno*fieldsize - field = data[start:start+fieldsize] - realframeno = realframeno + 1 - fn = int(realframeno*tpf) - if not self.write_frame(fn, field): - break - - def cont_capture(self): - saved_label = self.b_capture.label - self.b_capture.label = 'Stop\n' + saved_label - self.open_if_closed() - self.init_cont() - fps = 59.64 # Fields per second - # XXX (fps of Indigo monitor, not of PAL or NTSC!) - tpf = 1000.0 / fps # Time per field in msec - self.capturing = 1 - self.start_audio() - while 1: - try: - void = fl.check_forms() - except StopCapture: - break - try: - cd, id = self.video.GetCaptureData() - except sv.error: - sgi.nap(1) - continue - id = id + 2*self.rate - data = cd.InterleaveFields(1) - cd.UnlockCaptureData() - t = id*tpf - if not self.write_frame(t, data): - break - self.stop_audio() - self.capturing = 0 - self.end_cont() - if self.aout: - # If recording audio, can't capture multiple sequences - self.reset() - self.b_capture.label = saved_label - - def single_capture(self, stepfunc, timecode): - self.open_if_closed() - self.init_cont() - while 1: - try: - cd, id = self.video.GetCaptureData() - break - except sv.error: - pass - sgi.nap(1) - if stepfunc: # This might step the video - d=stepfunc() # to the next frame - if not self.use_24: - data = cd.InterleaveFields(1) - else: - x, y = self.vout.getsize() - if self.use_compress: - if self.rgb24_size == 1: - data = cd.YUVtoYUV422DC(0) - elif self.rgb24_size == 2: - data = cd.YUVtoYUV422DC_quarter(1) - x = x/2 - y = y/2 - elif self.rgb24_size == 3: - data = cd.YUVtoYUV422DC_sixteenth(1) - x = x/4 - y = y/4 - else: - data = cd.YUVtoRGB(1) - if self.maxx*self.maxy*4 <> len(data): - print 'maxx,maxy,exp,got=', self.maxx, - print self.maxy,self.maxx*self.maxy*4, - print len(data) - fl.showmessage('Wrong sized data') - return 0 - if self.rgb24_size <> 1: - data = imageop.scale(data, 4, \ - self.maxx, self.maxy, x, y) - if self.use_jpeg: - import jpeg - data = jpeg.compress(data, x, y, 4) - if self.use_compress: - data = self.compressor.Compress(1, data) - cd.UnlockCaptureData() - self.end_cont() - if timecode == None: - timecode = (self.nframes+1) * (1000/25) - return self.write_frame(timecode, data) - - def vcr_capture(self): - if not self.vcr: - try: - print 'Connecting to VCR ...' - self.vcr = VCR.VCR() - print 'Waiting for VCR to come online ...' - self.vcr.initvcr() - print 'Preparing VCR ...' - if not (self.vcr.fmmode('dnr') and \ - self.vcr.dmcontrol('digital slow')): - self.vcr_error('digital slow failed') - return - print 'VCR OK.' - except VCR.error, msg: - self.vcr = None - self.vcr_error(msg) - return - if not self.vcr.still(): - self.vcr_error('still failed') - return - self.open_if_closed() - rate = self.getint(self.in_rate_vcr, 1) - rate = max(rate, 1) - vcrspeed = self.c_vcrspeed.get_choice() - vcrspeed = VcrSpeeds[vcrspeed] - if vcrspeed == 0: - stepfunc = self.vcr.step - else: - stepfunc = None - self.speed_factor = rate - addr = start_addr = self.vcr.sense() - if not self.single_capture(None, 0): - return - print 'captured %02d:%02d:%02d:%02d' % self.vcr.addr2tc(addr) - count = self.getint(self.in_nframes_vcr, 1) - 1 - if count <= 0: - while rate > 0: - if not self.vcr.step(): - self.vcr_error('step failed') - here = self.vcr.sense() - if here > addr: - rate = rate - (here - addr) - addr = here - return - if not self.vcr.fwdshuttle(vcrspeed): - self.vcr_error('fwd shuttle failed') - return - cycle = 0 - while count > 0: - try: - here = self.vcr.sense() - except VCR.error, msg: - self.vcr_error(msg) - break - if here <> addr: - if here <> addr+1: - print 'Missed', here-addr-1, - print 'frame' + 's'*(here-addr-1 <> 1) - cycle = (cycle+1) % rate - if cycle == 0: - tc = (here-start_addr)*40 - if not self.single_capture(stepfunc, \ - tc): - break - print 'captured %02d:%02d:%02d:%02d' \ - % self.vcr.addr2tc(here) - count = count -1 - addr = here - if self.vcr and not self.vcr.still(): - self.vcr_error('still failed') - - def vcr_error(self, msg): - self.reset() - fl.show_message('VCR error:', str(msg), '') - - # Init/end continuous capture mode - - def init_cont(self): - qsize = 1 - if self.vmode == VM_CONT: - self.rate = self.getint(self.in_rate, 2) - else: - self.rate = 2 - x, y = self.vout.getsize() - if self.use_24: - info = (SV.YUV411_FRAMES, x, y, qsize, self.rate) - else: - info = (SV.RGB8_FRAMES, x, y, qsize, self.rate) - info2 = self.video.InitContinuousCapture(info) - if info2 <> info: - # XXX This is really only debug info - print 'Info mismatch: requested', info, 'got', info2 - - def end_cont(self): - self.video.EndContinuousCapture() - - # Misc stuff - - def settitle(self): - gl.winset(self.window) - x, y = gl.getsize() - title = 'Vb ' + self.vfile + ' (%dx%d)' % (x, y) - gl.wintitle(title) - - def get_vformat(self): - i = self.c_vformat.get_choice() - label = VideoFormatLabels[i-1] - format = VideoFormats[i-1] - if format == 'compress' and cl == None: - fl.show_message('Sorry, no compression library support') - format = '' - label = 'Video off' - self.vformat = format - if self.vformat == '': - self.form.freeze_form() - self.g_video.hide_object() - self.g_cont.hide_object() - self.g_burst.hide_object() - self.g_single.hide_object() - self.form.unfreeze_form() - else: - self.g_video.show_object() - if self.vmode == VM_CONT: - self.g_cont.show_object() - elif self.vmode == VM_BURST: - self.g_burst.show_object() - elif self.vmode == VM_SINGLE: - self.g_single.show_object() - # - self.rgb = (format[:3] == 'rgb' or format == 'compress') - self.mono = (format == 'mono') - self.grey = (format[:4] == 'grey') - self.use_24 = (format in ('rgb', 'jpeg', 'compress')) - if self.use_24: - self.g_rgb24.show_object() - else: - self.g_rgb24.hide_object() - self.use_jpeg = (format == 'jpeg') - self.mono_use_thresh = (label == 'mono thresh') - self.use_compress = (format == 'compress') - if self.use_compress: - self.g_compress.show_object() - else: - self.g_compress.hide_object() - s = format[4:] - if self.grey and s: - self.greybits = string.atoi(s) - else: - self.greybits = 8 - if label == 'grey2 dith': - self.greybits = -2 - # - convertor = None - if self.grey: - if self.greybits == 2: - convertor = imageop.grey2grey2 - elif self.greybits == 4: - convertor = imageop.grey2grey4 - elif self.greybits == -2: - convertor = imageop.dither2grey2 - self.convertor = convertor - self.optfullsizewindow() - - def get_aformat(self): - self.reset() - self.aformat = self.c_aformat.get_choice() - if self.aformat == A_OFF: - self.g_audio.hide_object() - else: - self.g_audio.show_object() - - def init_compressor(self, w, h): - self.compressor = None - scheme = cl.QuerySchemeFromName(CL.VIDEO, self.comp_scheme) - self.compressor = cl.OpenCompressor(scheme) - parambuf = [CL.IMAGE_WIDTH, w, \ - CL.IMAGE_HEIGHT, h, \ - CL.ORIGINAL_FORMAT, CL.YUV422DC] - self.compressor.SetParams(parambuf) - return self.compressor.Compress(0, '') - - def open_if_closed(self): - if not self.vout: - self.open_video() - if not self.aout: - self.open_audio() - - # File I/O handling - - def open_video(self): - self.close_video() - gl.winset(self.window) - x, y = gl.getsize() - if self.use_24: - if self.rgb24_size == 2: - x, y = x/2, y/2 - elif self.rgb24_size == 3: - x, y = x/4, y/4 - vout = VFile.VoutFile(self.vfile) - vout.setformat(self.vformat) - if self.vformat == 'compress': - cheader = self.init_compressor(x, y) - vout.setcompressheader(cheader) - vout.setsize(x, y) - if self.vmode == VM_BURST: - vout.setpf((1, -2)) - vout.writeheader() - self.vout = vout - self.nframes = 0 - self.speed_factor = 1 - self.t_nframes.label = `self.nframes` - - def write_frame(self, t, data): - t = t * self.speed_factor - if not self.vout: - gl.ringbell() - return 0 - if self.convertor: - data = self.convertor(data, len(data), 1) - elif self.mono: - if self.mono_use_thresh: - data = imageop.grey2mono(data, \ - len(data), 1,\ - self.mono_thresh) - else: - data = imageop.dither2mono(data, \ - len(data), 1) - try: - self.vout.writeframe(int(t), data, None) - except IOError, msg: - self.reset() - if msg == (0, 'Error 0'): - msg = 'disk full??' - fl.show_message('IOError', str(msg), '') - return 0 - self.nframes = self.nframes + 1 - self.t_nframes.label = `self.nframes` - return 1 - - def close_video(self): - if not self.vout: - return - self.nframes = 0 - self.t_nframes.label = '' - try: - self.vout.close() - except IOError, msg: - if msg == (0, 'Error 0'): - msg = 'disk full??' - fl.show_message('IOError', str(msg), '') - self.vout = None - self.compressor = None - - # Watch cursor handling - - def setwatch(self): - gl.winset(self.form.window) - gl.setcursor(WATCH, 0, 0) - gl.winset(self.window) - gl.setcursor(WATCH, 0, 0) - - def setarrow(self): - gl.winset(self.form.window) - gl.setcursor(ARROW, 0, 0) - gl.winset(self.window) - gl.setcursor(ARROW, 0, 0) - - # Numeric field handling - - def getint(self, field, default): - try: - value = string.atoi(field.get_input()) - except string.atoi_error: - value = default - field.set_input(`value`) - return value - - def getfloat(self, field, default): - try: - value = float(eval(field.get_input())) - except: - value = float(default) - field.set_input(`value`) - return value - - # Audio stuff - - def open_audio(self): - if self.aformat == A_OFF: - return - import aifc - import al - import AL - import thread - self.close_audio() - params = [AL.INPUT_RATE, 0] - al.getparams(AL.DEFAULT_DEVICE, params) - rate = params[1] - self.aout = aifc.open(self.afile, 'w') - if self.aformat in (A_16_STEREO, A_8_STEREO): - nch = AL.STEREO - else: - nch = AL.MONO - if self.aformat in (A_16_STEREO, A_16_MONO): - width = AL.SAMPLE_16 - else: - width = AL.SAMPLE_8 - self.aout.setnchannels(nch) - self.aout.setsampwidth(width) - self.aout.setframerate(rate) - c = al.newconfig() - c.setqueuesize(8000) - c.setchannels(nch) - c.setwidth(width) - self.aport = al.openport('Vb audio record', 'r', c) - self.audio_stop = 0 - self.audio_ok = 0 - self.audio_busy = 1 - thread.start_new_thread(self.record_audio, ()) - - def start_audio(self): - if self.aformat == A_OFF: - return - self.audio_ok = 1 - - def record_audio(self, *args): - # This function runs in a separate thread - # Currently no semaphores are used - while not self.audio_stop: - data = self.aport.readsamps(4000) - if self.audio_ok: - self.aout.writeframes(data) - data = None - self.audio_busy = 0 - - def stop_audio(self): - self.audio_ok = 0 - - def close_audio(self): - if self.aout: - self.audio_ok = 0 - self.audio_stop = 1 - while self.audio_busy: - time.sleep(0.1) - self.aout.close() - self.aout = None - if self.aport: - self.aport.closeport() - self.aport = None - - -try: - main() -except KeyboardInterrupt: - print '[Interrupt]' - sys.exit(1) diff --git a/Demo/sgi/video/VbForm.fd b/Demo/sgi/video/VbForm.fd deleted file mode 100644 index fd9759fb14..0000000000 --- a/Demo/sgi/video/VbForm.fd +++ /dev/null @@ -1,615 +0,0 @@ -Magic: 12321 - -Internal Form Definition File - (do not change) - -Number of forms: 1 - -=============== FORM =============== -Name: form -Width: 450.000000 -Height: 260.000000 -Number of Objects: 40 - --------------------- -class: 1 -type: 1 -box: 0.000000 0.000000 450.000000 260.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: -callback: -argument: - --------------------- -class: 11 -type: 5 -box: 330.000000 150.000000 110.000015 60.000004 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 1 -size: 11.000000 -lcol: 0 -label: Capture -name: b_capture -callback: cb_capture -argument: 0 - --------------------- -class: 11 -type: 0 -box: 330.000000 10.000000 110.000008 30.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: Quit -name: b_quit -callback: cb_quit -argument: 0 - --------------------- -class: 11 -type: 0 -box: 330.000000 50.000000 110.000000 30.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: Playback -name: b_play -callback: cb_play -argument: 0 - --------------------- -class: 42 -type: 0 -box: 80.000000 220.000000 120.000000 30.000000 -boxtype: 5 -colors: 7 0 -alignment: 2 -style: 0 -size: 11.000000 -lcol: 0 -label: Format: -name: c_vformat -callback: cb_vformat -argument: 0 - --------------------- -class: 11 -type: 0 -box: 330.000000 220.000000 110.000000 30.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: Reset -name: b_reset -callback: cb_reset -argument: 0 - --------------------- -class: 42 -type: 0 -box: 80.000000 50.000000 120.000000 30.000000 -boxtype: 5 -colors: 7 0 -alignment: 2 -style: 0 -size: 11.000000 -lcol: 0 -label: Format: -name: c_aformat -callback: cb_aformat -argument: 0 - --------------------- -class: 10000 -type: 0 -box: 0.000000 0.000000 0.000000 0.000000 -boxtype: 0 -colors: 1668246586 540019308 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: g_audio -callback: -argument: - --------------------- -class: 11 -type: 0 -box: 10.000000 10.000000 190.000000 30.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: Set audio file... -name: b_afile -callback: cb_afile -argument: 0 - --------------------- -class: 20000 -type: 0 -box: 0.000000 0.000000 0.000000 0.000000 -boxtype: 0 -colors: 876099360 892416522 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: -callback: -argument: - --------------------- -class: 10000 -type: 0 -box: 0.000000 0.000000 0.000000 0.000000 -boxtype: 0 -colors: 1147496041 1852404841 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: g_video -callback: -argument: - --------------------- -class: 42 -type: 0 -box: 80.000000 180.000000 120.000000 30.000000 -boxtype: 5 -colors: 7 0 -alignment: 2 -style: 0 -size: 11.000000 -lcol: 0 -label: Mode: -name: c_vmode -callback: cb_vmode -argument: 0 - --------------------- -class: 11 -type: 0 -box: 10.000000 90.000000 190.000000 30.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: Set video file... -name: b_vfile -callback: cb_vfile -argument: 0 - --------------------- -class: 20000 -type: 0 -box: 0.000000 0.000000 0.000000 0.000000 -boxtype: 0 -colors: 544171552 1331849829 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: -callback: -argument: - --------------------- -class: 10000 -type: 0 -box: 0.000000 0.000000 0.000000 0.000000 -boxtype: 0 -colors: 0 0 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: g_single -callback: -argument: - --------------------- -class: 31 -type: 2 -box: 220.000000 150.000000 100.000000 30.000000 -boxtype: 2 -colors: 13 5 -alignment: 0 -style: 0 -size: 11.000000 -lcol: 0 -label: Frames/sec -name: in_fps -callback: cb_fps -argument: 0 - --------------------- -class: 20000 -type: 0 -box: 0.000000 0.000000 0.000000 0.000000 -boxtype: 0 -colors: 0 0 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: -callback: -argument: - --------------------- -class: 10000 -type: 0 -box: 0.000000 0.000000 0.000000 0.000000 -boxtype: 0 -colors: 0 0 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: g_burst -callback: -argument: - --------------------- -class: 31 -type: 1 -box: 220.000000 150.000000 100.000000 30.000000 -boxtype: 2 -colors: 13 5 -alignment: 0 -style: 0 -size: 11.000000 -lcol: 0 -label: Max Mbytes: -name: in_maxmem -callback: cb_maxmem -argument: 0 - --------------------- -class: 31 -type: 2 -box: 220.000000 90.000000 100.000000 30.000000 -boxtype: 2 -colors: 13 5 -alignment: 0 -style: 0 -size: 11.000000 -lcol: 0 -label: Nr. of frames: -name: in_nframes -callback: cb_nframes -argument: 0 - --------------------- -class: 20000 -type: 0 -box: 0.000000 0.000000 0.000000 0.000000 -boxtype: 0 -colors: 0 0 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: -callback: -argument: - --------------------- -class: 10000 -type: 0 -box: 0.000000 0.000000 0.000000 0.000000 -boxtype: 0 -colors: 0 0 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: g_cont -callback: -argument: - --------------------- -class: 31 -type: 2 -box: 250.000000 150.000000 40.000000 30.000000 -boxtype: 2 -colors: 13 5 -alignment: 0 -style: 0 -size: 11.000000 -lcol: 0 -label: Capture rate: -name: in_rate -callback: cb_rate -argument: 0 - --------------------- -class: 2 -type: 0 -box: 220.000000 150.000000 30.000000 30.000000 -boxtype: 0 -colors: 47 47 -alignment: 2 -style: 0 -size: 11.000000 -lcol: 0 -label: 1/ -name: -callback: -argument: - --------------------- -class: 2 -type: 0 -box: 290.000000 150.000000 30.000000 30.000000 -boxtype: 0 -colors: 47 47 -alignment: 2 -style: 0 -size: 11.000000 -lcol: 0 -label: fr -name: -callback: -argument: - --------------------- -class: 13 -type: 0 -box: 220.000000 90.000000 100.000000 30.000000 -boxtype: 0 -colors: 7 3 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: Fielddrop -name: b_drop -callback: cb_drop -argument: 0 - --------------------- -class: 20000 -type: 0 -box: 0.000000 0.000000 0.000000 0.000000 -boxtype: 0 -colors: 0 0 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: -callback: -argument: - --------------------- -class: 2 -type: 0 -box: 330.000000 90.000000 110.000000 30.000002 -boxtype: 2 -colors: 47 47 -alignment: 2 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: t_nframes -callback: -argument: - --------------------- -class: 2 -type: 0 -box: 330.000000 120.000000 110.000000 30.000000 -boxtype: 0 -colors: 47 47 -alignment: 2 -style: 0 -size: 11.000000 -lcol: 0 -label: Frames done: -name: -callback: -argument: - --------------------- -class: 10000 -type: 0 -box: 0.000000 0.000000 0.000000 0.000000 -boxtype: 0 -colors: 640 235 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: g_vcr -callback: -argument: - --------------------- -class: 31 -type: 2 -box: 220.000000 90.000000 100.000000 30.000000 -boxtype: 2 -colors: 13 5 -alignment: 0 -style: 0 -size: 11.000000 -lcol: 0 -label: # frames wtd: -name: in_nframes_vcr -callback: cb_nframes_vcr -argument: 0 - --------------------- -class: 31 -type: 2 -box: 220.000000 150.000000 100.000000 30.000000 -boxtype: 2 -colors: 13 5 -alignment: 0 -style: 0 -size: 11.000000 -lcol: 0 -label: Sample rate: -name: in_rate_vcr -callback: cb_rate_vcr -argument: 0 - --------------------- -class: 42 -type: 0 -box: 220.000000 10.000000 100.000000 30.000000 -boxtype: 5 -colors: 7 0 -alignment: 0 -style: 0 -size: 11.000000 -lcol: 0 -label: VCR speed: -name: c_vcrspeed -callback: cb_vcrspeed -argument: 0 - --------------------- -class: 20000 -type: 0 -box: 0.000000 0.000000 0.000000 0.000000 -boxtype: 0 -colors: 640 235 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: -callback: -argument: - --------------------- -class: 10000 -type: 0 -box: 0.000000 0.000000 0.000000 0.000000 -boxtype: 0 -colors: 58720287 33751040 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: g_rgb24 -callback: -argument: - --------------------- -class: 42 -type: 0 -box: 260.000000 220.000000 60.000000 30.000000 -boxtype: 5 -colors: 7 0 -alignment: 2 -style: 0 -size: 11.000000 -lcol: 0 -label: Size: -name: c_rgb24_size -callback: cb_rgb24_size -argument: 0 - --------------------- -class: 20000 -type: 0 -box: 0.000000 0.000000 0.000000 0.000000 -boxtype: 0 -colors: 0 0 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: -callback: -argument: - --------------------- -class: 10000 -type: 0 -box: 0.000000 0.000000 0.000000 0.000000 -boxtype: 0 -colors: 0 0 -alignment: 4 -style: 0 -size: 10.000000 -lcol: 0 -label: -name: g_compress -callback: -argument: - --------------------- -class: 42 -type: 0 -box: 80.000000 140.000000 120.000000 30.000000 -boxtype: 5 -colors: 7 0 -alignment: 2 -style: 0 -size: 11.000000 -lcol: 0 -label: Scheme: -name: c_cformat -callback: cb_cformat -argument: 0 - --------------------- -class: 20000 -type: 0 -box: 0.000000 0.000000 0.000000 0.000000 -boxtype: 0 -colors: 0 0 -alignment: 4 -style: 0 -size: 10.000000 -lcol: 0 -label: -name: -callback: -argument: - -============================== -create_the_forms diff --git a/Demo/sgi/video/Vcopy.py b/Demo/sgi/video/Vcopy.py deleted file mode 100755 index 59c06a0f69..0000000000 --- a/Demo/sgi/video/Vcopy.py +++ /dev/null @@ -1,291 +0,0 @@ -#! /ufs/guido/bin/sgi/python - -# Universal (non-interactive) CMIF video file copier. - - -# Possibilities: -# -# - Manipulate the time base: -# = resample at a fixed rate -# = divide the time codes by a speed factor (to make it go faster/slower) -# = drop frames that are less than n msec apart (to accomodate slow players) -# - Convert to a different format -# - Magnify (scale) the image - - -# Usage function (keep this up-to-date if you change the program!) - -def usage(): - print 'Usage: Vcopy [options] [infile [outfile]]' - print - print 'Options:' - print - print '-t type : new image type (default unchanged)' - print - print '-M magnify : image magnification factor (default unchanged)' - print '-w width : output image width (default height*4/3 if -h used)' - print '-h height : output image height (default width*3/4 if -w used)' - print - print '-p pf : new x and y packfactor (default unchanged)' - print '-x xpf : new x packfactor (default unchanged)' - print '-y ypf : new y packfactor (default unchanged)' - print - print '-m delta : drop frames closer than delta msec (default 0)' - print '-r delta : regenerate input time base delta msec apart' - print '-s speed : speed change factor (default unchanged)' - print - print 'infile : input file (default film.video)' - print 'outfile : output file (default out.video)' - - -import sys -sys.path.append('/ufs/guido/src/video') - -import VFile -import imgconv -import imageop -import getopt -import string - - -# Global options - -speed = 1.0 -mindelta = 0 -regen = None -newpf = None -newtype = None -magnify = None -newwidth = None -newheight = None - - -# Function to turn a string into a float - -atof_error = 'atof_error' # Exception if it fails - -def atof(s): - try: - return float(eval(s)) - except: - raise atof_error - - -# Main program -- mostly command line parsing - -def main(): - global speed, mindelta, regen, newpf, newtype, \ - magnify, newwidth, newheight - - # Parse command line - try: - opts, args = getopt.getopt(sys.argv[1:], \ - 'M:h:m:p:r:s:t:w:x:y:') - except getopt.error, msg: - sys.stdout = sys.stderr - print 'Error:', msg, '\n' - usage() - sys.exit(2) - - xpf = ypf = None - - # Interpret options - try: - for opt, arg in opts: - if opt == '-M': magnify = atof(arg) - if opt == '-h': height = string.atoi(arg) - if opt == '-m': mindelta = string.atoi(arg) - if opt == '-p': xpf = ypf = string.atoi(arg) - if opt == '-r': regen = string.atoi(arg) - if opt == '-s': speed = atof(arg) - if opt == '-t': newtype = arg - if opt == '-w': newwidth = string.atoi(arg) - if opt == '-x': xpf = string.atoi(arg) - if opt == '-y': ypf = string.atoi(arg) - except string.atoi_error: - sys.stdout = sys.stderr - print 'Option', opt, 'requires integer argument' - sys.exit(2) - except atof_error: - sys.stdout = sys.stderr - print 'Option', opt, 'requires float argument' - sys.exit(2) - - if xpf or ypf: - newpf = (xpf, ypf) - - if newwidth or newheight: - if magnify: - sys.stdout = sys.stderr - print 'Options -w or -h are incompatible with -M' - sys.exit(2) - if not newheight: - newheight = newwidth * 3 / 4 - elif not newwidth: - newwidth = newheight * 4 / 3 - - # Check filename arguments - if len(args) < 1: - args.append('film.video') - if len(args) < 2: - args.append('out.video') - if len(args) > 2: - usage() - sys.exit(2) - if args[0] == args[1]: - sys.stderr.write('Input file can\'t be output file\n') - sys.exit(2) - - # Do the right thing - sts = process(args[0], args[1]) - - # Exit - sys.exit(sts) - - -# Copy one file to another - -def process(infilename, outfilename): - global newwidth, newheight, newpf - - try: - vin = VFile.BasicVinFile(infilename) - except IOError, msg: - sys.stderr.write(infilename + ': I/O error: ' + `msg` + '\n') - return 1 - except VFile.Error, msg: - sys.stderr.write(msg + '\n') - return 1 - except EOFError: - sys.stderr.write(infilename + ': EOF in video file\n') - return 1 - - try: - vout = VFile.BasicVoutFile(outfilename) - except IOError, msg: - sys.stderr.write(outfilename + ': I/O error: ' + `msg` + '\n') - return 1 - - print '=== input file ===' - vin.printinfo() - - vout.setinfo(vin.getinfo()) - - scale = 0 - flip = 0 - decompress = 0 - - vinfmt = vin.format - if vinfmt == 'compress': - if not newtype or newtype == 'compress': - # compressed->compressed: copy compression header - vout.setcompressheader(vin.getcompressheader()) - else: - # compressed->something else: go via rgb-24 - decompress = 1 - vinfmt = 'rgb' - elif newtype == 'compress': - # something else->compressed: not implemented - sys.stderr.write('Sorry, conversion to compressed not yet implemented\n') - return 1 - if newtype: - vout.setformat(newtype) - try: - convert = imgconv.getconverter(vinfmt, vout.format) - except imgconv.error, msg: - sys.stderr.write(str(msg) + '\n') - return 1 - - if newpf: - xpf, ypf = newpf - if not xpf: xpf = vin.xpf - if not ypf: ypf = vout.ypf - newpf = (xpf, ypf) - vout.setpf(newpf) - - if newwidth and newheight: - scale = 1 - - if vin.upside_down <> vout.upside_down or \ - vin.mirror_image <> vout.mirror_image: - flip = 1 - - inwidth, inheight = vin.getsize() - inwidth = inwidth / vin.xpf - inheight = inheight / vin.ypf - - if magnify: - newwidth = int(vout.width * magnify) - newheight = int(vout.height * magnify) - scale = 1 - - if scale: - vout.setsize(newwidth, newheight) - else: - newwidth, newheight = vout.getsize() - - if vin.packfactor <> vout.packfactor: - scale = 1 - - if scale or flip: - if vout.bpp not in (8, 32): - sys.stderr.write('Can\'t scale or flip this type\n') - return 1 - - newwidth = newwidth / vout.xpf - newheight = newheight / vout.ypf - - print '=== output file ===' - vout.printinfo() - vout.writeheader() - - told = 0 - nin = 0 - nout = 0 - tin = 0 - tout = 0 - - while 1: - try: - tin, data, cdata = vin.getnextframe() - except EOFError: - break - if decompress: - data = vin.decompress(data) - nin = nin + 1 - if regen: - tout = nin * regen - else: - tout = tin - tout = int(tout / speed) - if tout - told < mindelta: - continue - told = tout - if newtype: - data = convert(data, inwidth, inheight) - if scale: - data = imageop.scale(data, vout.bpp/8, \ - inwidth, inheight, newwidth, newheight) - if flip: - x0, y0 = 0, 0 - x1, y1 = newwidth-1, newheight-1 - if vin.upside_down <> vout.upside_down: - y1, y0 = y0, y1 - if vin.mirror_image <> vout.mirror_image: - x1, x0 = x0, x1 - data = imageop.crop(data, vout.bpp/8, \ - newwidth, newheight, x0, y0, x1, y1) - print 'Writing frame', nout - vout.writeframe(tout, data, cdata) - nout = nout + 1 - - vout.close() - vin.close() - - -# Don't forget to call the main program - -try: - main() -except KeyboardInterrupt: - print '[Interrupt]' diff --git a/Demo/sgi/video/VcrIndex.py b/Demo/sgi/video/VcrIndex.py deleted file mode 100755 index 80212ee561..0000000000 --- a/Demo/sgi/video/VcrIndex.py +++ /dev/null @@ -1,327 +0,0 @@ -# -# A VCR index. -# -import os -import string - -error='VcrIndex.error' -VERSION_STRING='#!VcrIndex 1.1\n' -PREV_VERSION_STRING='#!VcrIndex 1.0\n' - -class VcrIndex: - def __init__(self, name): - self.curmovie = None - self.curscene = None - self.modified = 0 - self.filename = name - self.basename = os.path.basename(name) - self.editable = [] - if not name: - self.movies = {} - return - try: - fp = open(name, 'r') - except IOError: - self.movies = {} - return - header = fp.readline() - if header == PREV_VERSION_STRING: - print 'Converting old-format database...' - data = fp.read(100000) - self.movies = eval(data) - for m in self.movies.keys(): - d = self.movies[m] - newd = {} - for s in d.keys(): - newsd = {} - newsd['START'] = d[s] - if s == 'START': - s = '-ALL-' - newd[s] = newsd - - self.movies[m] = newd - print 'Done.' - return - if header <> VERSION_STRING: - print 'VcrIndex: incorrect version string:', header - self.movies = {} - return - data = fp.read(100000) - self.movies = eval(data) - # - # Save database to given file (or same file as read from if no - # filename given). - # - def save(self, name): - if not name: - name = self.filename - if not name: - raise error, 'No filename given' - self.filename = name - bupname = name + '~' - try: - os.unlink(bupname) - except os.error: - pass - try: - os.rename(name, bupname) - except os.error: - pass - fp = open(name, 'w') - data = str(self.movies) - fp.write(VERSION_STRING) - fp.write(data) - fp.write('\n') - fp.close() - self.modified = 0 - # - # Get a list of movie names in tape order - # - def get_movienames(self): - names = self.movies.keys() - sorted = [] - for name in names: - sorted.append(self.movies[name]['-ALL-']['START'], name) - sorted.sort() - rv = [] - for pos, name in sorted: - rv.append(name) - return rv - # - # Get a list of scene names in tape order - # - def get_scenenames(self): - if not self.curmovie: - return [] - scenedict = self.movies[self.curmovie] - names = scenedict.keys() - sorted = [] - for name in names: - sorted.append(scenedict[name], name) - sorted.sort() - rv = [] - for pos, name in sorted: - rv.append(name) - return rv - # - # Get a list of scene ids (format '00:02:32:12 name') in tape order - # - def get_sceneids(self): - if not self.curmovie: - return [] - scenedict = self.movies[self.curmovie] - names = scenedict.keys() - sorted = [] - for name in names: - sorted.append(scenedict[name]['START'], name) - sorted.sort() - rv = [] - for pos, name in sorted: - str = '%02d:%02d:%02d:%02d ' % pos - rv.append(str + name) - return rv - # - # Does a movie exist? - # - def movie_exists(self, name): - return self.movies.has_key(name) - # - # Select a movie. - # - def movie_select(self, name): - if not self.movies.has_key(name): - raise error, 'No such movie: '+name - self.curmovie = name - self.curscene = None - # - # Get movie dictionary, or raise an error if no current movie. - # - def _getmoviedict(self): - if not self.curmovie: - raise error, 'No current movie' - return self.movies[self.curmovie] - # - # Rename a movie. - # - def movie_rename(self, newname): - scenedict = self._getmoviedict() - if self.movie_exists(newname): - raise error, 'Movie already exists: '+newname - del self.movies[self.curmovie] - self.movies[newname] = scenedict - self.curmovie = newname - self.modified = 1 - # - # Copy a movie. - # - def movie_copy(self, newname): - scenedict = self._getmoviedict() - if self.movie_exists(newname): - raise error, 'Movie already exists: '+newname - newdict = {} - for k in scenedict.keys(): - olddata = scenedict[k] - newdata = {} - for i in olddata.keys(): - newdata[i] = olddata[i] - newdict[k] = newdata - self.movies[newname] = newdict - self.curmovie = newname - self.modified = 1 - # - # Delete a movie. - # - def movie_delete(self): - if not self.curmovie: - raise error, 'No current movie' - del self.movies[self.curmovie] - self.curmovie = None - self.curscene = None - self.modified = 1 - # - # Create a new movie. - # - def movie_new(self, name, pos): - if self.movie_exists(name): - raise error, 'Movie already exists: '+name - newdict = {} - newsdict = {} - newsdict['START'] = pos - newdict['-ALL-'] = newsdict - self.movies[name] = newdict - self.curmovie = name - self.curscene = None - self.modified = 1 - # - # Does a scene exist? - # - def scene_exists(self, name): - scenedict = self._getmoviedict() - return scenedict.has_key(name) - # - # Select a current scene. - # - def scene_select(self, name): - scenedict = self._getmoviedict() - if not scenedict.has_key(name): - raise error, 'No such scene: '+name - self.curscene = name - # - # Rename a scene. - # - def scene_rename(self, newname): - scenedict = self._getmoviedict() - if not self.curscene: - raise error, 'No current scene' - if scenedict.has_key(newname): - raise error, 'Scene already exists: '+newname - if self.curscene == '-ALL-': - raise error, 'Cannot rename -ALL-' - scenedict[newname] = scenedict[self.curscene] - del scenedict[self.curscene] - self.curscene = newname - self.modified = 1 - # - # Copy a scene. - # - def scene_copy(self, newname): - scenedict = self._getmoviedict() - if not self.curscene: - raise error, 'No current scene' - if scenedict.has_key(newname): - raise error, 'Scene already exists: '+newname - scenedict[newname] = scenedict[self.curscene] - self.curscene = newname - self.modified = 1 - # - # Delete a scene. - # - def scene_delete(self): - scenedict = self._getmoviedict() - if not self.curscene: - raise error, 'No current scene' - if self.curscene == '-ALL-': - raise error, 'Cannot delete -ALL-' - del scenedict[self.curscene] - self.curscene = None - self.modified = 1 - # - # Add a new scene. - # - def scene_new(self, newname, pos): - scenedict = self._getmoviedict() - if scenedict.has_key(newname): - raise error, 'Scene already exists: '+newname - newdict = {} - newdict['START'] = pos - scenedict[newname] = newdict - self.curscene = newname - self.modified = 1 - # - # Get scene data. - # - def _getscenedata(self): - scenedict = self._getmoviedict() - if not self.curscene: - raise error, 'No current scene' - return scenedict[self.curscene] - # - # Data manipulation routines. - # - def pos_get(self): - return self._getscenedata()['START'] - # - def pos_set(self, pos): - data = self._getscenedata() - data['START'] = pos - self.modified = 1 - # - def comment_get(self): - data = self._getscenedata() - if data.has_key('COMMENT'): - return data['COMMENT'] - else: - return '' - # - def comment_set(self, comment): - data = self._getscenedata() - data['COMMENT'] = comment - self.modified = 1 - # - # Get the scene id of the current scene. - # - def get_cursceneid(self): - pos = self._getscenedata()['START'] - str = '%02d:%02d:%02d:%02d ' % pos - return str + self.curscene - # - # Convert a scene id to a scene name. - # - def scene_id2name(self, id): - pos = string.find(id, ' ') - if pos <= 0: - raise error, 'Not a scene id: '+id - return id[pos+1:] - # - # Select a scene given a position. - # - def pos_select(self, pos): - prevmovie = None - movies = self.get_movienames() - for movie in movies: - mpos = self.movies[movie]['-ALL-']['START'] - if mpos > pos: - break - prevmovie = movie - if not prevmovie: - raise error, 'Scene before BOT' - - self.movie_select(prevmovie) - scenes = self.get_scenenames() - scenedict = self._getmoviedict() - prevscene = 'START' - for scene in scenes: - if scenedict[scene]['START'] > pos: - break - prevscene = scene - self.scene_select(prevscene) diff --git a/Demo/sgi/video/Vedit.py b/Demo/sgi/video/Vedit.py deleted file mode 100755 index 228cabc366..0000000000 --- a/Demo/sgi/video/Vedit.py +++ /dev/null @@ -1,301 +0,0 @@ -#! /ufs/guido/bin/sgi/python - -# Edit CMIF movies interactively -- copy one or more files to an output file - - -# XXX To do: -# -# - convert between formats (grey, rgb, rgb8, ...) -# - change size -# - cut out a given area of the image -# - change time base (a la Vtime) - - -import sys -import os -import gl, GL, DEVICE -import fl, FL -import flp -import Viewer -import getopt -import string -import watchcursor - -ARROW = 0 -WATCH = 1 -watchcursor.defwatch(WATCH) - - -def main(): - qsize = 40 - opts, args = getopt.getopt(sys.argv[1:], 'q:') - for o, a in opts: - if o == '-q': - qsize = string.atoi(a) - ed = Editor(qsize) - if args[0:]: - ed.open_input(args[0]) - if args[1:]: - ed.open_output(args[1]) - while 1: - dummy = fl.do_forms() - - -class Editor: - - def __init__(self, qsize): - self.qsize = qsize - self.vin = None - self.vout = None - self.ifile = '' - self.ofile = '' - formdef = flp.parse_form('VeditForm', 'form') - flp.create_full_form(self, formdef) - self.form.show_form(FL.PLACE_SIZE, FL.TRUE, 'Vedit') - fl.set_event_call_back(self.do_event) - - def do_event(self, dev, val): - if dev == DEVICE.REDRAW: - if self.vin: - self.vin.redraw(val) - if self.vout: - self.vout.redraw(val) - - def busy(self): - gl.winset(self.form.window) - gl.setcursor(WATCH, 0, 0) - - def ready(self): - gl.winset(self.form.window) - gl.setcursor(ARROW, 0, 0) - - - def iocheck(self): - self.msg('') - if self.vin == None and self.vout == None: - self.err('Please open input and output files first') - return 0 - return self.icheck() and self.ocheck() - - def icheck(self): - self.msg('') - if self.vin == None: - self.err('Please open an input file first') - return 0 - return 1 - - def ocheck(self): - self.msg('') - if self.vout == None: - self.err('Please open an output file first') - return 0 - return 1 - - - def cb_in_new(self, *args): - self.msg('') - hd, tl = os.path.split(self.ifile) - filename = fl.file_selector('Input video file', hd, '', tl) - if not filename: return - self.open_input(filename) - - def cb_in_close(self, *args): - self.msg('') - self.close_input() - - def cb_in_skip(self, *args): - if not self.icheck(): return - if not self.vin.get(): self.err('End of input file') - self.ishow() - - def cb_in_back(self, *args): - if not self.icheck(): return - if not self.vin.backup(): self.err('Begin of input file') - self.ishow() - - def cb_in_slider(self, *args): - if not self.icheck(): return - left, pos, right = self.vin.qinfo() - i = int(self.in_slider.get_slider_value()) - i = max(i, left) - i = min(i, right) - if i == pos: return - if not self.vin.seek(i): - self.err('Input seek failed') - self.ishow() - - def cb_in_rewind(self, *args): - if not self.icheck(): return - self.vin.rewind() - self.ishow() - - - def cb_copy(self, *args): - if not self.iocheck(): return - data = self.vin.get() - if not data: - self.err('End of input file') - self.ishow() - return - if self.vout.getinfo() <> self.vin.getinfo(): - print 'Copying info...' - self.vout.setinfo(self.vin.getinfo()) - if self.vin.format == 'compress': - self.vout.setcompressheader(\ - self.vin.getcompressheader()) - self.vout.put(data) - self.oshow() - self.ishow() - - def cb_uncopy(self, *args): - if not self.iocheck(): return - if not self.vout.backup(): - self.err('Output buffer exhausted') - return - self.oshow() - if not self.vin.backup(): - self.err('Begin of input file') - return - self.ishow() - - - def cb_out_new(self, *args): - self.msg('') - hd, tl = os.path.split(self.ofile) - filename = fl.file_selector('Output video file', hd, '', tl) - if not filename: return - self.open_output(filename) - - def cb_out_close(self, *args): - self.msg('') - self.close_output() - - def cb_out_skip(self, *args): - if not self.ocheck(): return - if not self.vout.forward(): self.err('Output buffer exhausted') - self.oshow() - - def cb_out_back(self, *args): - if not self.ocheck(): return - if not self.vout.backup(): self.err('Output buffer exhausted') - self.oshow() - - def cb_out_slider(self, *args): - if not self.ocheck(): return - i = int(self.out_slider.get_slider_value()) - left, pos, right = self.vout.qinfo() - i = int(self.out_slider.get_slider_value()) - i = max(i, left) - i = min(i, right) - if i == pos: return - if not self.vout.seek(i): - self.err('Output seek failed') - self.oshow() - - def cb_out_trunc(self, *arcs): - if not self.ocheck(): return - self.vout.trunc() - self.oshow() - - def cb_out_rewind(self, *args): - if not self.ocheck(): return - self.vout.rewind() - self.oshow() - - - def cb_quit(self, *args): - self.close_input() - self.close_output() - sys.exit(0) - - - def open_input(self, filename): - self.ifile = filename - basename = os.path.split(filename)[1] - title = 'in: ' + basename - try: - vin = Viewer.InputViewer(filename, title) - except: - self.err('Can\'t open input file', filename) - return - self.close_input() - self.vin = vin - self.in_file.label = basename - self.ishow() - - def close_input(self): - if self.vin: - self.busy() - self.msg('Closing input file...') - self.vin.close() - self.ready() - self.msg('') - self.vin = None - self.in_file.label = '(none)' - self.format('in') - - def ishow(self): - self.vin.show() - self.format('in') - - def open_output(self, filename): - self.ofile = filename - basename = os.path.split(filename)[1] - title = 'out: ' + basename - try: - vout = Viewer.OutputViewer(filename, \ - title, self.qsize) - except: - self.err('Can\'t open output file', filename) - return - self.close_output() - self.vout = vout - self.out_file.label = basename - if self.vin: - self.vout.setinfo(self.vin.getinfo()) - self.oshow() - - def close_output(self): - if self.vout: - self.busy() - self.msg('Closing output file...') - self.vout.close() - self.ready() - self.msg('') - self.vout = None - self.out_file.label = '(none)' - self.format('out') - - def oshow(self): - self.vout.show() - self.format('out') - - - def msg(self, *args): - str = string.strip(string.join(args)) - self.msg_area.label = str - - def err(self, *args): - gl.ringbell() - apply(self.msg, args) - - def format(self, io): - v = getattr(self, 'v' + io) - if v == None: - left = right = pos = 0 - else: - left, pos, right = v.qinfo() - getattr(self, io + '_info1').label = `left` - getattr(self, io + '_info2').label = `pos` - getattr(self, io + '_info3').label = `right` - sl = getattr(self, io + '_slider') - sl.freeze_object() - sl.set_slider_bounds(left, right) - sl.set_slider_value(pos) - sl.unfreeze_object() - - -try: - main() -except KeyboardInterrupt: - print '[Interrupt]' diff --git a/Demo/sgi/video/VeditForm.fd b/Demo/sgi/video/VeditForm.fd deleted file mode 100644 index ba59de4d4f..0000000000 --- a/Demo/sgi/video/VeditForm.fd +++ /dev/null @@ -1,435 +0,0 @@ -Magic: 12321 - -Internal Form Definition File - (do not change) - -Number of forms: 1 - -=============== FORM =============== -Name: form -Width: 510.000000 -Height: 350.000000 -Number of Objects: 28 - --------------------- -class: 1 -type: 1 -box: 0.000000 0.000000 510.000000 350.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: -callback: -argument: - --------------------- -class: 1 -type: 6 -box: 10.000000 130.000000 240.000000 209.999985 -boxtype: 6 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: -callback: -argument: - --------------------- -class: 1 -type: 6 -box: 260.000000 130.000000 240.000000 209.999985 -boxtype: 6 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: -callback: -argument: - --------------------- -class: 2 -type: 0 -box: 10.000000 10.000000 430.000000 30.000000 -boxtype: 6 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: CMIF Video Editor, by Guido van Rossum -name: msg_area -callback: -argument: - --------------------- -class: 11 -type: 4 -box: 200.000000 90.000000 120.000000 30.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -> Copy -> -name: -callback: cb_copy -argument: 0 - --------------------- -class: 11 -type: 4 -box: 210.000000 220.000000 30.000000 30.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: @> -name: -callback: cb_in_skip -argument: 0 - --------------------- -class: 11 -type: 0 -box: 20.000000 140.000000 220.000000 30.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: Rewind -name: -callback: cb_in_rewind -argument: 0 - --------------------- -class: 11 -type: 0 -box: 270.000000 140.000000 100.000000 30.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: Reset -name: -callback: cb_out_rewind -argument: 0 - --------------------- -class: 11 -type: 0 -box: 20.000000 260.000000 160.000000 30.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: New input file... -name: -callback: cb_in_new -argument: 0 - --------------------- -class: 11 -type: 0 -box: 330.000000 260.000000 160.000000 30.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: New output file... -name: -callback: cb_out_new -argument: 0 - --------------------- -class: 2 -type: 0 -box: 20.000000 300.000000 220.000000 30.000000 -boxtype: 6 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: (none) -name: in_file -callback: -argument: - --------------------- -class: 2 -type: 0 -box: 270.000000 300.000000 220.000000 30.000000 -boxtype: 6 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: (none) -name: out_file -callback: -argument: - --------------------- -class: 11 -type: 0 -box: 450.000000 10.000000 50.000000 30.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: Quit -name: -callback: cb_quit -argument: 0 - --------------------- -class: 11 -type: 4 -box: 270.000000 220.000000 30.000000 30.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: @< -name: -callback: cb_out_back -argument: 0 - --------------------- -class: 11 -type: 4 -box: 20.000000 220.000000 30.000000 30.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: @< -name: -callback: cb_in_back -argument: 0 - --------------------- -class: 11 -type: 4 -box: 460.000000 220.000000 30.000000 30.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: @> -name: -callback: cb_out_skip -argument: 0 - --------------------- -class: 11 -type: 4 -box: 200.000000 50.000000 120.000000 30.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: Uncopy -name: -callback: cb_uncopy -argument: 0 - --------------------- -class: 11 -type: 0 -box: 190.000000 260.000000 50.000000 30.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: Close -name: -callback: cb_in_close -argument: 0 - --------------------- -class: 11 -type: 0 -box: 270.000000 260.000000 50.000000 30.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: Close -name: -callback: cb_out_close -argument: 0 - --------------------- -class: 21 -type: 1 -box: 60.000000 220.000000 140.000000 30.000000 -boxtype: 2 -colors: 47 47 -alignment: 1 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: in_slider -callback: cb_in_slider -argument: 0 - --------------------- -class: 21 -type: 1 -box: 310.000000 220.000000 140.000000 30.000000 -boxtype: 2 -colors: 47 47 -alignment: 1 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: out_slider -callback: cb_out_slider -argument: 0 - --------------------- -class: 2 -type: 0 -box: 20.000000 180.000000 30.000000 30.000000 -boxtype: 6 -colors: 47 47 -alignment: 4 -style: 0 -size: 8.000000 -lcol: 0 -label: -name: in_info1 -callback: -argument: - --------------------- -class: 2 -type: 0 -box: 100.000000 180.000000 60.000004 30.000000 -boxtype: 6 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: in_info2 -callback: -argument: - --------------------- -class: 2 -type: 0 -box: 210.000000 180.000000 30.000000 30.000000 -boxtype: 6 -colors: 47 47 -alignment: 4 -style: 0 -size: 8.000000 -lcol: 0 -label: -name: in_info3 -callback: -argument: - --------------------- -class: 2 -type: 0 -box: 270.000000 180.000000 30.000000 30.000000 -boxtype: 6 -colors: 47 47 -alignment: 4 -style: 0 -size: 8.000000 -lcol: 0 -label: -name: out_info1 -callback: -argument: - --------------------- -class: 2 -type: 0 -box: 350.000000 180.000000 60.000004 30.000000 -boxtype: 6 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: -name: out_info2 -callback: -argument: - --------------------- -class: 2 -type: 0 -box: 460.000000 180.000000 30.000000 30.000000 -boxtype: 6 -colors: 47 47 -alignment: 4 -style: 0 -size: 8.000000 -lcol: 0 -label: -name: out_info3 -callback: -argument: - --------------------- -class: 11 -type: 0 -box: 390.000000 140.000000 100.000000 30.000000 -boxtype: 1 -colors: 47 47 -alignment: 4 -style: 0 -size: 11.000000 -lcol: 0 -label: Truncate -name: -callback: cb_out_trunc -argument: 0 - -============================== -create_the_forms diff --git a/Demo/sgi/video/Vfix.py b/Demo/sgi/video/Vfix.py deleted file mode 100755 index 6b2602399c..0000000000 --- a/Demo/sgi/video/Vfix.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/ufs/guido/bin/sgi/python - -# Copy a video file, fixing the line width to be a multiple of 4 - - -# Usage: -# -# Vfix [infile [outfile]] - - -# Options: -# -# infile : input file (default film.video) -# outfile : output file (default out.video) - - -import sys -import imageop -sys.path.append('/ufs/guido/src/video') -import VFile - - -# Main program -- mostly command line parsing - -def main(): - args = sys.argv[1:] - if len(args) < 1: - args.append('film.video') - if len(args) < 2: - args.append('out.video') - if len(args) > 2: - sys.stderr.write('usage: Vfix [infile [outfile]]\n') - sys.exit(2) - sts = process(args[0], args[1]) - sys.exit(sts) - - -# Copy one file to another - -def process(infilename, outfilename): - try: - vin = VFile.BasicVinFile(infilename) - except IOError, msg: - sys.stderr.write(infilename + ': I/O error: ' + `msg` + '\n') - return 1 - except VFile.Error, msg: - sys.stderr.write(msg + '\n') - return 1 - except EOFError: - sys.stderr.write(infilename + ': EOF in video file\n') - return 1 - - try: - vout = VFile.BasicVoutFile(outfilename) - except IOError, msg: - sys.stderr.write(outfilename + ': I/O error: ' + `msg` + '\n') - return 1 - - info = vin.getinfo() - if info[0] <> 'grey': - sys.stderr.write('Vfix: input not in grey format\n') - return 1 - vout.setinfo(info) - inwidth, height = vin.getsize() - pf = vin.packfactor - if (inwidth/pf)%4 == 0: - sys.stderr.write('Vfix: fix not necessary\n') - return 1 - outwidth = (inwidth/pf/4)*4*pf - print 'inwidth =', inwidth, 'outwidth =', outwidth - vout.setsize(outwidth, height) - vout.writeheader() - n = 0 - try: - while 1: - t, data, cdata = vin.getnextframe() - n = n + 1 - sys.stderr.write('Frame ' + `n` + '...') - data = imageop.crop(data, 1, inwidth/pf, height/pf, \ - 0, 0, outwidth/pf-1, height/pf-1) - vout.writeframe(t, data, None) - sys.stderr.write('\n') - except EOFError: - pass - return 0 - - -# Don't forget to call the main program - -main() diff --git a/Demo/sgi/video/Viewer.py b/Demo/sgi/video/Viewer.py deleted file mode 100755 index 07cba54cec..0000000000 --- a/Demo/sgi/video/Viewer.py +++ /dev/null @@ -1,255 +0,0 @@ -import gl, GL -import VFile -import os - - -class InputViewer: - - def __init__(self, filename, title, *args): - try: - self.vin = VFile.VinFile(filename) - except (EOFError, VFile.Error): - raise IOError, 'bad video input file' - self.vin.warmcache() - if not title: - title = os.path.split(filename)[1] - self.filename = filename - self.title = title - self.qsize = len(self.vin.index) - gl.foreground() - gl.prefsize(self.vin.width, self.vin.height) - self.wid = -1 - self.reset() - - def close(self): - self.vin.close() - if self.wid > 0: - gl.winclose(self.wid) - - def rewind(self): - self.vin.rewind() - self.reset() - - def getinfo(self): - return self.vin.getinfo() - - # Internal - def reset(self): - if self.wid > 0: - gl.winset(self.wid) - gl.clear() - self.vin.initcolormap() - self.qindex = 0 - - def show(self): - if self.wid < 0: - gl.foreground() - gl.prefsize(self.vin.width, self.vin.height) - self.wid = gl.winopen(self.title) - gl.clear() - self.vin.initcolormap() - gl.winset(self.wid) - if self.qindex >= self.qsize: - self.vin.clear() - return - dt, d, cd = self.vin.getrandomframe(self.qindex) - self.vin.showframe(d, cd) - - def redraw(self, wid): - if wid == self.wid >= 0: - gl.winset(self.wid) - gl.reshapeviewport() - self.vin.clear() - self.show() - - def get(self): - if self.qindex >= self.qsize: - return None - if self.qindex > 0: - prevt, ds, cs = \ - self.vin.getrandomframeheader(self.qindex-1) - else: - prevt = 0 - t, data, cdata = self.vin.getrandomframe(self.qindex) - self.qindex = self.qindex + 1 - return t-prevt, data, cdata - - def backup(self): - if self.qindex == 0: - return 0 - self.qindex = self.qindex - 1 - return 1 - - def seek(self, i): - if not 0 <= i <= self.qsize: - return 0 - self.qindex = i - return 1 - - def tell(self): - return self.qindex - - def qsizes(self): - return self.qindex, self.qsize - self.qindex - - def qinfo(self): - return 0, self.qindex, self.qsize - - -class OutputViewer: - - def __init__(self, filename, title, qsize): - try: - self.vout = VFile.VoutFile(filename) - except (EOFError, VFile.Error): - raise IOError, 'bad video output file' - if not title: - title = os.path.split(filename)[1] - self.filename = filename - self.title = title - self.qsize = qsize - gl.foreground() - self.wid = -1 - self.reset() - - def close(self): - while self.queue: - self.flushq() - self.vout.close() - if self.wid > 0: - gl.winclose(self.wid) - - def rewind(self): - info = self.vout.getinfo() - self.vout.close() - self.vout = VFile.VoutFile(self.filename) - self.vout.setinfo(info) - self.reset() - - def getinfo(self): - return self.vout.getinfo() - - def setinfo(self, info): - if info == self.getinfo(): return # No change - self.vout.setinfo(info) - if self.wid > 0: - gl.winclose(self.wid) - self.wid = -1 - - # Internal - def reset(self): - if self.wid > 0: - gl.winset(self.wid) - gl.clear() - self.vout.initcolormap() - self.queue = [] - self.spares = [] - self.written = 0 - self.lastt = 0 - - # Internal - def flushq(self): - if self.written == 0: - self.vout.writeheader() - dt, d, cd = self.queue[0] - self.lastt = self.lastt + dt - self.vout.writeframe(self.lastt, d, cd) - del self.queue[0] - self.written = self.written + 1 - - def show(self): - if self.wid < 0: - gl.foreground() - gl.prefsize(self.vout.width, self.vout.height) - self.wid = gl.winopen(self.title) - gl.clear() - self.vout.initcolormap() - gl.winset(self.wid) - if not self.queue: - self.vout.clear() - return - dt, d, cd = self.queue[-1] - self.vout.showframe(d, cd) - - def redraw(self, wid): - if wid == self.wid >= 0: - gl.winset(self.wid) - gl.reshapeviewport() - self.vout.clear() - self.show() - - def backup(self): - if len(self.queue) < 1: return 0 - self.spares.insert(0, self.queue[-1]) - del self.queue[-1] - return 1 - - def forward(self): - if not self.spares: return 0 - self.queue.append(self.spares[0]) - del self.spares[0] - return 1 - - def put(self, item): - self.queue.append(item) - self.spares = [] - while len(self.queue) > self.qsize: - self.flushq() - - def seek(self, i): - i = i - self.written - if not 0 <= i <= len(self.queue) + len(self.spares): - return 0 - while i < len(self.queue): - if not self.backup(): - return 0 - while i > len(self.queue): - if not self.forward(): - return 0 - return 1 - - def trunc(self): - del self.spares[:] - - def tell(self): - return self.written + len(self.queue) - - def qsizes(self): - return len(self.queue), len(self.spares) - - def qinfo(self): - first = self.written - pos = first + len(self.queue) - last = pos + len(self.spares) - return first, pos, last - - -def test(): - import sys - a = InputViewer(sys.argv[1], '') - b = OutputViewer(sys.argv[2], '') - b.setinfo(a.getinfo()) - - while 1: - a.show() - data = a.get() - if data is None: - break - b.put(data) - b.show() - - while a.backup(): - data = a.get() - b.put(data) - b.show() - if a.backup(): a.show() - - while 1: - data = a.get() - if data is None: - break - b.put(data) - b.show() - a.show() - - b.close() diff --git a/Demo/sgi/video/Vinfo.py b/Demo/sgi/video/Vinfo.py deleted file mode 100755 index c4177dc842..0000000000 --- a/Demo/sgi/video/Vinfo.py +++ /dev/null @@ -1,174 +0,0 @@ -#! /ufs/guido/bin/sgi/python - -# Print some info about a CMIF movie file - - -# Usage: -# -# Vinfo [-d] [-q] [-s] [-t] [file] ... - - -# Options: -# -# -d : print deltas between frames instead of frame times -# -q : quick: don't read the frames -# -s : don't print times (but do count frames and print the total) -# -t : terse (one line/file, implies -s) -# file ... : file(s) to inspect; default film.video - - -import sys -sys.path.append('/ufs/guido/src/video') -import VFile -import getopt -import string - - -# Global options - -short = 0 -quick = 0 -delta = 0 -terse = 0 -maxwidth = 10 - - -# Main program -- mostly command line parsing - -def main(): - global short, quick, delta, terse, maxwidth - try: - opts, args = getopt.getopt(sys.argv[1:], 'dqst') - except getopt.error, msg: - sys.stdout = sys.stderr - print msg - print 'usage: Vinfo [-d] [-q] [-s] [-t] [file] ...' - sys.exit(2) - for opt, arg in opts: - if opt == '-q': - quick = 1 - if opt == '-d': - delta = 1 - if opt == '-s': - short = 1 - if opt == '-t': - terse = short = 1 - if not args: - args = ['film.video'] - for filename in args: - maxwidth = max(maxwidth, len(filename)) - sts = 0 - for filename in args: - if process(filename): - sts = 1 - sys.exit(sts) - - -# Process one file - -def process(filename): - try: - vin = VFile.RandomVinFile(filename) - except IOError, msg: - sys.stderr.write(filename + ': I/O error: ' + `msg` + '\n') - return 1 - except VFile.Error, msg: - sys.stderr.write(msg + '\n') - return 1 - except EOFError: - sys.stderr.write(filename + ': EOF in video file\n') - return 1 - - if terse: - print string.ljust(filename, maxwidth), - kbytes = (VFile.getfilesize(filename) + 1023) / 1024 - print string.rjust(`kbytes`, 5) + 'K', - print ' ', string.ljust(`vin.version`, 5), - print string.ljust(vin.format, 8), - print string.rjust(`vin.width`, 4), - print string.rjust(`vin.height`, 4), - if type(vin.packfactor) == type(()): - xpf, ypf = vin.packfactor - s = string.rjust(`xpf`, 2) + ',' + \ - string.rjust(`ypf`, 2) - else: - s = string.rjust(`vin.packfactor`, 2) - if type(vin.packfactor) == type(0) and \ - vin.format not in ('rgb', 'jpeg') and \ - (vin.width/vin.packfactor) % 4 <> 0: - s = s + '! ' - else: - s = s + ' ' - print s, - sys.stdout.flush() - else: - vin.printinfo() - - if quick: - if terse: - print - vin.close() - return 0 - - try: - vin.readcache() - if not terse: - print '[Using cached index]' - except VFile.Error: - if not terse: - print '[Constructing index on the fly]' - - if not short: - if delta: - print 'Frame time deltas:', - else: - print 'Frame times:', - - n = 0 - t = 0 - told = 0 - datasize = 0 - while 1: - try: - t, ds, cs = vin.getnextframeheader() - vin.skipnextframedata(ds, cs) - except EOFError: - break - datasize = datasize + ds - if cs: datasize = datasize + cs - if not short: - if n%8 == 0: - sys.stdout.write('\n') - if delta: - sys.stdout.write('\t' + `t - told`) - told = t - else: - sys.stdout.write('\t' + `t`) - n = n+1 - - if not short: print - - if terse: - print string.rjust(`n`, 6), - if t: print string.rjust(`int(n*10000.0/t)*0.1`, 5), - print - else: - print 'Total', n, 'frames in', t*0.001, 'sec.', - if t: print '-- average', int(n*10000.0/t)*0.1, 'frames/sec', - print - print 'Total data', 0.1 * int(datasize / 102.4), 'Kbytes', - if t: - print '-- average', - print 0.1 * int(datasize / 0.1024 / t), 'Kbytes/sec', - print - - vin.close() - return 0 - - -# Don't forget to call the main program - -try: - main() -except KeyboardInterrupt: - print '[Interrupt]' diff --git a/Demo/sgi/video/Vmkjpeg.py b/Demo/sgi/video/Vmkjpeg.py deleted file mode 100755 index 4e4c28ebf4..0000000000 --- a/Demo/sgi/video/Vmkjpeg.py +++ /dev/null @@ -1,92 +0,0 @@ -#!/ufs/guido/bin/sgi/python - -# Compress an rgb or grey video file to jpeg format - - -# Usage: -# -# Vmkjpeg [infile [outfile]] - - -# Options: -# -# infile : input file (default film.video) -# outfile : output file (default out.video) - - -import sys -import jpeg -sys.path.append('/ufs/guido/src/video') -import VFile - - -# Main program -- mostly command line parsing - -def main(): - args = sys.argv[1:] - if len(args) < 1: - args.append('film.video') - if len(args) < 2: - args.append('out.video') - if len(args) > 2: - sys.stderr.write('usage: Vmkjpeg [infile [outfile]]\n') - sys.exit(2) - sts = process(args[0], args[1]) - sys.exit(sts) - - -# Copy one file to another - -def process(infilename, outfilename): - try: - vin = VFile.BasicVinFile(infilename) - except IOError, msg: - sys.stderr.write(infilename + ': I/O error: ' + `msg` + '\n') - return 1 - except VFile.Error, msg: - sys.stderr.write(msg + '\n') - return 1 - except EOFError: - sys.stderr.write(infilename + ': EOF in video file\n') - return 1 - - try: - vout = VFile.BasicVoutFile(outfilename) - except IOError, msg: - sys.stderr.write(outfilename + ': I/O error: ' + `msg` + '\n') - return 1 - - info = vin.getinfo() - if info[0] == 'rgb': - width, height = vin.getsize() - bytes = 4 - format = 'jpeg' - elif info[0] == 'grey': - width, height = vin.getsize() - pf = vin.packfactor - width, height = width / pf, height / pf - bytes = 1 - format = 'jpeggrey' - else: - sys.stderr.write('Vmkjpeg: input not in rgb or grey format\n') - return 1 - info = (format,) + info[1:] - vout.setinfo(info) - vout.writeheader() - n = 0 - try: - while 1: - t, data, cdata = vin.getnextframe() - n = n + 1 - sys.stderr.write('Frame ' + `n` + '...') - data = jpeg.compress(data, width, height, bytes) - vout.writeframe(t, data, None) - sys.stderr.write('\n') - except EOFError: - pass - return 0 - - -# Don't forget to call the main program - -main() diff --git a/Demo/sgi/video/Vplay.py b/Demo/sgi/video/Vplay.py deleted file mode 100755 index 05cff6d6ef..0000000000 --- a/Demo/sgi/video/Vplay.py +++ /dev/null @@ -1,354 +0,0 @@ -#! /ufs/guido/bin/sgi/python - -# Play CMIF movie files - - -# Help function - -def help(): - print 'Usage: Vplay [options] [file] ...' - print - print 'Options:' - print '-M magnify : magnify the image by the given factor' - print '-d : write some debug stuff on stderr' - print '-l : loop, playing the movie over and over again' - print '-m delta : drop frames closer than delta msec (default 0)' - print '-n : don\'t wait after each file' - print '-q : quiet, no informative messages' - print '-r delta : regenerate input time base delta msec apart' - print '-s speed : speed change factor (default 1.0)' - print '-t : use a 2nd thread for read-ahead' - print '-x left : window offset from left of screen' - print '-y top : window offset from top of screen' - print '-w width : window width' - print '-h height : window height' - print '-b color : background color (white,black or (r,g,b))' - print 'file ... : file(s) to play; default film.video' - print - print 'User interface:' - print 'Press the left mouse button to stop or restart the movie.' - print 'Press ESC or use the window manager Close or Quit command' - print 'to close the window and play the next file (if any).' - - -# Imported modules - -import sys -sys.path.append('/ufs/guido/src/video') # Increase chance of finding VFile -import VFile -import time -import gl, GL -from DEVICE import REDRAW, ESCKEY, LEFTMOUSE, WINSHUT, WINQUIT -import getopt -import string - - -# Global options - -debug = 0 -looping = 0 -magnify = 1 -mindelta = 0 -nowait = 0 -quiet = 0 -regen = None -speed = 1.0 -threading = 0 -xoff = yoff = None -xwsiz = ywsiz = None -bgcolor = None - - -# Main program -- mostly command line parsing - -def main(): - global debug, looping, magnify, mindelta, nowait, quiet, regen, speed - global threading, xoff, yoff, xwsiz, ywsiz, bgcolor - - # Parse command line - try: - opts, args = getopt.getopt(sys.argv[1:], \ - 'M:dlm:nqr:s:tx:y:w:h:b:') - except getopt.error, msg: - sys.stdout = sys.stderr - print 'Error:', msg, '\n' - help() - sys.exit(2) - - # Interpret options - try: - for opt, arg in opts: - if opt == '-M': magnify = float(eval(arg)) - if opt == '-d': debug = debug + 1 - if opt == '-l': looping = 1 - if opt == '-m': mindelta = string.atoi(arg) - if opt == '-n': nowait = 1 - if opt == '-q': quiet = 1 - if opt == '-r': regen = string.atoi(arg) - if opt == '-s': - try: - speed = float(eval(arg)) - except: - sys.stdout = sys.stderr - print 'Option -s needs float argument' - sys.exit(2) - if opt == '-t': - try: - import thread - threading = 1 - except ImportError: - print 'Sorry, this version of Python', - print 'does not support threads:', - print '-t ignored' - if opt == '-x': xoff = string.atoi(arg) - if opt == '-y': yoff = string.atoi(arg) - if opt == '-w': xwsiz = string.atoi(arg) - if opt == '-h': ywsiz = string.atoi(arg) - if opt == '-b': - if arg == 'black': - bgcolor = (0,0,0) - elif arg == 'white': - bgcolor = (255,255,255) - else: - try: - bgcolor = eval(arg) - xxr, xxg, xxb = bgcolor - except: - print '-b needs (r,g,b) tuple' - sys.exit(2) - except string.atoi_error: - sys.stdout = sys.stderr - print 'Option', opt, 'requires integer argument' - sys.exit(2) - - # Check validity of certain options combinations - if nowait and looping: - print 'Warning: -n and -l are mutually exclusive; -n ignored' - nowait = 0 - if xoff <> None and yoff == None: - print 'Warning: -x without -y ignored' - if xoff == None and yoff <> None: - print 'Warning: -y without -x ignored' - - # Process all files - if not args: args = ['film.video'] - sts = 0 - for filename in args: - sts = (process(filename) or sts) - - # Exit with proper exit status - sys.exit(sts) - - -# Process one movie file - -def process(filename): - try: - vin = VFile.VinFile(filename) - except IOError, msg: - sys.stderr.write(filename + ': I/O error: ' + `msg` + '\n') - return 1 - except VFile.Error, msg: - sys.stderr.write(msg + '\n') - return 1 - except EOFError: - sys.stderr.write(filename + ': EOF in video header\n') - return 1 - - if not quiet: - vin.printinfo() - - gl.foreground() - - width, height = int(vin.width * magnify), int(vin.height * magnify) - xborder = yborder = 0 - if xwsiz: - vin.xorigin = (xwsiz - width)/2 - width = xwsiz - if ywsiz: - vin.yorigin = (ywsiz - height)/2 - height = ywsiz - if xoff <> None and yoff <> None: - scrheight = gl.getgdesc(GL.GD_YPMAX) - gl.prefposition(xoff, xoff+width-1, \ - scrheight-yoff-height, scrheight-yoff-1) - else: - gl.prefsize(width, height) - - win = gl.winopen(filename) - gl.clear() - - if quiet: vin.quiet = 1 - vin.initcolormap() - - if bgcolor: - r, g, b = bgcolor - vin.clearto(r,g,b) - - gl.qdevice(ESCKEY) - gl.qdevice(WINSHUT) - gl.qdevice(WINQUIT) - gl.qdevice(LEFTMOUSE) - - stop = 0 - - while not stop: - gl.wintitle(filename) - stop = (playonce(vin) or nowait) - gl.wintitle('(done) ' + filename) - if not looping: - while not stop: - dev, val = gl.qread() - if dev == REDRAW: - if bgcolor: - r,g,b = bgcolor - vin.clearto(r,g,b) - else: - vin.clear() - if dev == LEFTMOUSE and val == 1: - break # Continue outer loop - if dev == ESCKEY and val == 1 or \ - dev in (WINSHUT, WINQUIT): - stop = 1 - - # Set xoff, yoff for the next window from the current window - global xoff, yoff - xoff, yoff = gl.getorigin() - width, height = gl.getsize() - scrheight = gl.getgdesc(GL.GD_YPMAX) - yoff = scrheight - yoff - height - gl.winclose(win) - - return 0 - - -# Play a movie once; return 1 if user wants to stop, 0 if not - -def playonce(vin): - vin.rewind() - vin.colormapinited = 1 - vin.magnify = magnify - - if threading: - MAXSIZE = 20 # Don't read ahead too much - import thread - import Queue - queue = Queue.Queue(MAXSIZE) - stop = [] - thread.start_new_thread(read_ahead, (vin, queue, stop)) - # Get the read-ahead thread going - while queue.qsize() < MAXSIZE/2 and not stop: - time.millisleep(100) - - tin = 0 - toffset = 0 - oldtin = 0 - told = 0 - nin = 0 - nout = 0 - nlate = 0 - nskipped = 0 - data = None - - tlast = t0 = time.millitimer() - - while 1: - if gl.qtest(): - dev, val = gl.qread() - if dev == ESCKEY and val == 1 or \ - dev in (WINSHUT, WINQUIT) or \ - dev == LEFTMOUSE and val == 1: - if debug: sys.stderr.write('\n') - if threading: - stop.append(None) - while 1: - item = queue.get() - if item == None: break - return (dev != LEFTMOUSE) - if dev == REDRAW: - gl.reshapeviewport() - if data: vin.showframe(data, cdata) - if threading: - if debug and queue.empty(): sys.stderr.write('.') - item = queue.get() - if item == None: break - tin, data, cdata = item - else: - try: - tin, size, csize = vin.getnextframeheader() - except EOFError: - break - nin = nin+1 - if tin+toffset < oldtin: - print 'Fix reversed time:', oldtin, 'to', tin - toffset = oldtin - tin - tin = tin + toffset - oldtin = tin - if regen: tout = nin * regen - else: tout = tin - tout = int(tout / speed) - if tout - told < mindelta: - nskipped = nskipped + 1 - if not threading: - vin.skipnextframedata(size, csize) - else: - if not threading: - try: - data, cdata = \ - vin.getnextframedata(size, csize) - except EOFError: - if not quiet: - print '[incomplete last frame]' - break - now = time.millitimer() - dt = (tout-told) - (now-tlast) - told = tout - if debug: sys.stderr.write(`dt/10` + ' ') - if dt < 0: nlate = nlate + 1 - if dt > 0: - time.millisleep(dt) - now = now + dt - tlast = now - vin.showframe(data, cdata) - nout = nout + 1 - - t1 = time.millitimer() - - if debug: sys.stderr.write('\n') - - if quiet: return 0 - - print 'Recorded:', nin, 'frames in', tin*0.001, 'sec.', - if tin: print '-- average', int(nin*10000.0/tin)*0.1, 'frames/sec', - print - - if nskipped: print 'Skipped', nskipped, 'frames' - - tout = t1-t0 - print 'Played:', nout, - print 'frames in', tout*0.001, 'sec.', - if tout: print '-- average', int(nout*10000.0/tout)*0.1, 'frames/sec', - print - - if nlate: print 'There were', nlate, 'late frames' - - return 0 - - -# Read-ahead thread - -def read_ahead(vin, queue, stop): - try: - while not stop: queue.put(vin.getnextframe()) - except EOFError: - pass - queue.put(None) - stop.append(None) - - -# Don't forget to call the main program - -try: - main() -except KeyboardInterrupt: - print '[Interrupt]' diff --git a/Demo/sgi/video/Vrec.py b/Demo/sgi/video/Vrec.py deleted file mode 100755 index b3660e2e06..0000000000 --- a/Demo/sgi/video/Vrec.py +++ /dev/null @@ -1,412 +0,0 @@ -#! /ufs/guido/bin/sgi/python -#! /ufs/guido/bin/sgi/python-405 - -# Capture a CMIF movie using the Indigo video library and board - -# The CMIF video file format is documented in cmif-film.ms. -# Audio data is recorded in AIFF format, using the input sampling -# rate, source and volume set by the audio panel, in mono, 8 -# bits/sample. - - -# Usage and help functions (keep this up-to-date if you change the program!) - -def usage(): - print 'Usage: Vrec [options] [moviefile [audiofile]]' - print - print 'Options:' - print '-a : record audio as well' - print '-q queuesize : set the capture queue size (default 2)' - print '-r rate : capture 1 out of every "rate" frames', \ - '(default and min 2)' - print '-w width : initial window width', \ - '(default 256, use 0 for interactive placement)' - print '-n : Don\'t write to file, only timing info' - print '-d : drop fields if needed' - print '-g bits : greyscale (2, 4 or 8 bits)' - print '-G : 2-bit greyscale dithered' - print '-m : monochrome dithered' - print '-M value : monochrome tresholded with value' - print '-f : Capture fields (in stead of frames)' - print '-P frames : preallocate space for "frames" frames' - print 'moviefile : here goes the movie data (default film.video)' - print 'audiofile : with -a, here goes the audio data', \ - '(default film.aiff)' - -def help(): - print 'Press the left mouse button to start recording, release it to' - print 'end recording. You can record as many times as you wish, but' - print 'each recording overwrites the output file(s) -- only the last' - print 'recording is kept.' - print - print 'Press ESC or use the window manager Quit or Close window option' - print 'to quit. If you quit before recording anything, the output' - print 'file(s) are not touched.' - - -# Imported modules - -import sys -sys.path.append('/ufs/guido/src/video') -import sv, SV -import VFile -import gl, GL, DEVICE -import al, AL -import time -import posix -import getopt -import string -import imageop -import sgi - - -# Main program - -def main(): - format = SV.RGB8_FRAMES - qsize = 2 - audio = 0 - rate = 2 - width = 0 - norecord = 0 - drop = 0 - mono = 0 - grey = 0 - greybits = 0 - monotreshold = -1 - fields = 0 - preallocspace = 0 - - # Parse command line - try: - opts, args = getopt.getopt(sys.argv[1:], 'aq:r:w:ndg:mM:GfP:') - except getopt.error, msg: - sys.stdout = sys.stderr - print 'Error:', msg, '\n' - usage() - sys.exit(2) - - # Interpret options - try: - for opt, arg in opts: - if opt == '-a': - audio = 1 - elif opt == '-q': - qsize = string.atoi(arg) - elif opt == '-r': - rate = string.atoi(arg) - if rate < 2: - sys.stderr.write( \ - '-r rate must be >= 2\n') - sys.exit(2) - elif opt == '-w': - width = string.atoi(arg) - elif opt == '-n': - norecord = 1 - elif opt == '-d': - drop = 1 - elif opt == '-g': - grey = 1 - greybits = string.atoi(arg) - if not greybits in (2, 4, 8): - sys.stderr.write( \ - 'Only 2, 4 or 8 bit greyscale supported\n') - sys.exit(2) - elif opt == '-G': - grey = 1 - greybits = -2 - elif opt == '-m': - mono = 1 - elif opt == '-M': - mono = 1 - monotreshold = string.atoi(arg) - elif opt == '-f': - fields = 1 - elif opt == '-P': - preallocspace = string.atoi(arg) - except string.atoi_error: - sys.stdout = sys.stderr - print 'Option', opt, 'requires integer argument' - sys.exit(2) - - # Check excess arguments - # If norecord is on, refuse filename arguments - if norecord: - if args: - sys.stdout = sys.stderr - print 'With -n, no filename arguments are used\n' - usage() - sys.exit(2) - elif args[2:]: - sys.stdout = sys.stderr - print 'Too many filename arguments\n' - usage() - sys.exit(2) - - # Process file arguments - if args: - filename = args[0] - else: - filename = 'film.video' - - if args[1:] and not audio: - sys.stderr.write('-a turned on by appearance of 2nd file\n') - audio = 1 - - if audio: - if args[1:]: - audiofilename = args[1] - else: - audiofilename = 'film.aiff' - else: - audiofilename = None - - if norecord: - filename = audiofilename = '' - - # Open video - v = sv.OpenVideo() - # Determine maximum window size based on signal standard - param = [SV.BROADCAST, 0] - v.GetParam(param) - if param[1] == SV.PAL: - x = SV.PAL_XMAX - y = SV.PAL_YMAX - elif param[1] == SV.NTSC: - x = SV.NTSC_XMAX - y = SV.NTSC_YMAX - else: - print 'Unknown video standard', param[1] - sys.exit(1) - - gl.foreground() - gl.maxsize(x, y) - gl.keepaspect(x, y) - gl.stepunit(8, 6) - if width: - height = width*3/4 - x1 = 150 - x2 = x1 + width-1 - y2 = 768-150 - y1 = y2-height+1 - gl.prefposition(x1, x2, y1, y2) - win = gl.winopen(filename) - if width: - gl.maxsize(x, y) - gl.keepaspect(x, y) - gl.stepunit(8, 6) - gl.winconstraints() - x, y = gl.getsize() - print x, 'x', y - - v.SetSize(x, y) - - if drop: - param = [SV.FIELDDROP, 1, SV.GENLOCK, SV.GENLOCK_OFF] - else: - param = [SV.FIELDDROP, 0, SV.GENLOCK, SV.GENLOCK_ON] - if mono or grey: - param = param+[SV.COLOR, SV.MONO, SV.DITHER, 0, \ - SV.INPUT_BYPASS, 1] - else: - param = param+[SV.COLOR, SV.DEFAULT_COLOR, SV.INPUT_BYPASS, 0] - - v.BindGLWindow(win, SV.IN_REPLACE) - v.SetParam(param) - - gl.qdevice(DEVICE.LEFTMOUSE) - gl.qdevice(DEVICE.WINQUIT) - gl.qdevice(DEVICE.WINSHUT) - gl.qdevice(DEVICE.ESCKEY) - - help() - - while 1: - dev, val = gl.qread() - if dev == DEVICE.LEFTMOUSE: - if val == 1: - info = format, x, y, qsize, rate - record(v, info, filename, audiofilename,\ - mono, grey, greybits, monotreshold, \ - fields, preallocspace) - elif dev == DEVICE.REDRAW: - # Window resize (or move) - x, y = gl.getsize() - print x, 'x', y - v.SetSize(x, y) - v.BindGLWindow(win, SV.IN_REPLACE) - elif dev in (DEVICE.ESCKEY, DEVICE.WINQUIT, DEVICE.WINSHUT): - # Quit - v.CloseVideo() - gl.winclose(win) - break - - -# Record until the mouse is released (or any other GL event) -# XXX audio not yet supported - -def record(v, info, filename, audiofilename, mono, grey, greybits, \ - monotreshold, fields, preallocspace): - import thread - format, x, y, qsize, rate = info - fps = 59.64 # Fields per second - # XXX (Strange: need fps of Indigo monitor, not of PAL or NTSC!) - tpf = 1000.0 / fps # Time per field in msec - if filename: - vout = VFile.VoutFile(filename) - if mono: - format = 'mono' - elif grey and greybits == 8: - format = 'grey' - elif grey: - format = 'grey'+`abs(greybits)` - else: - format = 'rgb8' - vout.setformat(format) - vout.setsize(x, y) - if fields: - vout.setpf((1, -2)) - vout.writeheader() - if preallocspace: - print 'Preallocating space...' - vout.prealloc(preallocspace) - print 'done.' - MAXSIZE = 20 # XXX should be a user option - import Queue - queue = Queue.Queue(MAXSIZE) - done = thread.allocate_lock() - done.acquire_lock() - convertor = None - if grey: - if greybits == 2: - convertor = imageop.grey2grey2 - elif greybits == 4: - convertor = imageop.grey2grey4 - elif greybits == -2: - convertor = imageop.dither2grey2 - thread.start_new_thread(saveframes, \ - (vout, queue, done, mono, monotreshold, convertor)) - if audiofilename: - audiodone = thread.allocate_lock() - audiodone.acquire_lock() - audiostop = [] - initaudio(audiofilename, audiostop, audiodone) - gl.wintitle('(rec) ' + filename) - lastid = 0 - t0 = time.millitimer() - count = 0 - ids = [] - v.InitContinuousCapture(info) - while not gl.qtest(): - try: - cd, id = v.GetCaptureData() - except sv.error: - #time.millisleep(10) # XXX is this necessary? - sgi.nap(1) # XXX Try by Jack - continue - ids.append(id) - - id = id + 2*rate -## if id <> lastid + 2*rate: -## print lastid, id - lastid = id - count = count+1 - if fields: - data1, data2 = cd.GetFields() - cd.UnlockCaptureData() - if filename: - queue.put((data1, int(id*tpf))) - queue.put((data2, int((id+1)*tpf))) - else: - data = cd.InterleaveFields(1) - cd.UnlockCaptureData() - if filename: - queue.put((data, int(id*tpf))) - t1 = time.millitimer() - gl.wintitle('(busy) ' + filename) - print lastid, 'fields in', t1-t0, 'msec', - print '--', 0.1 * int(lastid * 10000.0 / (t1-t0)), 'fields/sec' - print 'Captured',count*2, 'fields,', - print 0.1*int(count*20000.0/(t1-t0)), 'f/s', - if lastid: - print count*200.0/lastid, '%,', - print count*rate*200.0/lastid, '% of wanted rate', - print - if ids: - print 'Ids:', - t0 = ids[0] - del ids[0] - for t1 in ids: - print t1-t0, - t0 = t1 - print - if filename and audiofilename: - audiostop.append(None) - audiodone.acquire_lock() - v.EndContinuousCapture() - if filename: - queue.put(None) # Sentinel - done.acquire_lock() - gl.wintitle('(done) ' + filename) - - -# Thread to save the frames to the file - -def saveframes(vout, queue, done, mono, monotreshold, convertor): - while 1: - x = queue.get() - if not x: - break - data, t = x - if convertor: - data = convertor(data, len(data), 1) - elif mono and monotreshold >= 0: - data = imageop.grey2mono(data, len(data), 1,\ - monotreshold) - elif mono: - data = imageop.dither2mono(data, len(data), 1) - vout.writeframe(t, data, None) - sys.stderr.write('Done writing video\n') - vout.close() - done.release_lock() - - -# Initialize audio recording - -AQSIZE = 8000 # XXX should be a user option - -def initaudio(filename, stop, done): - import thread, aifc - afile = aifc.open(filename, 'w') - afile.setnchannels(AL.MONO) - afile.setsampwidth(AL.SAMPLE_8) - params = [AL.INPUT_RATE, 0] - al.getparams(AL.DEFAULT_DEVICE, params) - print 'audio sampling rate =', params[1] - afile.setframerate(params[1]) - c = al.newconfig() - c.setchannels(AL.MONO) - c.setqueuesize(AQSIZE) - c.setwidth(AL.SAMPLE_8) - aport = al.openport(filename, 'r', c) - thread.start_new_thread(audiorecord, (afile, aport, stop, done)) - - -# Thread to record audio samples - -def audiorecord(afile, aport, stop, done): - while not stop: - data = aport.readsamps(AQSIZE/2) - afile.writesampsraw(data) - del data - afile.close() - print 'Done writing audio' - done.release_lock() - - -# Don't forget to call the main program - -try: - main() -except KeyboardInterrupt: - print '[Interrupt]' diff --git a/Demo/sgi/video/Vrecb.py b/Demo/sgi/video/Vrecb.py deleted file mode 100755 index ca81753ae6..0000000000 --- a/Demo/sgi/video/Vrecb.py +++ /dev/null @@ -1,429 +0,0 @@ -#! /ufs/guido/bin/sgi/python - -# Capture a CMIF movie using the Indigo video library and board in burst mode - - -# User interface: -# -# Start the application. Resize the window to the desired movie size. -# Press the left mouse button to start recording, release it to end -# recording. You can record as many times as you wish, but each time -# you overwrite the output file(s), so only the last recording is -# kept. -# -# Press ESC or select the window manager Quit or Close window option -# to quit. If you quit before recording anything, the output file(s) -# are not touched. - - -import sys -sys.path.append('/ufs/guido/src/video') -import sv, SV -import VFile -import gl, GL, DEVICE -import al, AL -import time -import posix -import getopt -import string -import imageop -import sgi - - -# Usage and help functions (keep this up-to-date if you change the program!) - -def usage(): - print 'Usage: Vrecb [options] [moviefile [audiofile]]' - print - print 'Options:' - print '-a : record audio as well' - print '-r rate : capture 1 out of every "rate" frames', \ - '(default and min 1)' - print '-w width : initial window width', \ - '(default 256, use 0 for interactive placement)' - print '-d : drop fields if needed' - print '-g bits : greyscale (2, 4 or 8 bits)' - print '-G : 2-bit greyscale dithered' - print '-m : monochrome dithered' - print '-M value : monochrome tresholded with value' - print '-f : Capture fields (instead of frames)' - print '-n number : Capture this many frames (default 60)' - print '-N memsize : Capture frames fitting in this many kbytes' - print 'moviefile : here goes the movie data (default film.video)' - -def help(): - print 'Press the left mouse button to start recording.' - print 'Recording time is determined by the -n option.' - print 'You can record as many times as you wish, but each' - print 'recording overwrites the output file(s) -- only the' - print 'last recording is kept.' - print - print 'Press ESC or use the window manager Quit or Close window option' - print 'to quit. If you quit before recording anything, the output' - print 'file(s) are not touched.' - - -# Main program - -def main(): - format = SV.RGB8_FRAMES - audio = 0 - rate = 1 - width = 256 - drop = 0 - mono = 0 - grey = 0 - greybits = 0 - monotreshold = -1 - fields = 0 - number = 0 - memsize = 0 - - try: - opts, args = getopt.getopt(sys.argv[1:], 'ar:w:dg:mM:Gfn:N:') - except getopt.error, msg: - sys.stdout = sys.stderr - print 'Error:', msg, '\n' - usage() - sys.exit(2) - - try: - for opt, arg in opts: - if opt == '-a': - audio = 1 - if opt == '-r': - rate = string.atoi(arg) - if rate < 1: - sys.stderr.write('-r rate must be >= 1\n') - sys.exit(2) - elif opt == '-w': - width = string.atoi(arg) - elif opt == '-d': - drop = 1 - elif opt == '-g': - grey = 1 - greybits = string.atoi(arg) - if not greybits in (2,4,8): - sys.stderr.write( \ - 'Only 2, 4 or 8 bit greyscale supported\n') - sys.exit(2) - elif opt == '-G': - grey = 1 - greybits = -2 - elif opt == '-m': - mono = 1 - elif opt == '-M': - mono = 1 - monotreshold = string.atoi(arg) - elif opt == '-f': - fields = 1 - elif opt == '-n': - number = string.atoi(arg) - elif opt == '-N': - memsize = string.atoi(arg) - if 0 < memsize < 1024: - memsize = memsize * 1024 - if 0 < memsize < 1024*1024: - memsize = memsize * 1024 - print 'memsize', memsize - except string.atoi_error: - sys.stdout = sys.stderr - print 'Option', opt, 'requires integer argument' - sys.exit(2) - - if number <> 0 and memsize <> 0: - sys.stderr.write('-n and -N are mutually exclusive\n') - sys.exit(2) - if number == 0 and memsize == 0: - number = 60 - - if not fields: - print '-f option assumed until somebody fixes it' - fields = 1 - - if args[2:]: - sys.stderr.write('usage: Vrecb [options] [file [audiofile]]\n') - sys.exit(2) - - if args: - filename = args[0] - else: - filename = 'film.video' - - if args[1:] and not audio: - sys.stderr.write('-a turned on by appearance of 2nd file\n') - audio = 1 - - if audio: - if args[1:]: - audiofilename = args[1] - else: - audiofilename = 'film.aiff' - else: - audiofilename = None - - v = sv.OpenVideo() - # Determine maximum window size based on signal standard - param = [SV.BROADCAST, 0] - v.GetParam(param) - if param[1] == SV.PAL: - x = SV.PAL_XMAX - y = SV.PAL_YMAX - elif param[1] == SV.NTSC: - x = SV.NTSC_XMAX - y = SV.NTSC_YMAX - else: - print 'Unknown video standard', param[1] - sys.exit(1) - - gl.foreground() - gl.maxsize(x, y) - gl.keepaspect(x, y) - gl.stepunit(8, 6) - if width: - height = width*3/4 - x1 = 150 - x2 = x1 + width-1 - y2 = 768-150 - y1 = y2-height+1 - gl.prefposition(x1, x2, y1, y2) - win = gl.winopen(filename) - if width: - gl.maxsize(x, y) - gl.keepaspect(x, y) - gl.stepunit(8, 6) - gl.winconstraints() - x, y = gl.getsize() - print x, 'x', y - if memsize: - number = calcnumber(x, y, grey or mono, memsize) - print number, 'frames' - v.SetSize(x, y) - - if drop: - param = [SV.FIELDDROP, 1, SV.GENLOCK, SV.GENLOCK_OFF] - else: - param = [SV.FIELDDROP, 0, SV.GENLOCK, SV.GENLOCK_ON] - if mono or grey: - param = param+[SV.COLOR, SV.MONO, SV.DITHER, 0, \ - SV.INPUT_BYPASS, 1] - else: - param = param+[SV.COLOR, SV.DEFAULT_COLOR, SV.INPUT_BYPASS, 0] - - v.BindGLWindow(win, SV.IN_REPLACE) - v.SetParam(param) - - gl.qdevice(DEVICE.LEFTMOUSE) - gl.qdevice(DEVICE.WINQUIT) - gl.qdevice(DEVICE.WINSHUT) - gl.qdevice(DEVICE.ESCKEY) - - help() - - while 1: - dev, val = gl.qread() - if dev == DEVICE.LEFTMOUSE: - if val == 1: - info = format, x, y, number, rate - record(v, info, filename, audiofilename, \ - mono, grey, \ - greybits, monotreshold, fields) - elif dev == DEVICE.REDRAW: - # Window resize (or move) - x, y = gl.getsize() - print x, 'x', y - if memsize: - number = calcnumber(x, y, grey or mono, memsize) - print number, 'frames' - v.SetSize(x, y) - v.BindGLWindow(win, SV.IN_REPLACE) - elif dev in (DEVICE.ESCKEY, DEVICE.WINQUIT, DEVICE.WINSHUT): - # Quit - v.CloseVideo() - gl.winclose(win) - break - - -def calcnumber(x, y, grey, memsize): - pixels = x*y - pixels = pixels/2 # XXX always assume fields - if grey: n = memsize/pixels - else: n = memsize/(4*pixels) - return max(1, n) - - -# Record until the mouse is released (or any other GL event) -# XXX audio not yet supported - -def record(v, info, filename, audiofilename, \ - mono, grey, greybits, monotreshold, fields): - import thread - format, x, y, number, rate = info - fps = 59.64 # Fields per second - # XXX (Strange: need fps of Indigo monitor, not of PAL or NTSC!) - tpf = 1000.0 / fps # Time per field in msec - # - # Go grab - # - if audiofilename: - gl.wintitle('(start audio) ' + filename) - audiodone = thread.allocate_lock() - audiodone.acquire_lock() - audiostart = thread.allocate_lock() - audiostart.acquire_lock() - audiostop = [] - initaudio(audiofilename, audiostop, audiostart, audiodone) - audiostart.acquire_lock() - gl.wintitle('(rec) ' + filename) - try: - ninfo, data, bitvec = v.CaptureBurst(info) - except sv.error, arg: - print 'CaptureBurst failed:', arg - print 'info:', info - gl.wintitle(filename) - return - gl.wintitle('(save) '+ filename) - # - # Check results - # - if info <> ninfo: - print 'Sorry, format changed.' - print 'Wanted:',info - print 'Got :',ninfo - gl.wintitle(filename) - return - # print bitvec - if x*y*number <> len(data): - print 'Funny data length: wanted',x,'*',y,'*', number,'=',\ - x*y*number,'got',len(data) - gl.wintitle(filename) - return - # - # Save - # - if filename and audiofilename: - audiostop.append(None) - audiodone.acquire_lock() - if filename: - # - # Construct header and write it - # - try: - vout = VFile.VoutFile(filename) - except IOError, msg: - print filename, ':', msg - sys.exit(1) - if mono: - vout.format = 'mono' - elif grey and greybits == 8: - vout.format = 'grey' - elif grey: - vout.format = 'grey'+`abs(greybits)` - else: - vout.format = 'rgb8' - vout.width = x - vout.height = y - if fields: - vout.packfactor = (1,-2) - else: - print 'Sorry, can only save fields at the moment' - print '(i.e. you *must* use the -f option)' - gl.wintitle(filename) - return - vout.writeheader() - # - # Compute convertor, if needed - # - convertor = None - if grey: - if greybits == 2: - convertor = imageop.grey2grey2 - elif greybits == 4: - convertor = imageop.grey2grey4 - elif greybits == -2: - convertor = imageop.dither2grey2 - fieldsize = x*y/2 - nskipped = 0 - realframeno = 0 - tpf = 1000 / 50.0 #XXXX - # Trying to find the pattern in frame skipping - okstretch = 0 - skipstretch = 0 - for frameno in range(0, number*2): - if frameno <> 0 and \ - bitvec[frameno] == bitvec[frameno-1]: - nskipped = nskipped + 1 - if okstretch: - print okstretch, 'ok', - okstretch = 0 - skipstretch = skipstretch + 1 - continue - if skipstretch: - print skipstretch, 'skipped' - skipstretch = 0 - okstretch = okstretch + 1 - # - # Save field. - # XXXX Works only for fields and top-to-bottom - # - start = frameno*fieldsize - field = data[start:start+fieldsize] - if convertor: - field = convertor(field, len(field), 1) - elif mono and monotreshold >= 0: - field = imageop.grey2mono( \ - field, len(field), 1, monotreshold) - elif mono: - field = imageop.dither2mono( \ - field, len(field), 1) - realframeno = realframeno + 1 - vout.writeframe(int(realframeno*tpf), field, None) - print okstretch, 'ok', - print skipstretch, 'skipped' - print 'Skipped', nskipped, 'duplicate frames' - vout.close() - - gl.wintitle('(done) ' + filename) -# Initialize audio recording - -AQSIZE = 8*8000 # XXX should be a user option - -def initaudio(filename, stop, start, done): - import thread, aifc - afile = aifc.open(filename, 'w') - afile.setnchannels(AL.MONO) - afile.setsampwidth(AL.SAMPLE_8) - params = [AL.INPUT_RATE, 0] - al.getparams(AL.DEFAULT_DEVICE, params) - print 'audio sampling rate =', params[1] - afile.setframerate(params[1]) - c = al.newconfig() - c.setchannels(AL.MONO) - c.setqueuesize(AQSIZE) - c.setwidth(AL.SAMPLE_8) - aport = al.openport(filename, 'r', c) - thread.start_new_thread(audiorecord, (afile, aport, stop, start, done)) - - -# Thread to record audio samples - -def audiorecord(afile, aport, stop, start, done): - start.release_lock() - leeway = 4 - while leeway > 0: - if stop: - leeway = leeway - 1 - data = aport.readsamps(AQSIZE/8) - afile.writesampsraw(data) - del data - afile.close() - print 'Done writing audio' - done.release_lock() - - -# Don't forget to call the main program - -try: - main() -except KeyboardInterrupt: - print '[Interrupt]' diff --git a/Demo/sgi/video/Vrecc.py b/Demo/sgi/video/Vrecc.py deleted file mode 100755 index 6a539f8192..0000000000 --- a/Demo/sgi/video/Vrecc.py +++ /dev/null @@ -1,281 +0,0 @@ -#! /ufs/guido/bin/sgi/python-405 -#! /ufs/guido/bin/sgi/python - -# Capture a continuous CMIF movie using the Indigo video library and board - - -# Usage: -# -# makemovie [-r rate] [-w width] [moviefile] - - -# Options: -# -# -r rate : capture 1 out of every 'rate' frames (default 1) -# -w width : initial window width (default interactive placement) -# -d : drop fields if needed -# -g bits : greyscale (2, 4 or 8 bits) -# -G : 2-bit greyscale dithered -# -m : monochrome dithered -# -M value : monochrome tresholded with value -# -f : Capture fields (in stead of frames) -# -n number : Capture 'number' fields (default 60) -# -# moviefile : here goes the movie data (default film.video); -# the format is documented in cmif-film.ms - - -# User interface: -# -# Start the application. Resize the window to the desired movie size. -# Press the left mouse button to start recording, release it to end -# recording. You can record as many times as you wish, but each time -# you overwrite the output file(s), so only the last recording is -# kept. -# -# Press ESC or select the window manager Quit or Close window option -# to quit. If you quit before recording anything, the output file(s) -# are not touched. - - -import sys -sys.path.append('/ufs/guido/src/video') -import sv, SV -import VFile -import gl, GL, DEVICE -import al, AL -import time -import posix -import getopt -import string -import imageop -import sgi - -# Main program - -def main(): - format = SV.RGB8_FRAMES - rate = 1 - width = 0 - drop = 0 - mono = 0 - grey = 0 - greybits = 0 - monotreshold = -1 - fields = 0 - number = 60 - - opts, args = getopt.getopt(sys.argv[1:], 'r:w:dg:mM:Gfn:') - for opt, arg in opts: - if opt == '-r': - rate = string.atoi(arg) - if rate < 2: - sys.stderr.write('-r rate must be >= 2\n') - sys.exit(2) - elif opt == '-w': - width = string.atoi(arg) - elif opt == '-d': - drop = 1 - elif opt == '-g': - grey = 1 - greybits = string.atoi(arg) - if not greybits in (2,4,8): - print 'Only 2, 4 or 8 bit greyscale supported' - elif opt == '-G': - grey = 1 - greybits = -2 - elif opt == '-m': - mono = 1 - elif opt == '-M': - mono = 1 - monotreshold = string.atoi(arg) - elif opt == '-f': - fields = 1 - elif opt == '-n': - number = string.atoi(arg) - - if args[2:]: - sys.stderr.write('usage: Vrec [options] [file]\n') - sys.exit(2) - - if args: - filename = args[0] - else: - filename = 'film.video' - - v = sv.OpenVideo() - # Determine maximum window size based on signal standard - param = [SV.BROADCAST, 0] - v.GetParam(param) - if param[1] == SV.PAL: - x = SV.PAL_XMAX - y = SV.PAL_YMAX - elif param[1] == SV.NTSC: - x = SV.NTSC_XMAX - y = SV.NTSC_YMAX - else: - print 'Unknown video standard', param[1] - sys.exit(1) - - gl.foreground() - gl.maxsize(x, y) - gl.keepaspect(x, y) - gl.stepunit(8, 6) - if width: - gl.prefsize(width, width*3/4) - win = gl.winopen(filename) - if width: - gl.maxsize(x, y) - gl.keepaspect(x, y) - gl.stepunit(8, 6) - gl.winconstraints() - x, y = gl.getsize() - print x, 'x', y - - v.SetSize(x, y) - - if drop: - param = [SV.FIELDDROP, 1, SV.GENLOCK, SV.GENLOCK_OFF] - else: - param = [SV.FIELDDROP, 0, SV.GENLOCK, SV.GENLOCK_ON] - if mono or grey: - param = param+[SV.COLOR, SV.MONO, SV.INPUT_BYPASS, 1] - else: - param = param+[SV.COLOR, SV.DEFAULT_COLOR, SV.INPUT_BYPASS, 0] - v.SetParam(param) - - v.BindGLWindow(win, SV.IN_REPLACE) - - gl.qdevice(DEVICE.LEFTMOUSE) - gl.qdevice(DEVICE.WINQUIT) - gl.qdevice(DEVICE.WINSHUT) - gl.qdevice(DEVICE.ESCKEY) - - print 'Press left mouse to start recording' - - while 1: - dev, val = gl.qread() - if dev == DEVICE.LEFTMOUSE: - if val == 1: - info = format, x, y, number, rate - record(v, info, filename, mono, grey, \ - greybits, monotreshold, fields) - elif dev == DEVICE.REDRAW: - # Window resize (or move) - x, y = gl.getsize() - print x, 'x', y - v.SetSize(x, y) - v.BindGLWindow(win, SV.IN_REPLACE) - elif dev in (DEVICE.ESCKEY, DEVICE.WINQUIT, DEVICE.WINSHUT): - # Quit - v.CloseVideo() - gl.winclose(win) - break - - -# Record until the mouse is released (or any other GL event) -# XXX audio not yet supported - -def record(v, info, filename, mono, grey, greybits, monotreshold, fields): - import thread - format, x, y, number, rate = info - fps = 59.64 # Fields per second - # XXX (Strange: need fps of Indigo monitor, not of PAL or NTSC!) - tpf = 1000.0 / fps # Time per field in msec - # - # Go grab - # - gl.wintitle('(rec) ' + filename) - try: - ninfo, data, bitvec = v.CaptureBurst(info) - except sv.error, arg: - print 'CaptureBurst failed:', arg - print 'info:', info - gl.wintitle(filename) - return - gl.wintitle('(save) '+ filename) - # - # Check results - # - if info <> ninfo: - print 'Sorry, format changed.' - print 'Wanted:',info - print 'Got :',ninfo - gl.wintitle(filename) - return - # print bitvec - if x*y*number <> len(data): - print 'Funny data length: wanted',x,'*',y,'*', number,'=',\ - x*y*number,'got',len(data) - gl.wintitle(filename) - return - # - # Save - # - if filename: - # - # Construct header and write it - # - vout = VFile.VoutFile().init(filename) - if mono: - vout.format = 'mono' - elif grey and greybits == 8: - vout.format = 'grey' - elif grey: - vout.format = 'grey'+`abs(greybits)` - else: - vout.format = 'rgb8' - vout.width = x - vout.height = y - if fields: - vout.packfactor = (1,-2) - else: - print 'Sorry, can only save fields at the moment' - gl.wintitle(filename) - return - vout.writeheader() - # - # Compute convertor, if needed - # - convertor = None - if grey: - if greybits == 2: - convertor = imageop.grey2grey2 - elif greybits == 4: - convertor = imageop.grey2grey4 - elif greybits == -2: - convertor = imageop.dither2grey2 - fieldsize = x*y/2 - nskipped = 0 - realframeno = 0 - tpf = 1000 / 50.0 #XXXX - for frameno in range(0, number*2): - if frameno <> 0 and \ - bitvec[frameno] == bitvec[frameno-1]: - nskipped = nskipped + 1 - continue - # - # Save field. - # XXXX Works only for fields and top-to-bottom - # - start = frameno*fieldsize - field = data[start:start+fieldsize] - if convertor: - field = convertor(field, x, y) - elif mono and monotreshold >= 0: - field = imageop.grey2mono(field, x, y, \ - 1, monotreshold) - elif mono: - field = imageop.dither2mono(field, x, y) - vout.writeframe(int(realframeno*tpf), field, None) - print 'Skipped',nskipped,'duplicate frames' - vout.close() - - gl.wintitle('(done) ' + filename) - -# Don't forget to call the main program - -try: - main() -except KeyboardInterrupt: - print '[Interrupt]' diff --git a/Demo/sgi/video/Vreceive.py b/Demo/sgi/video/Vreceive.py deleted file mode 100755 index f72c6a5920..0000000000 --- a/Demo/sgi/video/Vreceive.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/ufs/guido/bin/sgi/python - -# Receive live video UDP packets. -# Usage: Vreceive [port] - -import sys -import struct -from socket import * # syscalls and support functions -from SOCKET import * # -from IN import * # -import select -import struct -import gl, GL, DEVICE -sys.path.append('/ufs/guido/src/video') -import LiveVideoOut -import regsub -import getopt - -from senddefs import * - - -# Print usage message and exit(2). - -def usage(msg): - print msg - print 'usage: Vreceive [-m mcastgrp] [-p port] [-c type]' - print '-m mcastgrp: multicast group (default ' + `DEFMCAST` + ')' - print '-p port : port (default ' + `DEFPORT` + ')' - print '-c type : signal type: rgb8, grey or mono (default rgb8)' - sys.exit(2) - - -# Main program: parse options and main loop. - -def main(): - - sys.stdout = sys.stderr - - group = DEFMCAST - port = DEFPORT - width = DEFWIDTH - height = DEFHEIGHT - vtype = 'rgb8' - - try: - opts, args = getopt.getopt(sys.argv[1:], 'm:p:c:') - except getopt.error, msg: - usage(msg) - - try: - for opt, optarg in opts: - if opt == '-p': - port = string.atoi(optarg) - if opt == '-m': - group = gethostbyname(optarg) - if opt == '-c': - vtype = optarg - except string.atoi_error, msg: - usage('bad integer: ' + msg) - - s = opensocket(group, port) - - gl.foreground() - gl.prefsize(width, height) - wid = gl.winopen('Vreceive') - gl.winconstraints() - gl.qdevice(DEVICE.ESCKEY) - gl.qdevice(DEVICE.WINSHUT) - gl.qdevice(DEVICE.WINQUIT) - - lvo = LiveVideoOut.LiveVideoOut(wid, width, height, vtype) - - ifdlist = [gl.qgetfd(), s.fileno()] - ofdlist = [] - xfdlist = [] - timeout = 1.0 - selectargs = (ifdlist, ofdlist, xfdlist, timeout) - - while 1: - - if gl.qtest(): - dev, val = gl.qread() - if dev in (DEVICE.ESCKEY, \ - DEVICE.WINSHUT, DEVICE.WINQUIT): - break - if dev == DEVICE.REDRAW: - lvo.reshapewindow() - elif s.avail(): - data = s.recv(16*1024) - pos, w, h = struct.unpack('hhh', data[:6]) - if (w, h) <> (width, height): - x, y = gl.getorigin() - y = y + height - h - gl.winposition(x, x+w-1, y, y+h-1) - width, height = w, h - lvo.resizevideo(width, height) - lvo.putnextpacket(pos, data[6:]) - else: - x = select.select(selectargs) - - lvo.close() - - -# Subroutine to create and properly initialize the receiving socket - -def opensocket(group, port): - - # Create the socket - s = socket(AF_INET, SOCK_DGRAM) - - # Allow multiple copies of this program on one machine - s.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1) # (Not strictly needed) - - # Bind the port to it - s.bind('', port) - - # Look up the group once - group = gethostbyname(group) - - # Construct binary group address - group_bytes = eval(regsub.gsub('\.', ',', group)) - grpaddr = 0 - for byte in group_bytes: grpaddr = (grpaddr << 8) | byte - - # Construct struct mreq from grpaddr and ifaddr - ifaddr = INADDR_ANY - mreq = struct.pack('ll', grpaddr, ifaddr) - - # Add group membership - s.setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq) - - return s - - -main() diff --git a/Demo/sgi/video/Vsend.py b/Demo/sgi/video/Vsend.py deleted file mode 100755 index cc1e1ca675..0000000000 --- a/Demo/sgi/video/Vsend.py +++ /dev/null @@ -1,152 +0,0 @@ -#!/ufs/guido/bin/sgi/python - -# Send live video UDP packets. -# Usage: Vsend [-b] [-h height] [-p port] [-s size] [-t ttl] [-w width] -# [host] .. - -import sys -import time -import struct -import string -from socket import * -from SOCKET import * -import gl, GL, DEVICE -sys.path.append('/ufs/guido/src/video') -import LiveVideoIn -import LiveVideoOut -import SV -import getopt -from IN import * - -from senddefs import * - -def usage(msg): - print msg - print 'usage: Vsend [-b] [-h height] [-p port] [-s size] [-t ttl] [-c type] [-m]', - print '[-w width] [host] ...' - print '-b : broadcast on local net' - print '-h height : window height (default ' + `DEFHEIGHT` + ')' - print '-p port : port to use (default ' + `DEFPORT` + ')' - print '-t ttl : time-to-live (multicast only; default 1)' - print '-s size : max packet size (default ' + `DEFPKTMAX` + ')' - print '-w width : window width (default ' + `DEFWIDTH` + ')' - print '-c type : Type: rgb8, mono or grey (default rgb8)' - print '[host] ...: host(s) to send to (default multicast to ' + \ - DEFMCAST + ')' - sys.exit(2) - - -def main(): - sys.stdout = sys.stderr - - hosts = [] - port = DEFPORT - ttl = -1 - pktmax = DEFPKTMAX - width = DEFWIDTH - height = DEFHEIGHT - vtype = 'rgb8' - - try: - opts, args = getopt.getopt(sys.argv[1:], 'bh:p:s:t:w:c:') - except getopt.error, msg: - usage(msg) - - try: - for opt, optarg in opts: - if opt == '-p': - port = string.atoi(optarg) - if opt == '-b': - host = '' - if opt == '-t': - ttl = string.atoi(optarg) - if opt == '-s': - pktmax = string.atoi(optarg) - if opt == '-w': - width = string.atoi(optarg) - if opt == '-h': - height = string.atoi(optarg) - if opt == '-c': - vtype = optarg - except string.atoi_error, msg: - usage('bad integer: ' + msg) - - for host in args: - hosts.append(gethostbyname(host)) - - if not hosts: - hosts.append(gethostbyname(DEFMCAST)) - - if not LiveVideoIn.have_video: - print 'Sorry, no video available (use python-405)' - sys.exit(1) - - gl.foreground() - gl.prefsize(width, height) - gl.stepunit(8, 6) - wid = gl.winopen('Vsend') - gl.keepaspect(width, height) - gl.stepunit(8, 6) - gl.maxsize(SV.PAL_XMAX, SV.PAL_YMAX) - gl.winconstraints() - gl.qdevice(DEVICE.ESCKEY) - gl.qdevice(DEVICE.WINSHUT) - gl.qdevice(DEVICE.WINQUIT) - gl.qdevice(DEVICE.WINFREEZE) - gl.qdevice(DEVICE.WINTHAW) - width, height = gl.getsize() - - lvo = LiveVideoOut.LiveVideoOut(wid, width, height, vtype) - - lvi = LiveVideoIn.LiveVideoIn(pktmax, width, height, vtype) - - s = socket(AF_INET, SOCK_DGRAM) - s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1) - if ttl >= 0: - s.setsockopt(IPPROTO_IP, IP_MULTICAST_TTL, chr(ttl)) - - frozen = 0 - - while 1: - - if gl.qtest(): - dev, val = gl.qread() - if dev in (DEVICE.ESCKEY, \ - DEVICE.WINSHUT, DEVICE.WINQUIT): - break - if dev == DEVICE.WINFREEZE: - frozen = 1 - if dev == DEVICE.WINTHAW: - frozen = 0 - if dev == DEVICE.REDRAW: - w, h = gl.getsize() - x, y = gl.getorigin() - if (w, h) <> (width, height): - width, height = w, h - lvi.resizevideo(width, height) - lvo.resizevideo(width, height) - - rv = lvi.getnextpacket() - if not rv: - time.millisleep(10) - continue - - pos, data = rv - - if not frozen: - lvo.putnextpacket(pos, data) - - hdr = struct.pack('hhh', pos, width, height) - for host in hosts: - try: - s.sendto(hdr + data, (host, port)) - except error, msg: # really socket.error - if msg[0] <> 121: # no buffer space available - raise error, msg # re-raise it - print 'Warning:', msg[1] - - lvi.close() - lvo.close() - - -main() diff --git a/Demo/sgi/video/Vstat.py b/Demo/sgi/video/Vstat.py deleted file mode 100755 index cc0ecfb54a..0000000000 --- a/Demo/sgi/video/Vstat.py +++ /dev/null @@ -1,23 +0,0 @@ -#! /ufs/guido/bin/sgi/python - -# Print the value of all video parameters - -import sys -import sv, SV - -def main(): - v = sv.OpenVideo() - for name in dir(SV): - const = getattr(SV, name) - if type(const) is type(0): - sys.stdout.flush() - params = [const, 0] - try: - v.GetParam(params) - except sv.error, msg: -## print name, msg - continue - print name, params - -main() - diff --git a/Demo/sgi/video/Vtime.py b/Demo/sgi/video/Vtime.py deleted file mode 100755 index be161ccb67..0000000000 --- a/Demo/sgi/video/Vtime.py +++ /dev/null @@ -1,117 +0,0 @@ -#! /ufs/guido/bin/sgi/python - -# Manipulate the time base of CMIF movies - - -# Possibilities: -# -# - resample at a fixed rate -# - divide the time codes by a speed factor (to make it go faster/slower) -# - drop frames that are less than n msec apart (to accomodate slow players) - - -# Usage: -# -# Vtime [-m msec] [-r msec] [-s speed] [infile [outfile]] - - -# Options: -# -# -m n : drop frames closer than n msec (default 0) -# -r n : regenerate input time base n msec apart -# -s speed : speed change factor after other processing (default 1.0) -# infile : input file (default film.video) -# outfile : output file (default out.video) - - -import sys -sys.path.append('/ufs/guido/src/video') -import VFile -import getopt -import string - - -# Global options - -speed = 1.0 -mindelta = 0 -regen = None - - -# Main program -- mostly command line parsing - -def main(): - global speed, mindelta - opts, args = getopt.getopt(sys.argv[1:], 'm:r:s:') - for opt, arg in opts: - if opt == '-m': - mindelta = string.atoi(arg) - elif opt == '-r': - regen = string.atoi(arg) - elif opt == '-s': - speed = float(eval(arg)) - if len(args) < 1: - args.append('film.video') - if len(args) < 2: - args.append('out.video') - if len(args) > 2: - sys.stderr.write('usage: Vtime [options] [infile [outfile]]\n') - sys.exit(2) - sts = process(args[0], args[1]) - sys.exit(sts) - - -# Copy one file to another - -def process(infilename, outfilename): - try: - vin = VFile.BasicVinFile(infilename) - except IOError, msg: - sys.stderr.write(infilename + ': I/O error: ' + `msg` + '\n') - return 1 - except VFile.Error, msg: - sys.stderr.write(msg + '\n') - return 1 - except EOFError: - sys.stderr.write(infilename + ': EOF in video file\n') - return 1 - - try: - vout = VFile.BasicVoutFile(outfilename) - except IOError, msg: - sys.stderr.write(outfilename + ': I/O error: ' + `msg` + '\n') - return 1 - - vout.setinfo(vin.getinfo()) - vout.writeheader() - - told = 0 - nin = 0 - nout = 0 - tin = 0 - tout = 0 - - while 1: - try: - tin, data, cdata = vin.getnextframe() - except EOFError: - break - nin = nin + 1 - if regen: - tout = nin * regen - else: - tout = tin - tout = int(tout / speed) - if tout - told < mindelta: - continue - told = tout - vout.writeframe(tout, data, cdata) - nout = nout + 1 - - vout.close() - vin.close() - - -# Don't forget to call the main program - -main() diff --git a/Demo/sgi/video/Vunjpeg.py b/Demo/sgi/video/Vunjpeg.py deleted file mode 100755 index 9f21f959ff..0000000000 --- a/Demo/sgi/video/Vunjpeg.py +++ /dev/null @@ -1,97 +0,0 @@ -#!/ufs/guido/bin/sgi/python - -# Decompress a jpeg or jpeggrey video file to rgb format - - -# Usage: -# -# Vunjpeg [infile [outfile]] - - -# Options: -# -# infile : input file (default film.video) -# outfile : output file (default out.video) - - -import sys -import jpeg -sys.path.append('/ufs/guido/src/video') -import VFile - - -# Main program -- mostly command line parsing - -def main(): - args = sys.argv[1:] - if len(args) < 1: - args.append('film.video') - if len(args) < 2: - args.append('out.video') - if len(args) > 2: - sys.stderr.write('usage: Vunjpeg [infile [outfile]]\n') - sys.exit(2) - sts = process(args[0], args[1]) - sys.exit(sts) - - -# Copy one file to another - -def process(infilename, outfilename): - try: - vin = VFile.BasicVinFile(infilename) - except IOError, msg: - sys.stderr.write(infilename + ': I/O error: ' + `msg` + '\n') - return 1 - except VFile.Error, msg: - sys.stderr.write(msg + '\n') - return 1 - except EOFError: - sys.stderr.write(infilename + ': EOF in video file\n') - return 1 - - try: - vout = VFile.BasicVoutFile(outfilename) - except IOError, msg: - sys.stderr.write(outfilename + ': I/O error: ' + `msg` + '\n') - return 1 - - info = vin.getinfo() - if info[0] == 'jpeg': - format = 'rgb' - width, height = vin.getsize() - bytes = 4 - elif info[0] == 'jpeggrey': - format = 'grey' - width, height = vin.getsize() - pf = vin.packfactor - width, height = width/pf, height/pf - bytes = 1 - else: - sys.stderr.write('Vunjpeg: input not in jpeg[grey] format\n') - return 1 - info = (format,) + info[1:] - vout.setinfo(info) - vout.writeheader() - sts = 0 - n = 0 - try: - while 1: - t, data, cdata = vin.getnextframe() - n = n + 1 - sys.stderr.write('Frame ' + `n` + '...') - data, w, h, b = jpeg.decompress(data) - if (w, h, b) <> (width, height, bytes): - sys.stderr.write('jpeg data has wrong size\n') - sts = 1 - else: - vout.writeframe(t, data, None) - sys.stderr.write('\n') - except EOFError: - pass - return sts - - -# Don't forget to call the main program - -main() diff --git a/Demo/sgi/video/aplay.py b/Demo/sgi/video/aplay.py deleted file mode 100755 index 7b1002722c..0000000000 --- a/Demo/sgi/video/aplay.py +++ /dev/null @@ -1,167 +0,0 @@ -#! /ufs/guido/bin/sgi/python - -# Play synchronous video and audio. -# Highly experimental! - -import sys -import getopt -import string -import os - -import VFile -import aifc - -import gl, GL, DEVICE -import al, AL - - -def usage(): - sys.stderr.write( \ - 'usage: aplay [-o offset] [-q qsize] videofile audiofile\n') - sys.exit(2) - -def main(): - offset = 0 - qsize = 0 # This defaults to 1/10 second of sound - videofile = 'film.video' - audiofile = 'film.aiff' - - try: - opts, args = getopt.getopt(sys.argv[1:], 'o:q:') - except getopt.error, msg: - sys.stderr.write(msg + '\n') - usage() - - try: - for o, a in opts: - if o == '-o': - offset = string.atoi(a) - if o == '-q': - qsize = string.atoi(a) - except string.atoi_error: - sys.stderr.write(o + ' arg must be integer\n') - usage() - - if len(args) > 2: - usage() - - if args: videofile = args[0] - if args[1:]: audiofile = args[1] - - if not os.path.exists(videofile) and \ - os.path.exists(videofile + '.video'): - if not args[1:] and os.path.exists(videofile + '.aiff'): - audiofile = videofile + '.aiff' - videofile = videofile + '.video' - - print 'Opening video input file..' - vin = VFile.VinFile(videofile) - - print 'Opening audio input file..' - ain = aifc.open(audiofile, 'r') - print 'rate :', ain.getframerate() - print 'channels:', ain.getnchannels() - print 'frames :', ain.getnframes() - print 'width :', ain.getsampwidth() - print 'kbytes :', \ - ain.getnframes() * ain.getnchannels() * ain.getsampwidth() - - print 'Opening audio output port..' - c = al.newconfig() - c.setchannels(ain.getnchannels()) - c.setwidth(ain.getsampwidth()) - nullsample = '\0' * ain.getsampwidth() - samples_per_second = ain.getnchannels() * ain.getframerate() - if qsize <= 0: qsize = samples_per_second / 10 - qsize = max(qsize, 512) - c.setqueuesize(qsize) - saveparams = [AL.OUTPUT_RATE, 0] - al.getparams(AL.DEFAULT_DEVICE, saveparams) - newparams = [AL.OUTPUT_RATE, ain.getframerate()] - al.setparams(AL.DEFAULT_DEVICE, newparams) - aport = al.openport(audiofile, 'w', c) - - print 'Opening video output window..' - gl.foreground() - gl.prefsize(vin.width, vin.height) - wid = gl.winopen(videofile + ' + ' + audiofile) - gl.clear() - vin.initcolormap() - - print 'Playing..' - gl.qdevice(DEVICE.ESCKEY) - gl.qdevice(DEVICE.LEFTARROWKEY) - gl.qdevice(DEVICE.RIGHTARROWKEY) -## gl.qdevice(DEVICE.UPARROWKEY) -## gl.qdevice(DEVICE.DOWNARROWKEY) - gl.qdevice(DEVICE.SPACEKEY) - - while 1: - samples_written = 0 - samples_read = 0 - lastt = 0 - pause = 0 - while 1: - if gl.qtest(): - dev, val = gl.qread() - if val == 1: - if dev == DEVICE.ESCKEY: - sys.exit(0) - elif dev == DEVICE.LEFTARROWKEY: - offset = offset - 100 - print 'offset =', offset - elif dev == DEVICE.RIGHTARROWKEY: - offset = offset + 100 - print 'offset =', offset - elif dev == DEVICE.SPACEKEY: - pause = (not pause) - - if pause: - continue - - try: - t, data, cdata = vin.getnextframe() - except EOFError: - break - t = int(t) - dt = t - lastt - lastt = t - target = samples_per_second * t / 1000 - n = target - samples_written + qsize - offset - if n > 0: - # This call will block until the time is right: - try: - samples = ain.readframes(n) - except EOFError: - samples = '' - k = len(samples) / len(nullsample) - samples_read = samples_read + k - if k < n: - samples = samples + (n-k) * nullsample - aport.writesamps(samples) - samples_written = samples_written + n - vin.showframe(data, cdata) - - while 1: - try: - samples = ain.readframes(qsize) - except EOFError: - break - if not samples: - break - aport.writesamps(samples) - k = len(samples) / len(nullsample) - samples_read = samples_read + k - samples_written = samples_written + k - - print samples_read, 'samples ==', - print samples_read * 1.0 / samples_per_second, 'sec.' - print lastt, 'milliseconds' - - print 'Restarting..' - ain.close() - ain = aifc.open(audiofile, 'r') - vin.rewind() - - -main() diff --git a/Demo/sgi/video/cam.py b/Demo/sgi/video/cam.py deleted file mode 100755 index fa8966f8b3..0000000000 --- a/Demo/sgi/video/cam.py +++ /dev/null @@ -1,129 +0,0 @@ -import sys -from socket import * -from gl import * -from GL import * -from DEVICE import * -from time import millitimer - -HS = 40 # Header size (must be same as in tv.py) - -# Rely on UDP packet (de)fragmentation for smoother images -# (Changed for broadcast) -MAX = 16000 - -PF = 2 # Default packfactor - -# Default receiver station is voorn. -# Kwik has no yellow pages, so... -HOST = '192.16.201.121' -PORT = 5555 - -if sys.argv[1:]: - PF = eval(sys.argv[1]) - -if sys.argv[2:]: - HOST = sys.argv[2] - if HOST == 'all': - HOST = '' - MAX = 1400 - -PF2 = PF*PF - -def main(): - centerx, centery = 400, 300 - - foreground() - wid = winopen('cam') - RGBmode() - doublebuffer() - gconfig() - qdevice(ESCKEY) - - w, h = getsize() - ortho2(0, w, 0, h) - w = w/PF*PF - h = h/PF*PF - - readsource(SRC_FRAMEGRABBER) - - s = socket(AF_INET, SOCK_DGRAM) - if HOST == '': - s.allowbroadcast(1) - addr = HOST, PORT - - bytesperline = w/PF2 - linesperchunk = MAX/bytesperline - linesperchunk = linesperchunk/PF*PF - nchunks = (h+linesperchunk-1)/linesperchunk - - print 'MAX=', MAX, - print 'linesperchunk=', linesperchunk, - print 'nchunks=', nchunks, - print 'w=', w, 'h=', h - - x1, x2 = 0, w-1 - - t1 = millitimer() - nframes = 0 - fps = 0 - - msg = '' - - while 1: - while qtest(): - dev, val = qread() - if dev == REDRAW: - reshapeviewport() - w, h = getsize() - ortho2(0, w, 0, h) - w = w/PF*PF - h = h/PF*PF - - bytesperline = w/PF2 - linesperchunk = MAX/bytesperline - linesperchunk = linesperchunk/PF*PF - nchunks = (h+linesperchunk-1)/linesperchunk - - print 'MAX=', MAX, - print 'linesperchunk=', linesperchunk, - print 'nchunks=', nchunks, - print 'w=', w, 'h=', h - - x1, x2 = 0, w-1 - - fps = 0 - - elif dev == ESCKEY: - winclose(wid) - return - - readsource(SRC_FRAMEGRABBER) - - nframes = nframes+1 - if nframes >= fps: - t2 = millitimer() - if t2 <> t1: - fps = int(10000.0*nframes/(t2-t1)) * 0.1 - msg = `fps` + ' frames/sec' - t1 = t2 - nframes = 0 - - RGBcolor(255,255,255) - cmov2i(9,9) - charstr(msg) - - swapbuffers() - rectcopy(centerx-w/2, centery-w/2, centerx+w/2, centery+w/2, 0, 0) - - for i in range(nchunks): - y1 = i*linesperchunk - y2 = y1 + linesperchunk-1 - if y2 >= h: y2 = h-1 - data = lrectread(x1, y1, x2, y2) - data2 = packrect(x2-x1+1, y2-y1+1, PF, data) - prefix = `w, h, PF, x1, y1, x2, y2` - prefix = prefix + ' ' * (HS-len(prefix)) - data3 = prefix + data2 - s.sendto(data3, addr) - -main() diff --git a/Demo/sgi/video/camcorder.py b/Demo/sgi/video/camcorder.py deleted file mode 100755 index 9b7618c436..0000000000 --- a/Demo/sgi/video/camcorder.py +++ /dev/null @@ -1,266 +0,0 @@ -from gl import * -from GL import * -from DEVICE import * -import time -import sys -import getopt -import socket -import posix -import vtime - -# Preallocation parameter -PREALLOC = 4 # Megabyte - -# Sync audio parameters -SYNCPORT = 10000 -CTLPORT = 10001 - -from vpregs import * - -class Struct(): pass -epoch = Struct() - -def getvideosize(): - w = getvideo(VP_WIDTH) - h = getvideo(VP_HEIGHT) - print 'WIDTH,HEIGHT:', w, h - print 'GB{X,Y}ORG:', getvideo(VP_GBXORG), getvideo(VP_GBYORG) - print 'FB{X,Y}ORG:', getvideo(VP_FBXORG), getvideo(VP_FBYORG) - x = 0 - y = 0 - return x,y,w,h - -framelist = [] - -def prealloc(w, h): - nbytes = w*h*4 - limit = PREALLOC*1024*1024 - total = 0 - list = [] - print 'Prealloc to', PREALLOC, 'Megabytes...' - while total+nbytes <= limit: - list.append('x'*nbytes) - total = total + nbytes - print 'Done.' - -def grabframe(f,x,y,w,h,pf): - readsource(SRC_FRONT) - if pf: - w = w/pf*pf - h = h/pf*pf - data = lrectread(x,y,x+w-1,y+h-1) - t = time.millitimer()-epoch.epoch - framelist.append(data, t) - readsource(SRC_FRAMEGRABBER) - -def saveframes(f, w, h, pf): - for data, t in framelist: - if pf: - w = w/pf*pf - h = h/pf*pf - data = packrect(w,h,pf,data) - f.write(`t` + ',' + `len(data)` + '\n') - f.write(data) - framelist[:] = [] - -def saveframe(f,x,y,w,h,pf, notime): - readsource(SRC_FRONT) - if pf: - w = w/pf*pf - h = h/pf*pf - data = lrectread(x,y,x+w-1,y+h-1) - if pf: data = packrect(w,h,pf,data) - if notime: t = 0 - else: t = time.millitimer()-epoch.epoch - f.write(`t` + ',' + `len(data)` + '\n') - f.write(data) - readsource(SRC_FRAMEGRABBER) - -def drawframe(x,y,w,h,col): - drawmode(OVERDRAW) - color(col) - bgnline() - v2i(x-1,y-1) ; v2i(x+w,y-1); v2i(x+w,y+h); v2i(x-1,y+h); v2i(x-1,y-1) - endline() - drawmode(NORMALDRAW) - -def usage(): - sys.stderr.write('Usage: camcorder ' + \ - '[-c] [-p packfactor] [-a audiomachine [-s]] [outputfile]\n') - sys.exit(2) - -def wrheader(f, w, h, pf): - f.write('CMIF video 1.0\n') - f.write(`w,h,pf` + '\n') - print 'width,height,pf:', w, h, pf, - if pf == 0: pf = 4 - print '(i.e.,', w*h*pf, 'bytes/frame)' - -def main(): - foreground() - pf = 2 - ausync = 0 - austart = 0 - optlist, args = getopt.getopt(sys.argv[1:],'ca:sp:') - for opt, arg in optlist: - if opt == '-c': - pf = 0 - elif opt == '-a': - ausync = 1 - aumachine = arg - elif opt == '-s': - austart = 1 - elif opt == '-p': - pf = int(eval(arg)) - else: - usage() - if args: - if len(args) > 1: - print 'Too many arguments' - usage() - filename = args[0] - else: - filename = 'film.video' - if austart: - if not ausync: - print 'Cannot use -s without -a' - usage() - print 'Starting audio recorder...' - posix.system('rsh '+aumachine+' syncrecord '+socket.gethostname()+' &') - if ausync: - print 'Syncing to audio recorder...' - globtime = vtime.VTime().init(1,aumachine,SYNCPORT) - ctl = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) - ctl.bind((socket.gethostname(),CTLPORT)) - aua = (socket.gethostbyname(aumachine), CTLPORT) - print 'Done.' - vidx, vidy, w, h = getvideosize() - #prefsize(w,h) - winx, winy = 1280-w-10, 1024-h-30 - prefposition(winx,winx+w-1,winy,winy+h-1) - win = winopen(filename) - f = open(filename, 'w') - w, h = getsize() - realw, realh = w, h - ####doublebuffer() - RGBmode() - gconfig() - qdevice(LEFTMOUSE) - qdevice(RKEY) - qdevice(SKEY) - qdevice(CKEY) - qdevice(PKEY) - qdevice(ESCKEY) - qdevice(WINQUIT) - qdevice(WINSHUT) - inrunning = 1 - outrunning = 0 - stop = 'stop' - readsource(SRC_FRAMEGRABBER) - mousing = 0 - epoch.epoch = time.millitimer() - stoptime = epoch.epoch - sizewritten = 0 - x, y = realw/4, realh/4 - w, h = w/2, h/2 - prealloc(w, h) - try: - drawframe(x,y,w,h,1) - nframe = 0 - num = 0 - while 1: - insingle = 0 - outsingle = 0 - if mousing: - drawframe(x,y,w,h,0) - ox, oy = getorigin() - if sizewritten: - x = getvaluator(MOUSEX)-ox - y = getvaluator(MOUSEY)-oy - else: - w = getvaluator(MOUSEX)-x-ox - h = getvaluator(MOUSEY)-y-oy - drawframe(x,y,w,h,1) - if qtest() or \ - not (mousing or inrunning or insingle or outrunning or outsingle): - ev, val = qread() - if ev == LEFTMOUSE and val == 1: - drawframe(x,y,w,h,0) - mousing = 1 - ox, oy = getorigin() - x = getvaluator(MOUSEX)-ox - y = getvaluator(MOUSEY)-oy - elif ev == LEFTMOUSE and val == 0: - if h < 0: - y, h = y+h, -h - if w < 0: - x, w = x+w, -w - mousing = 0 - if not sizewritten: - wrheader(f, w, h, pf) - sizewritten = 1 - prealloc(w, h) - elif ev == RKEY and val == 1: - if not inrunning: - ringbell() - else: - outrunning = 1 - wasstopped = time.millitimer() - stoptime - epoch.epoch = epoch.epoch + wasstopped - nframe = 0 - starttime = time.millitimer() - if ausync: - ctl.sendto(`(1,starttime)`, aua) - elif ev == PKEY and val == 1 and outrunning: - outrunning = 0 - stoptime = time.millitimer() - if ausync: - ctl.sendto(`(0,stoptime)`, aua) - fps = nframe * 1000.0 / (time.millitimer()-starttime) - print 'Recorded', nframe, - print 'frames at', 0.1*int(fps*10),'frames/sec' - print 'Saving...' - saveframes(f, w, h, pf) - print 'Done.' - elif ev == PKEY and val == 1 and not outrunning: - outsingle = 1 - elif ev == CKEY and val == 1: - inrunning = 1 - elif ev == SKEY and val == 1: - if outrunning: - ringbell() - elif inrunning: - inrunning = 0 - else: - insingle = 1 - elif ev in (ESCKEY, WINQUIT, WINSHUT): - if ausync: - ctl.sendto(`(2,time.millitimer())`, aua) - raise stop - elif ev == REDRAW: - drawframe(x,y,w,h,0) - reshapeviewport() - drawframe(x,y,w,h,1) - if inrunning or insingle: - if outrunning: - rectcopy(vidx+x,vidy+y,vidx+x+w-1,vidy+y+h-1,x,y) - else: - rectcopy(vidx,vidy,vidx+realw-1,vidx+realh-1,0,0) - ####swapbuffers() - if outrunning or outsingle: - nframe = nframe + 1 - if not sizewritten: - wrheader(f, w, h, pf) - sizewritten = 1 - if outrunning: - grabframe(f, x, y, w, h, pf) - else: - saveframe(f, x, y, w, h, pf, outsingle) - except stop: - pass - finally: - drawmode(OVERDRAW) - color(0) - clear() - -main() diff --git a/Demo/sgi/video/cmif-film.ms b/Demo/sgi/video/cmif-film.ms deleted file mode 100755 index aa114d9788..0000000000 --- a/Demo/sgi/video/cmif-film.ms +++ /dev/null @@ -1,200 +0,0 @@ -.de PP -.LP -.. -.de pT -.IP \fB\\$1\fP -.. -.TL -CMIF video file format -.AU -Jack Jansen -(Version of 27-Feb-92) -.SH -Introduction -.PP -The CMIF video format was invented to allow various applications -to exchange video data. The format consists of -a header containing global information (like data format) -followed by a sequence of frames, each consisting of a header -followed by the actual frame data. -All information except pixel data is -encoded in ASCII. Pixel data is \fIalways\fP encoded in Silicon Graphics -order, which means that the first pixel in the frame is the lower left -pixel on the screen. -.PP -All ASCII data except the first line of the file -is in python format. This means that -outer parentheses can be ommitted, and parentheses around a tuple with -one element can also be omitted. So, the lines -.IP -.ft C -.nf -('grey',(4)) -('grey',4) -'grey',4 -.LP -have the same meaning. -To ease parsing in C programs, however, it is advised that there are -no parenteses around single items, and that there are parentheses around -lists. So, the second format above is preferred. -.PP -The current version is version 3, but this document will also explain -shortly what the previous formats looked like. -.SH -Header. -.PP -The header consists of three lines. The first line identifies the file -as a CMIF video file, and gives the version number. -It looks as follows: -.IP -.ft C -CMIF video 3.0 -.LP -All programs expect the layout to be exactly like this, so no -extra spaces, etc. should be added. -.PP -The second line specifies the data format. Its format is a python -tuple with two members. The first member is a string giving the format -type and the second is a tuple containing type-specific information. -The following formats are currently understood: -.pT rgb -The video data is 24 bit RGB packed into 32 bit words. -R is the least significant byte, then G and then B. The top byte is -unused. -.IP -There is no type-specific information, so the complete data format -line is -.IP -.ft C -('rgb',()) -.pT grey -The video data is greyscale, at most 8 bits. Data is packed into -8 bit bytes (in the low-order bits). The extra information is the -number of significant bits, so an example data format line is -.IP -.ft C -('grey',(6)) -.pT yiq -The video data is in YIQ format. This is a format that has one luminance -component, Y, and two chrominance components, I and Q. The luminance and -chrominance components are encoded in \fItwo\fP pixel arrays: first an -array of 8-bit luminance values followed by a array of 16 bit chrominance -values. See the section on chrominance coding for details. -.IP -The type specific part contains the number of bits for Y, I and Q, -the chrominance packfactor and the colormap offset. So, a sample format -information line of -.IP -.ft C -('yiq',(5,3,3,2,1024)) -.IP -means that the pictures have 5 bit Y values (in the luminance array), -3 bits of I and Q each (in the chrominance array), chrominance data -is packed for 2x2 pixels, and the first colormap index used is 1024. -.pT hls -The video data is in HLS format. L is the luminance component, H and S -are the chrominance components. The data format and type specific information -are the same as for the yiq format. -.pT hsv -The video data is in HSV format. V is the luminance component, H and S -are the chrominance components. Again, data format and type specific -information are the same as for the yiq format. -.pT rgb8 -The video data is in 8 bit dithered rgb format. This is the format -used internally by the Indigo. bit 0-2 are green, bit 3-4 are blue and -bit 5-7 are red. Because rgb8 is treated more-or-less like yiq format -internally the type-specific information is the same, with zeroes for -the (unused) chrominance sizes: -.IP -.ft C -('rgb8',(8,0,0,0,0)) -.PP -The third header line contains width and height of the video image, -in pixels, and the pack factor of the picture. For compatability, RGB -images must have a pack factor of 0 (zero), and non-RGB images must -have a pack factor of at least 1. -The packfactor is the amount of compression done on the original video -signal to obtain pictures. In other words, if only one out of three pixels -and lines is stored (so every 9 original pixels have one pixel in the -data) the packfactor is three. Width and height are the size of the -\fIoriginal\fP picture. -Viewers are expected to enlarge the picture so it is shown in the -original size. RGB videos cannot be packed. -So, a size line like -.IP -.ft C -200,200,2 -.LP -means that this was a 200x200 picture that is stored as 100x100 pixels. -.SH -Frame header -.PP -Each frame is preceded by a single header line. This line contains timing information -and optional size information. The time information is mandatory, and -contains the time this frame should be displayed, in milliseconds since -the start of the film. Frames should be stored in chronological order. -.PP -An optional second number is interpreted as the size of the luminance -data in bytes. Currently this number, if present, should always be the -same as \fCwidth*height/(packfactor*packfactor)\fP (times 4 for RGB -data), but this might change if we come up with variable-length encoding -for frame data. -.PP -An optional third number is the size of the chrominance data -in bytes. If present, the number should be equal to -.ft C -luminance_size2*/(chrompack*chrompack). -.SH -Frame data -.PP -For RGB films, the frame data is an array of 32 bit pixels containing -RGB data in the lower 24 bits. For greyscale films, the frame data -is an array of 8 bit pixels. For split luminance/chrominance films the -data consists of two parts: first an array of 8 bit luminance values -followed by an array of 16 bit chrominance values. -.PP -For all data formats, the data is stored left-to-right, bottom-to-top. -.SH -Chrominance coding -.PP -Since the human eye is apparently more sensitive to luminance changes -than to chrominance changes we support a coding where we split the luminance -and chrominance components of the video image. The main point of this -is that it allows us to transmit chrominance data in a coarser granularity -than luminance data, for instance one chrominance pixel for every -2x2 luminance pixels. According to the theory this should result in an -acceptable picture while reducing the data by a fair amount. -.PP -The coding of split chrominance/luminance data is a bit tricky, to -make maximum use of the graphics hardware on the Personal Iris. Therefore, -there are the following constraints on the number of bits used: -.IP - -No more than 8 luminance bits, -.IP - -No more than 11 bits total, -.IP - -The luminance bits are in the low-end of the data word, and are stored -as 8 bit bytes, -.IP - -The two sets of chrominance bits are stored in 16 bit words, correctly -aligned, -.IP - -The color map offset is added to the chrominance data. The offset should -be at most 4096-256-2**(total number of bits). To reduce interference with -other applications the offset should be at least 1024. -.LP -So, as an example, an HLS video with 5 bits L, 4 bits H, 2 bits S and an -offset of 1024 will look as follows in-core and in-file: -.IP -.nf -.ft C - 31 15 11 10 9 8 5 4 0 - +-----------------------------------+ -incore + 0+ 1+ S + H + L + - +-----------------------------------+ - +----------+ -L-array + 0 + L + - +----------+ - +-----------------------+ -C-array + 0+ 1+ S + H + 0 + - +-----------------------+ diff --git a/Demo/sgi/video/colorsys.py b/Demo/sgi/video/colorsys.py deleted file mode 100755 index dd3a033b26..0000000000 --- a/Demo/sgi/video/colorsys.py +++ /dev/null @@ -1,106 +0,0 @@ -# -# Module color - do color conversions -# - -ONE_THIRD=1.0/3.0 -ONE_SIXTH=1.0/6.0 -TWO_THIRD=2.0/3.0 - -def rgb_to_yiq(r,g,b): - y = 0.3*r + 0.59*g + 0.11*b - i = 0.6*r - 0.28*g - 0.32*b - q = 0.21*r- 0.52*g + 0.31*b - return (y,i,q) -def yiq_to_rgb(y,i,q): - r = y + 0.948262*i + 0.624013*q - g = y - 0.276066*i - 0.639810*q - b = y - 1.105450*i + 1.729860*q - if r < 0.0: r = 0.0 - if g < 0.0: g = 0.0 - if b < 0.0: b = 0.0 - if r > 1.0: r = 1.0 - if g > 1.0: g = 1.0 - if b > 1.0: b = 1.0 - return (r,g,b) - -def _v(m1,m2,hue): - if hue >= 1.0: hue = hue - 1.0 - if hue < 0.0: hue = hue + 1.0 - if hue < ONE_SIXTH: - return m1 + (m2-m1)*hue*6.0 - if hue < 0.5: - return m2 - if hue < TWO_THIRD: - return m1 + (m2-m1)*(TWO_THIRD-hue)*6.0 - return m1 - -def rgb_to_hls(r,g,b): - maxc = max(r,g,b) - minc = min(r,g,b) - l = (minc+maxc)/2.0 - if minc == maxc: - return 0.0, l, 0.0 - if l <= 0.5: - s = (maxc-minc)/(maxc+minc) - else: - s = (maxc-minc)/(2-maxc-minc) - rc = (maxc-r)/(maxc-minc) - gc = (maxc-g)/(maxc-minc) - bc = (maxc-b)/(maxc-minc) - if r == maxc: - h = bc-gc - elif g == maxc: - h = 2.0+rc-bc - else: - h = 4.0+gc-rc - h = h/6.0 - if h < 0.0: - h = h + 1.0 - return h,l,s -def hls_to_rgb(h,l,s): - if s == 0.0: - return l,l,l - if l <= 0.5: - m2 = l * (1.0+s) - else: - m2 = l+s-(l*s) - m1 = 2.0*l - m2 - return (_v(m1,m2,h+ONE_THIRD), _v(m1,m2,h), _v(m1,m2,h-ONE_THIRD)) - -def rgb_to_hsv(r,g,b): - maxc = max(r,g,b) - minc = min(r,g,b) - v = maxc - if minc == maxc: - return 0.0, 0.0, v - s = (maxc-minc)/maxc - rc = (maxc-r)/(maxc-minc) - gc = (maxc-g)/(maxc-minc) - bc = (maxc-b)/(maxc-minc) - if r == maxc: - h = bc-gc - elif g == maxc: - h = 2.0+rc-bc - else: - h = 4.0+gc-rc - h = h/6.0 - if h < 0.0: - h = h + 1.0 - return h,s,v -def hsv_to_rgb(h,s,v): - if s == 0.0: - return v,v,v - i = int(h*6.0) - f = (h*6.0)-i - p = v*(1.0-s) - q = v*(1.0-s*f) - t = v*(1.0-s*(1.0-f)) - if i in (0,6): return v,t,p - if i == 1: return q,v,p - if i == 2: return p,v,t - if i == 3: return p,q,v - if i == 4: return t,p,v - if i == 5: return v,p,q - print i, h, f - print h, s, v - raise 'Bad color' diff --git a/Demo/sgi/video/i2v.c b/Demo/sgi/video/i2v.c deleted file mode 100755 index 21dfabe2b2..0000000000 --- a/Demo/sgi/video/i2v.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * i2v -- image-to-video. - * Convert an SGI image file to a format that is immediately usable - * by lrectwrite. - * The header of the file contains a description (in ASCII) - * padded to 8196 byte for fast access of the rest of the file. - * - * Based upon "showimg.c" by Paul Haeberli. - * --Guido van Rossum, CWI, Amsterdam - */ -#include -#include -#include -#include - -unsigned short rs[8192]; -unsigned short gs[8192]; -unsigned short bs[8192]; - -IMAGE *image; -int xsize, ysize, zsize; -FILE *fp; - -char header[100]; -char *progname = "i2v"; - -main(argc,argv) -int argc; -char **argv; -{ - int y; - if (argc > 0) progname = argv[0]; - if( argc != 3 ) { - fprintf(stderr, "usage: %s infile outfile\n", progname); - exit(2); - } - if( (image=iopen(argv[1],"r")) == NULL ) { - fprintf(stderr, "%s: can't open input file %s\n",progname, argv[1]); - exit(1); - } - xsize = image->xsize; - ysize = image->ysize; - zsize = image->zsize; - if ((fp = fopen(argv[2], "w")) == NULL) { - fprintf(stderr,"%s: can't open output file %s\n", progname, argv[2]); - exit(1); - } - fprintf(fp, "CMIF video 1.0\n"); - fprintf(fp, "(%d, %d, %d)\n", xsize, ysize, 0); - fprintf(fp, "0, %ld\n", (long)xsize * (long)ysize * sizeof(long)); - fflush(fp); - for(y = 0; y < ysize; y++) { - if(zsize<3) { - getrow(image, rs, y, 0); - writepacked(xsize, rs, rs, rs); - } else { - getrow(image, rs, y, 0); - getrow(image, gs, y, 1); - getrow(image, bs, y, 2); - writepacked(xsize, rs, gs, bs); - } - } - exit(0); -} - -writepacked(n, rsptr, gsptr, bsptr) - int n; - short *rsptr, *gsptr, *bsptr; -{ - long parray[8192]; - long *pptr = parray; - int i = n; - while (--i >= 0) { - *pptr++ = *rsptr++ | (*gsptr++<<8) | (*bsptr++<<16); - } - if (fwrite((char *) parray, sizeof(long), n, fp) != n) { - perror("fwrite"); - exit(1); - } -} diff --git a/Demo/sgi/video/imgconv.py b/Demo/sgi/video/imgconv.py deleted file mode 100755 index 291fdc8125..0000000000 --- a/Demo/sgi/video/imgconv.py +++ /dev/null @@ -1,140 +0,0 @@ -import imageop - -error = 'imgconv.error' - -LOSSY = 1 -NOT_LOSSY = 0 - -def null(img, x, y): - return img - -def mono2grey(img, x, y): - return imageop.mono2grey(img, x, y, 0, 255) - -def grey2jpeggrey(img, x, y): - import jpeg - return jpeg.compress(img, x, y, 1) - -def rgb2jpeg(img, x, y): - import jpeg - return jpeg.compress(img, x, y, 4) - -def jpeggrey2grey(img, width, height): - import jpeg - data, width, height, bytesperpixel = jpeg.decompress(img) - if bytesperpixel <> 1: raise RuntimeError, 'not greyscale jpeg' - return data - -def jpeg2rgb(img, width, height): - import cl, CL - import jpeg - data, width, height, bytesperpixel = jpeg.decompress(img) - if bytesperpixel <> 4: raise RuntimeError, 'not rgb jpeg' - return data - -converters = [ \ - ('grey', 'grey4', imageop.grey2grey4, LOSSY), \ - ('grey', 'grey2', imageop.dither2grey2, LOSSY), \ - ('grey', 'mono', imageop.dither2mono, LOSSY), \ - ('mono', 'grey', mono2grey, NOT_LOSSY), \ - ('grey2', 'grey', imageop.grey22grey, NOT_LOSSY), \ - ('grey4', 'grey', imageop.grey42grey, NOT_LOSSY), \ - ('rgb', 'rgb8', imageop.rgb2rgb8, LOSSY), \ - ('rgb8', 'rgb', imageop.rgb82rgb, NOT_LOSSY), \ - ('rgb', 'grey', imageop.rgb2grey, LOSSY), \ - ('grey', 'rgb', imageop.grey2rgb, NOT_LOSSY), \ - ('jpeggrey','grey',jpeggrey2grey, NOT_LOSSY), \ - ('grey', 'jpeggrey',grey2jpeggrey, LOSSY), \ - ('jpeg', 'rgb', jpeg2rgb, NOT_LOSSY), \ - ('rgb', 'jpeg', rgb2jpeg, LOSSY), \ -] - -built = {} - -def addconverter(fcs, tcs, lossy, func): - for i in range(len(converters)): - ifcs, itcs, irtn, ilossy = converters[i] - if (fcs, tcs) == (ifcs, itcs): - converters[i] = (fcs, tcs, func, lossy) - return - converters.append((fcs,tcs,lossy,func)) - -def getconverter(fcs, tcs): - # - # If formats are the same return the dummy converter - # - if fcs == tcs: return null - # - # Otherwise, if we have a converter return that one - # - for ifcs, itcs, irtn, ilossy in converters: - if (fcs, tcs) == (ifcs, itcs): - return irtn - # - # Finally, we try to create a converter - # - if not built.has_key(fcs): - built[fcs] = enumerate_converters(fcs) - if not built[fcs].has_key(tcs): - raise error, 'Sorry, conversion from '+fcs+' to '+tcs+ \ - ' is not implemented' - if len(built[fcs][tcs]) == 3: - # - # Converter not instantiated yet - # - built[fcs][tcs].append(instantiate_converter(built[fcs][tcs])) - cf = built[fcs][tcs][3] - return cf - -def enumerate_converters(fcs): - cvs = {} - formats = [fcs] - steps = 0 - while 1: - workdone = 0 - for ifcs, itcs, irtn, ilossy in converters: - if ifcs == fcs: - template = [ilossy, 1, [irtn]] - elif cvs.has_key(ifcs): - template = cvs[ifcs][:] - template[2] = template[2][:] - if ilossy: - template[0] = ilossy - template[1] = template[1] + 1 - template[2].append(irtn) - else: - continue - if not cvs.has_key(itcs): - cvs[itcs] = template - workdone = 1 - else: - previous = cvs[itcs] - if template < previous: - cvs[itcs] = template - workdone = 1 - if not workdone: - break - steps = steps + 1 - if steps > len(converters): - print '------------------loop in emunerate_converters--------' - print 'CONVERTERS:' - print converters - print 'RESULTS:' - print cvs - raise error, 'Internal error - loop' - return cvs - -def instantiate_converter(args): - list = args[2] - cl = RtConverters(list) - args.append(cl.convert) - return args - -class RtConverters: - def __init__(self, list): - self.list = list - - def convert(self, img, w, h): - for cv in self.list: - img = cv(img, w, h) - return img diff --git a/Demo/sgi/video/makemovie.py b/Demo/sgi/video/makemovie.py deleted file mode 100755 index 5cb41cde2e..0000000000 --- a/Demo/sgi/video/makemovie.py +++ /dev/null @@ -1,218 +0,0 @@ -#! /ufs/guido/bin/sgi/python -#! /ufs/guido/src/video/py - -# Capture a CMIF movie using the Indigo video library and board - - -# Usage: -# -# makemovie [-q queuesize] [-t recordtime] [-a] [moviefile [audiofile]] - - -# Options: -# -# -q queuesize : set the capture queue size (default and max 16) -# -t recordtime : set the record time in seconds (default 5 seconds) -# -a : record audio as well -# moviefile : here goes the movie data (default film.video); -# the format is documented in cmif-film.ms -# audiofile : with -a, here goes the audio data (default film.aiff); -# audio data is recorded in AIFF format, using the -# input sampling rate, source and volume set by the -# audio panel, in mono, 8 bits/sample - - -# User interface: -# -# Start the application. Resize the window to the desired movie size. -# Click the left mouse button to start recording (recording starts -# when you release the mouse button). Recording time is specified by -# the -t option (XXX this should change). -# -# Press ESC or select the window manager Quit or Close window option -# to quit. (You can do this without recording -- then the output -# files are untouched.) -# -# (It is possible to record more than once; but this doesn't set the -# time stamps correctly yet, and doesn't work at all with audio. So -# don't use.) - - -# XXX To do: -# -# fix timestamps for second and further recordings -# fix audio " " " " " -# flush audio buffer when recording starts -# make code more readable - - -import sys -sys.path.append('/ufs/guido/src/video') -import sv, SV -import VFile -import gl, GL, DEVICE -import al, AL -import time -import posix -import getopt -import string - - -def main(): - QSIZE = 16 - TIME = 5 - audio = 0 - - opts, args = getopt.getopt(sys.argv[1:], 'aq:t:') - for opt, arg in opts: - if opt == '-a': - audio = 1 - elif opt == '-q': - QSIZE = string.atoi(arg) - elif opt == '-t': - TIME = string.atoi(arg) - - if args: - filename = args[0] - else: - filename = 'film.video' - - if audio: - if args[1:]: - audiofilename = args[1] - else: - audiofilename = 'film.aiff' - - gl.foreground() - - x, y = SV.PAL_XMAX / 4, SV.PAL_YMAX / 4 - print x, 'x', y - - gl.minsize(40, 30) - gl.stepunit(8, 6) - gl.maxsize(SV.PAL_XMAX, SV.PAL_YMAX) - gl.keepaspect(SV.PAL_XMAX, SV.PAL_YMAX) - win = gl.winopen(filename) - x, y = gl.getsize() - print x, 'x', y - - v = sv.OpenVideo() - v.BindGLWindow(win, SV.IN_REPLACE) - v.SetSize(x, y) - v.BindGLWindow(win, SV.IN_REPLACE) - - v.SetCaptureFormat(SV.RGB_FRAMES) - v.SetCaptureMode(SV.BLOCKING_CAPTURE) - v.SetQueueSize(QSIZE) - v.InitCapture() - if v.GetQueueSize() != QSIZE: - QSIZE = v.GetQueueSize() - print 'Warning: QSIZE reduced to', QSIZE - - gl.qdevice(DEVICE.LEFTMOUSE) - gl.qdevice(DEVICE.WINQUIT) - gl.qdevice(DEVICE.WINSHUT) - gl.qdevice(DEVICE.ESCKEY) - - print 'Click left mouse to start recording', TIME, 'seconds' - ofile = None - afile = None - # Mouse down opens the file & freezes window - # Mouse up starts recording frames - - while 1: - dev, val = gl.qread() - if dev == DEVICE.LEFTMOUSE: - # Start recording - if val == 1: - # Mouse down -- preparations - if ofile == None: - ofile = VFile.VoutFile().init(filename) - ofile.format = 'rgb8' - ofile.width = x - ofile.height = y - ofile.writeheader() - # XXX other format bits? - # The window can't be resized from now - gl.prefsize(x, y) - gl.winconstraints() - gl.wintitle('* ' + filename) - if audio: - afile = initaudio(audiofilename) - continue - # Mouse up -- start actual recording - global recording, stop_recording - if audio: - stop_recording = 0 - recording.release() - t0 = time.millitimer() - v.StartCapture() - while 1: - t = time.millitimer() - t0 - if t >= TIME*1000: - break - if v.GetCaptured() > 2: - doframe(v, ofile, x, y, t) - v.StopCapture() - stop_recording = 1 - while v.GetCaptured() > 0: - doframe(v, ofile, x, y, t) - t = time.millitimer() - t0 - gl.wintitle(filename) - elif dev == DEVICE.REDRAW: - # Window resize (or move) - x, y = gl.getsize() - print x, 'x', y - v.SetSize(x, y) - v.BindGLWindow(win, SV.IN_REPLACE) - elif dev in (DEVICE.ESCKEY, DEVICE.WINQUIT, DEVICE.WINSHUT): - # Quit - if ofile: - ofile.close() - if afile: - afile.destroy() - posix._exit(0) - # EndCapture dumps core... - v.EndCapture() - v.CloseVideo() - gl.winclose(win) - -def doframe(v, ofile, x, y, t): - cd, start = v.GetCaptureData() - data = cd.interleave(x, y) - cd.UnlockCaptureData() - ofile.writeframe(t, data, None) - -AQSIZE = 16000 - -def initaudio(filename): - import thread, aiff - global recording, stop_recording - afile = aiff.Aiff().init(filename, 'w') - afile.nchannels = AL.MONO - afile.sampwidth = AL.SAMPLE_8 - params = [AL.INPUT_RATE, 0] - al.getparams(AL.DEFAULT_DEVICE, params) - print 'rate =', params[1] - afile.samprate = params[1] - c = al.newconfig() - c.setchannels(AL.MONO) - c.setqueuesize(AQSIZE) - c.setwidth(AL.SAMPLE_8) - aport = al.openport(filename, 'r', c) - recording = thread.allocate_lock() - recording.acquire() - stop_recording = 0 - thread.start_new_thread(recorder, (afile, aport)) - return afile - -def recorder(afile, aport): - # XXX recording more than one fragment doesn't work - # XXX (the thread never dies) - recording.acquire() - while not stop_recording: - data = aport.readsamps(AQSIZE/2) - afile.writesampsraw(data) - del data - -main() diff --git a/Demo/sgi/video/rgb2video.py b/Demo/sgi/video/rgb2video.py deleted file mode 100755 index b6c34ebc35..0000000000 --- a/Demo/sgi/video/rgb2video.py +++ /dev/null @@ -1,79 +0,0 @@ -import sys -import VFile -import getopt -import imgfile -import string -import imgconv - -def main(): - format = None - interval = 40 - outfile = 'film.video' - - try: - opts, args = getopt.getopt(sys.argv[1:], 'f:i:o:') - except getopt.error: - usage() - sys.exit(1) - for opt, arg in opts: - if opt == '-f': - format = arg - elif opt == '-i': - interval = string.atoi(arg) - elif opt == '-o': - outfile = arg - else: - usage() - sys.exit(1) - if not args: - usage() - sys.exit(1) - - xsize, ysize, zsize = imgfile.getsizes(args[0]) - nxsize = xsize - - if zsize == 3: - oformat = 'rgb' - elif zsize == 1: - oformat = 'grey' - if xsize % 4: - addbytes = 4-(xsize%4) - nxsize = xsize + addbytes - print 'rgb2video: add',addbytes,'pixels per line' - else: - print 'rgb2video: incorrect number of planes:',zsize - sys.exit(1) - - if format == None: - format = oformat - cfunc = imgconv.getconverter(oformat, format) - - vout = VFile.VoutFile(outfile) - vout.format = format - vout.width = nxsize - vout.height = ysize - vout.writeheader() - t = 0 - sys.stderr.write('Processing ') - for img in args: - sys.stderr.write(img + ' ') - if imgfile.getsizes(img) <> (xsize, ysize, zsize): - print 'rgb2video: Image is different size:', img - sys.exit(1) - data = imgfile.read(img) - if xsize <> nxsize: - ndata = '' - for i in range(0,len(data), xsize): - curline = data[i:i+xsize] - ndata = ndata + curline + ('\0'*(nxsize-xsize)) - data = ndata - vout.writeframe(t, cfunc(data, nxsize, ysize), None) - t = t + interval - sys.stderr.write('\n') - vout.close() - -def usage(): - print 'Usage: rgb2video [-o output] [-i frameinterval] [-f format] rgbfile ...' - -main() - diff --git a/Demo/sgi/video/senddefs.py b/Demo/sgi/video/senddefs.py deleted file mode 100755 index c3ce2cd1e9..0000000000 --- a/Demo/sgi/video/senddefs.py +++ /dev/null @@ -1,11 +0,0 @@ -# Defaults shared by Vsend and Vreceice - -DEFMCAST = '225.0.0.250' -DEFPORT = 5555 - -PKTMAX_UCAST = 16*1024 - 6 -PKTMAX_BCAST = 1450 -DEFPKTMAX = PKTMAX_BCAST - -DEFWIDTH = 400 -DEFHEIGHT = 300 diff --git a/Demo/sgi/video/squash.c b/Demo/sgi/video/squash.c deleted file mode 100755 index d5ea946924..0000000000 --- a/Demo/sgi/video/squash.c +++ /dev/null @@ -1,130 +0,0 @@ -#include - -long *bm; -long h, w; -long factor; - -#define OC(x,xi) ((x)*factor+(xi)) -#define BM(x,xi,y,yi) bm[OC(y,yi)*w+OC(x,xi)] - -#define COMP(r,g,b) ((r) | ((g)<<8) | ((b) << 16)) - -#define R(comp) ((comp) & 0xff) -#define G(comp) (((comp)>>8) & 0xff) -#define B(comp) (((comp)>>16) & 0xff) - -main(argc, argv) - char **argv; -{ - char lbuf[100]; - int nh, nw; - int x, y, xi, yi; - int num; - int r, g, b; - long data; - long *nbm, *nbmp; - int i; - int bits, mask, roundbit, addbit; - int pf; - int newfmt = 0; - - if( argc != 2 && argc != 3) { - fprintf(stderr, "Usage: squash factor [bits]\n"); - exit(1); - } - factor = atoi(argv[1]); - if ( argc > 2 ) { - bits = atoi(argv[2]); - mask = (1 << bits) - 1; - mask <<= (8-bits); - roundbit = 1 << (7-bits); - addbit = 1 << (8-bits); - fprintf(stderr, "%x %x %x\n", mask, roundbit, addbit); - } else { - mask = 0xff; - roundbit = 0; - addbit = 0; - } - gets(lbuf); - if ( strncmp( lbuf, "CMIF", 4) == 0 ) { - newfmt = 1; - gets(lbuf); - if( sscanf(lbuf, "(%d,%d,%d)", &w, &h, &pf) != 3) { - fprintf(stderr, "%s: bad size spec: %s\n", argv[0], lbuf); - exit(1); - } - if ( pf != 0 ) { - fprintf(stderr, "%s: packed file\n", argv[0]); - exit(1); - } - } else { - if ( sscanf(lbuf, "(%d,%d)", &w, &h) != 2) { - fprintf(stderr, "%s: bad size spec: %s\n", argv[0], lbuf); - exit(1); - } - } - nh = h / factor; - nw = w / factor; - if ( newfmt ) - printf("CMIF video 1.0\n(%d,%d,%d)\n", nw, nh, 0); - else - printf("(%d,%d)\n", nw, nh); - if ( (bm = (long *)malloc(h*w*sizeof(long))) == 0) { - fprintf(stderr, "%s: No memory\n", argv[0]); - exit(1); - } - if ( (nbm = (long *)malloc(nh*nw*sizeof(long))) == 0) { - fprintf(stderr, "%s: No memory\n", argv[0]); - exit(1); - } - while( !feof(stdin) ) { - { int t, s; - gets(lbuf); - if ( feof(stdin) ) break; - if ( sscanf(lbuf, "%d,%d", &t,&s) == 2) { - if ( s != h*w*4 ) { - fprintf(stderr, "Size changed from %d to %d: %s\n",4*h*w,s, lbuf); - exit(1); - } - printf("%d, %d\n", t, nh*nw*4); - } else { - puts(lbuf); - } - } - fprintf(stderr, "Reading %d\n", h*w*sizeof(long)); - if ( (i=fread(bm, 1, h*w*sizeof(long), stdin)) != h*w*sizeof(long)) { - fprintf(stderr, "%s: short read, %d wanted %d\n", argv[0], - i, h*w*sizeof(long)); - exit(1); - } - nbmp = nbm; - for( y=0; y - -long *bm; -long h, w; -long factor; - -#define OC(x,xi) ((x)*factor+(xi)) -#define BM(x,xi,y,yi) bm[OC(y,yi)*w+OC(x,xi)] - -#define COMP(r,g,b) ((r) | ((g)<<8) | ((b) << 16)) - -#define R(comp) ((comp) & 0xff) -#define G(comp) (((comp)>>8) & 0xff) -#define B(comp) (((comp)>>16) & 0xff) - -main(argc, argv) - char **argv; -{ - char lbuf[100]; - int nh, nw; - int x, y, xi, yi; - int num; - int r, g, b; - long data; - long *nbm, *nbmp; - int i; - - if( argc != 2) { - fprintf(stderr, "Usage: squash factor\n"); - exit(1); - } - factor = atoi(argv[1]); - gets(lbuf); - if ( sscanf(lbuf, "(%d,%d)", &w, &h) != 2) { - fprintf(stderr, "%s: bad size spec: %s\n", argv[0], lbuf); - exit(1); - } - nh = h / factor; - nw = w / factor; - printf("(%d,%d)\n", nw, nh); - if ( (bm = (long *)malloc(h*w*sizeof(long))) == 0) { - fprintf(stderr, "%s: No memory\n", argv[0]); - exit(1); - } - if ( (nbm = (long *)malloc(nh*nw*sizeof(long))) == 0) { - fprintf(stderr, "%s: No memory\n", argv[0]); - exit(1); - } - while( !feof(stdin) ) { - gets(lbuf); - if ( feof(stdin) ) break; - puts(lbuf); - fprintf(stderr, "Reading %d\n", h*w*sizeof(long)); - if ( (i=fread(bm, 1, h*w*sizeof(long), stdin)) != h*w*sizeof(long)) { - fprintf(stderr, "%s: short read, %d wanted %d\n", argv[0], - i, h*w*sizeof(long)); - exit(1); - } - nbmp = nbm; - for( y=0; y size: - raise EOFError - dostat(w2, h2, data) - nframes = nframes+1 - t1 = millitimer() - - t = 0.001 * (t1-t0) - fps = 0.1 * int(10*nframes/t) - print nframes, 'frames in', t, 'sec. =', fps, 'frames/sec.' - -def dostat(w, h, data): - print - stat3(w, h, data) - -# Statistic op 1: frequencies of byte values -def stat1(w, h, data): - bins = [0]*256 - for c in data: - i = ord(c) - bins[i] = bins[i]+1 - prbins(bins) - -def prbins(bins): - import string - s = '' - tot = 0 - for i in range(256): - tot = tot + bins[i] - s = s + string.rjust(`bins[i]`, 4) - if len(s) >= 4*16: - print s, string.rjust(`tot`, 7) - s = '' - tot = 0 - -# Statistic op 2: run lengths -def stat2(w, h, data): - runs = [] - for y in range(h): - count, value = 0, ord(data[y*w]) - for c in data[y*w : y*w+w]: - i = ord(c) - if i <> value: - runs.append(count, value) - count, value = 0, i - count = count+1 - runs.append(count, value) - print len(runs), 'runs =', 0.1 * (10*w*h/len(runs)), 'bytes/run' - -# Statistic op 3: frequencies of byte differences -def stat3(w, h, data): - bins = [0]*256 - prev = 0 - for c in data: - i = ord(c) - delta = divmod(i-prev, 256)[1] - prev = i - bins[delta] = bins[delta]+1 - prbins(bins) - -# Try packing -def packblock(w, h, data): - res = '' - for y in range(h): - res = res + packline(data[y*w : y*w+w]) - return res - -def packline(line): - bytes = [] - for c in line: - bytes.append(ord(c)) - prev = bytes[0] - i, n = 1, len(bytes) - while i < n: - for pack in (0, 2, 4, 8): - if pack == 0: - lo, hi = 0, 0 - else: - hi = pow(2, pack-1)-1 - lo = -hi-1 - p = prev - j = i - count = 0 - while j < n: - x = bytes[j] - delta = byte(x-p) - if not lo <= delta <= hi: - break - p = x - j = j+1 - -def byte(x): return divmod(x, 256)[1] - -main() diff --git a/Demo/sgi/video/svgrab24.c b/Demo/sgi/video/svgrab24.c deleted file mode 100755 index 3418b145da..0000000000 --- a/Demo/sgi/video/svgrab24.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * svgrab24 - Grab the current video input image into an rgb file. - * - * Jack Jansen, CWI, May 93. - * - * Adapted from grabone.c - */ - -#ident "$Revision$" - -#include -#include -#include -#include -#include -#include -#include - -main(int argc, char *argv[]) -{ - SVhandle V; - svCaptureInfo ci; - boolean debug; - int ch, errflg; - int bufferSize; - long *buffer; - IMAGE *imgfile; - short *r, *g, *b; - int x, y; - char *ProgName = argv[0]; - - debug = FALSE; - ci.format = SV_RGB32_FRAMES; - ci.width = 0; - ci.height = 0; - ci.size = 1; - - argv++; argc--; - if ( argc > 2 && strcmp(argv[0], "-w") == 0) { - ci.width = atoi(argv[1]); - argc -= 2; - argv += 2; - } - if ( argc != 1 ) { - fprintf(stderr, "Usage: %s [-w width] rgbfilename\n", ProgName); - exit(1); - } - - /* Open video device */ - if ((V = svOpenVideo()) == NULL) { - svPerror("open"); - exit(1); - } - - if (svQueryCaptureBufferSize(V, &ci, &bufferSize) < 0) { - svPerror("svQueryCaptureBufferSize"); - exit(1); - } - buffer = malloc(bufferSize); - - if (svCaptureOneFrame(V, ci.format, &ci.width, &ci.height, buffer) < 0) { - svPerror("svCaptureOneFrame"); - exit(1); - } - if (debug) { - printf("captured size: %d by %d\n", ci.width, ci.height); - } - - if ( (imgfile=iopen(argv[0], "w", RLE(1), 3, ci.width, ci.height, 3)) == 0) { - perror(argv[1]); - exit(1); - } - r = (short *)malloc(ci.width*sizeof(short)); - g = (short *)malloc(ci.width*sizeof(short)); - b = (short *)malloc(ci.width*sizeof(short)); - if ( !r || !g || !b ) { - fprintf(stderr, "%s: malloc failed\n", ProgName); - exit(1); - } - for(y=0; y>8) & 0xff; - b[x] = (data>>16) & 0xff; - } - if ( putrow(imgfile, r, y, 0) == 0 || - putrow(imgfile, g, y, 1) == 0 || - putrow(imgfile, b, y, 2) == 0) { - fprintf(stderr, "%s: putrow failed\n", ProgName); - exit(1); - } - } - iclose(imgfile); - exit(0); -} diff --git a/Demo/sgi/video/syncaudio.py b/Demo/sgi/video/syncaudio.py deleted file mode 100755 index fd09d2879c..0000000000 --- a/Demo/sgi/video/syncaudio.py +++ /dev/null @@ -1,94 +0,0 @@ -import AL -import al -import sys -import vtime -import socket -import time - - -SLEEPTIME = 500 # 500 ms sleeps -SAMPLEFREQ = 16000 # 16Khz samples -SAMPLERATE = AL.RATE_16000 -NEEDBUFFERED = SAMPLEFREQ # Buffer 1 second of sound -BUFFERSIZE = NEEDBUFFERED*4 # setqueuesize() par for 2 second sound - -AVSYNCPORT = 10000 # Port for time syncing -AVCTLPORT = 10001 # Port for record start/stop - -def main(): - if len(sys.argv) <> 3: - print 'Usage: ', sys.argv[0], 'videohostname soundfile' - sys.exit(1) - # - ofile = open(sys.argv[2], 'w') - # - globaltime = vtime.VTime().init(0,sys.argv[1],AVSYNCPORT) - # - ctl = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) - ctl.bind((socket.gethostname(),AVCTLPORT)) - # - inp = openmic() - # - out = 0 # Open aiff file - # - while 1: - if mainloop(None, ctl, inp, out, globaltime): - break - if mainloop(ofile, ctl, inp, out, globaltime): - break - pass # Close aiff file - sys.exit(0) -# -def openmic(): - conf = al.newconfig() - conf.setqueuesize(BUFFERSIZE) - conf.setwidth(AL.SAMPLE_16) - conf.setchannels(AL.MONO) - return al.openport('micr','r',conf) -# -def mainloop(ofile, ctl, inp, out, globaltime): - # - # Wait for sync packet, keeping 1-2 seconds of sound in the - # buffer - # - totsamps = 0 - totbytes = 0 - starttime = time.millitimer() - while 1: - time.millisleep(SLEEPTIME) - if ctl.avail(): - break - nsamples = inp.getfilled()-NEEDBUFFERED - if nsamples>0: - data = inp.readsamps(nsamples) - totsamps = totsamps + nsamples - totbytes = totbytes + len(data) - if ofile <> None: - ofile.write(data) - # - # Compute his starttime and the timestamp of the first byte in the - # buffer. Discard all buffered data upto his starttime - # - startstop,histime = eval(ctl.recv(100)) - if (ofile == None and startstop == 0) or \ - (ofile <> None and startstop == 1): - print 'Sync error: saving=',save,' request=',startstop - sys.exit(1) - filllevel = inp.getfilled() - filltime = time.millitimer() - filltime = filltime - filllevel / (SAMPLEFREQ/1000) - starttime = globaltime.his2mine(histime) - nsamples = starttime - filltime - if nsamples < 0: - print 'Start/stop signal came too late' - sys.exit(1) - nsamples = nsamples * (SAMPLEFREQ / 1000) - data = inp.readsamps(nsamples) - totsamps = totsamps + nsamples - totbytes = totbytes + len(data) - print 'Time: ', time.millitimer()-starttime, ', Bytes: ', totbytes, ', Samples: ', totsamps - if ofile <> None: - ofile.write(data) - return (startstop == 2) - -main() diff --git a/Demo/sgi/video/tomono.c b/Demo/sgi/video/tomono.c deleted file mode 100755 index 546af68afd..0000000000 --- a/Demo/sgi/video/tomono.c +++ /dev/null @@ -1,165 +0,0 @@ -#include - -long *bm; -long *nbm; -long h, w; -int nh, nw; -long factor; - -#define OC(x,xi) ((x)*factor+(xi)) -#define BM(x,xi,y,yi) bm[OC(y,yi)*w+OC(x,xi)] - -#define COMP(r,g,b) ((r) | ((g)<<8) | ((b) << 16)) - -#define R(comp) ((comp) & 0xff) -#define G(comp) (((comp)>>8) & 0xff) -#define B(comp) (((comp)>>16) & 0xff) - -#define CHOICEFUNC(np1, np2) ( random() & 1 ) - -int inlevels = 3*255; -int outlevels = 1; - -main(argc, argv) - char **argv; -{ - char lbuf[100]; - int x, y, xi, yi; - int num; - int r, g, b; - long data; - int i; - double greyness; - int inpixels, outpixels; - int resid; - - setvbuf(stdout, 0, _IOFBF, 1024*128); - if( argc != 2) { - fprintf(stderr, "Usage: tomono factor\n"); - exit(1); - } - factor = atoi(argv[1]); - gets(lbuf); - if ( sscanf(lbuf, "(%d,%d)", &w, &h) != 2) { - fprintf(stderr, "%s: bad size spec: %s\n", argv[0], lbuf); - exit(1); - } - nh = h / factor; - nw = w / factor; - printf("(%d,%d)\n", nw, nh); - if ( (bm = (long *)malloc(h*w*sizeof(long))) == 0) { - fprintf(stderr, "%s: No memory\n", argv[0]); - exit(1); - } - if ( (nbm = (long *)malloc(nh*nw*sizeof(long))) == 0) { - fprintf(stderr, "%s: No memory\n", argv[0]); - exit(1); - } - while( !feof(stdin) ) { - gets(lbuf); - if ( feof(stdin) ) break; - puts(lbuf); - fprintf(stderr, "Reading %d\n", h*w*sizeof(long)); - if ( (i=fread(bm, 1, h*w*sizeof(long), stdin)) != h*w*sizeof(long)) { - fprintf(stderr, "%s: short read, %d wanted %d\n", argv[0], - i, h*w*sizeof(long)); - exit(1); - } - /* - ** Compute picture blackness. - */ - inpixels = 0; - inpixels = countpixels(0,0,w,h); - greyness = (double)inpixels/(h*w*inlevels); - fprintf(stderr, "%3.1f%% grey\n", 100.0*greyness); - outpixels = (int)(greyness*outlevels*nh*nw); - fprintf(stderr, "Inpixels: %d (%d) Outpixels %d\n", inpixels, inpixels/inlevels, outpixels); - resid = fillpixels(0,0,nw,nh,0,0,w,h,outpixels); - if ( resid > 1 ) fprintf(stderr, "Residue: %d pixels\n", resid); - fprintf(stderr, "Writing %d\n", (nh*nw)*sizeof(long)); - fwrite(nbm, 1, (nh*nw)*sizeof(long), stdout); - } - exit(0); -} - -countpixels(x0,y0,x1,y1) -{ - int x, y, tot, data; - - tot = 0; - for( y=y0; y= x1 && y0+1 >= y1 ) { - if ( npixels ) { - nbm[y0*nw+x0] = 0xffffff; -/* fprintf(stderr, "->%d,%d\n", x0,y0); */ - return npixels - 1; - } - return 0; - } - if ( x1-x0 < y1-y0 ) { - if ( y1 - y0 <= 2 ) - m = y0 + 1; - else - m = y0+1+(random()%(y1-y0-1)); -/* fprintf(stderr,"%d,%d %d,%d Y %d\n", x0, x1, y0, y1, m); */ - /* om = (oy0+oy1)/2; */ om = m; - p1 = countpixels(ox0,oy0,ox1,om); - p2 = countpixels(ox0,om,ox1,oy1); - np1 = (int)(((float)p1/(p1+p2))*npixels); - np2 = (int)(((float)p2/(p1+p2))*npixels); - rp = npixels - np1 - np2; - if ( rp ) { - np1 += rp/2; - rp = rp - rp/2; - np2 += rp; - } - resid = 0; - if ( CHOICEFUNC(np1, np2) ) { - resid = fillpixels(x0,y0,x1,m,ox0,oy0,ox1,om,np1+resid); - resid = fillpixels(x0,m,x1,y1,ox0,om,ox1,oy1,np2+resid); - } else { - resid = fillpixels(x0,m,x1,y1,ox0,om,ox1,oy1,np2+resid); - resid = fillpixels(x0,y0,x1,m,ox0,oy0,ox1,om,np1+resid); - } - } else { - if ( x1 - x0 <= 2 ) - m = x0 + 1; - else - m = x0+1+(random()%(x1-x0-1)); -/* fprintf(stderr,"%d,%d %d,%d X %d\n", x0, x1, y0, y1, m); */ - /* om = (ox0+ox1)/2; */ om = m; - p1 = countpixels(ox0,oy0,om,oy1); - p2 = countpixels(om,oy0,ox1,oy1); - np1 = (int)(((float)p1/(p1+p2))*npixels); - np2 = (int)(((float)p2/(p1+p2))*npixels); - rp = npixels - np1 - np2; - if ( rp ) { - np1 += rp/2; - rp = rp - rp/2; - np2 += rp; - } - resid = 0; - if ( CHOICEFUNC(np1, np2) ) { - resid = fillpixels(x0,y0,m,y1,ox0,oy0,om,oy1,np1+resid); - resid = fillpixels(m,y0,x1,y1,om,oy0,ox1,oy1,np2+resid); - } else { - resid = fillpixels(m,y0,x1,y1,om,oy0,ox1,oy1,np2+resid); - resid = fillpixels(x0,y0,m,y1,ox0,oy0,om,oy1,np1+resid); - } - } - return resid; -} diff --git a/Demo/sgi/video/tv.py b/Demo/sgi/video/tv.py deleted file mode 100755 index da4bacbb63..0000000000 --- a/Demo/sgi/video/tv.py +++ /dev/null @@ -1,79 +0,0 @@ -import string - -from socket import * -from gl import * -from GL import * -from DEVICE import * -from time import millisleep, millitimer - -PORT = 5555 - -PF = 2 # packfactor -HS = 40 # Header size - -def testimage(): - RGBcolor(0, 0, 0) - clear() - RGBcolor(0, 255, 0) - cmov2i(10, 10) - charstr('Waiting...') - -def reshape(): - reshapeviewport() - w, h = getsize() - ortho2(0, w, 0, h) - testimage() - return w, h - -def main(): - s = socket(AF_INET, SOCK_DGRAM) - s.bind('', PORT) - - foreground() - wid = winopen('tv') - RGBmode() - gconfig() - qdevice(ESCKEY) - - oldw, oldh = getsize() - ortho2(0, oldw, 0, oldh) - testimage() - - t1 = millitimer() - - while 1: - if qtest(): - dev, val = qread() - if dev == ESCKEY: - winclose(wid) - return - elif dev == REDRAW: - oldw, oldh = reshape() - elif s.avail(): - data = s.recv(17000) - header = string.strip(data[:HS]) - w, h, pf, x1, y1, x2, y2 = eval(header) - if (w, h) <> (oldw, oldh): - x, y = getorigin() - x, y = x-1, y+21 # TWM correction - winposition(x, x+w-1, y+oldh-h, y+oldh-1) - oldw, oldh = reshape() - data2 = data[HS:] - dx = (x2-x1+1)/pf - dy = (y2-y1+1)/pf - data3 = unpackrect(dx, dy, 1, data2) - rectzoom(pf, pf) - lrectwrite(x1, y1, x1+dx-1, y1+dy-1, data3) - t1 = millitimer() - else: - t2 = millitimer() - if t2-t1 >= 5000: - testimage() - t1 = t2 - else: - millisleep(10) - - winclose(wid) - return data - -main() diff --git a/Demo/sgi/video/v2i.c b/Demo/sgi/video/v2i.c deleted file mode 100755 index 5f8f3b5dec..0000000000 --- a/Demo/sgi/video/v2i.c +++ /dev/null @@ -1,79 +0,0 @@ -/* Convert the first image of a CMIF video movie file to SGI .rgb format. - usage: v2i videofile imagefile [planemask] - link with -limage -*/ - -#include -#include - -long bm[1280]; -short rb[1280], gb[1280], bb[1280]; -long w, h, pf; - -#define R(comp) ((comp) & 0xff) -#define G(comp) (((comp)>>8) & 0xff) -#define B(comp) (((comp)>>16) & 0xff) - -main(argc, argv) - char **argv; -{ - char lbuf[100]; - int x, y; - int i; - IMAGE * of; - int pmask; - - if( argc != 3 && argc != 4) { - fprintf(stderr, "Usage: v2i videofile imgfile [planemask]\n"); - exit(2); - } - if ( argc == 4) - pmask = atoi(argv[3]); - else - pmask = 7; - if ( freopen(argv[1], "r", stdin) == NULL ) { - perror(argv[1]); - exit(1); - } - if (fgets(lbuf, sizeof lbuf, stdin) == NULL) { - fprintf(stderr, "Immediate EOF\n"); - exit(1); - } - if (strncmp(lbuf, "CMIF", 4) == 0) { - /* Skip optional header line */ - if (fgets(lbuf, sizeof lbuf, stdin) == NULL) { - fprintf(stderr, "Immediate EOF after header\n"); - exit(1); - } - } - pf = 2; /* Default */ - if ( sscanf(lbuf, "(%d,%d,%d)", &w, &h, &pf) < 2) { - fprintf(stderr, "%s: bad size spec: %s\n", argv[0], lbuf); - exit(1); - } - fgets(lbuf, sizeof lbuf, stdin); /* Skip time info */ - if ( w > 1280 ) { - fprintf(stderr, "%s: Sorry, too wide\n", argv[0]); - exit(1); - } - if ( (of=iopen(argv[2], "w", RLE(1), 3, w, h, 3)) == 0) { - perror(argv[2]); - exit(1); - } - for( y=0; y 2: - usage() - [ifile, ofile] = args - print 'open film ', ifile - ifilm = VFile.VinFile().init(ifile) - print 'open output ', ofile - ofilm = VFile.VoutFile().init(ofile) - - ofilm.setinfo(ifilm.getinfo()) - - use_grabber = 0 - continuous = 0 - tomono = 0 - tomonodither = 0 - for o, a in opts: - if o == '-t': - ofilm.format = a - use_grabber = 1 - if o == '-a': - continuous = 1 - if o == '-m': - if ifilm.format <> 'grey': - print '-m only supported for greyscale' - sys.exit(1) - tomono = 1 - treshold = string.atoi(a) - ofilm.format = 'mono' - if o == '-d': - if ifilm.format <> 'grey': - print '-m only supported for greyscale' - sys.exit(1) - tomonodither = 1 - ofilm.format = 'mono' - - ofilm.writeheader() - # - prefsize(ifilm.width, ifilm.height) - w = winopen(ifile) - qdevice(KEYBD) - qdevice(ESCKEY) - qdevice(WINQUIT) - qdevice(WINSHUT) - print 'qdevice calls done' - # - help() - # - time, data, cdata = ifilm.getnextframe() - ifilm.showframe(data, cdata) - iframe = 1 - report(time, iframe) - # - while 1: - if continuous: - dev = KEYBD - else: - dev, val = qread() - if dev in (ESCKEY, WINQUIT, WINSHUT): - break - if dev == REDRAW: - reshapeviewport() - elif dev == KEYBD: - if continuous: - c = '0' - else: - c = chr(val) - #XXX Debug - if c == 'R': - c3i(255,0,0) - clear() - if c == 'G': - c3i(0,255,0) - clear() - if c == 'B': - c3i(0,0,255) - clear() - if c == 'w' or continuous: - if use_grabber: - data, cdata = ofilm.grabframe() - if tomono: - data = imageop.grey2mono(data, \ - ifilm.width, ifilm.height, \ - treshold) - if tomonodither: - data = imageop.dither2mono(data, \ - ifilm.width, ifilm.height) - ofilm.writeframe(time, data, cdata) - print 'Frame', iframe, 'written.' - if c == 'n' or continuous: - try: - time,data,cdata = ifilm.getnextframe() - ifilm.showframe(data, cdata) - iframe = iframe+1 - report(time, iframe) - except EOFError: - print 'EOF' - if continuous: - break - ringbell() - elif dev == INPUTCHANGE: - pass - else: - print '(dev, val) =', (dev, val) - ofilm.close() - -main() diff --git a/Demo/sgi/video/video.doc b/Demo/sgi/video/video.doc deleted file mode 100755 index 982c008f7e..0000000000 --- a/Demo/sgi/video/video.doc +++ /dev/null @@ -1,109 +0,0 @@ - CMIF video tools - -This document gives a quick introduction to some of the tools useful -for recording, editing and playing back video data in CMIF video -format. All the tools mentioned currently live in /ufs/guido/bin/sgi. -A description of the CMIF video file format can be found in -/ufs/jack/cmif-film.ms. - - Recording video - -There are two tools to record video, Vrec and and Vrecb. Vrec does -continuous capture, but can capture at most 15 frames per second. -Vrecb uses burst capture, enabling it to capture all frames. It -captures to main memory, however, so it cannot handle long video -fragments. The following options are common to both programs: - - -r rate Capture one out of 'rate' frames. Default (and - minimum) is 1 for Vrecb, 2 for Vrec. There are some - caveats for recording PAL, see below. - -w width Set initial window width (and height, implicitly). - -g bits Create greyscale film in stead of 8-bit dithered color - film. Allowable values for 'bits' are 2, 4 or 8. - -m Create monochrome dithered film. These look horrible. - -M threshold Create monochrome thresholded film with specified - threshold (in range 0..255). - -G Create 2-bit dithered greyscale film. - -f Capture fields in stead of frames. The film is created - in such a way that the picture will be suitably - enlarged on playback, so aspect ratio, etc. are - maintained. - -d Drop fields if they would cause data from two video - fields to be combined. See the section on PAL for more - details. - -Options for Vrec: - -a Record audio as well. You will have to twiddle audio - and video later if you want lipsync playback. - -q queuesize Set size of the video board circular buffer. A little - experimentation with this may lead to more video being - captured, but not always. - -P frames Preallocate diskspace for 'frames' images. This may - enable you to capture more frames. - -Options for Vrecb: - -n number Capture 'number' frames. Default is 60 (2 seconds). - -Both programs accept a filename to store the video on (default -film.video) and Vrec also accepts an audio file name (default -film.aiff). When you want to record you press the left mouse button. -Vrec stops recording when you release the mouse button and Vrecb stops -after the predetermined number of frames have been recorded. During -recording the picture may look funny, but do not let this worry you, -the film will be ok. - -After recording and saving, Vrec will print the deltas of the field -numbers recorded. A list of '4 4 4 4'... means that all possible -frames (one out of two) have been recorded. Vrecb will tell you how -many duplicate fields have been skipped. See below on PAL useage -again. - - PAL caveats - -The IndigoVideo board converts the incoming video signal to the 60Hz -(59.something, actually) display rate. All further operations, -including capture, are done with respect to display rate. This is -especially bothersome in the case of PAL video, since it means one out -of 5 frames will be duplicated. Together with the fact that, in -continuous capture, you can only capture every second frame this leads -to strange and wondrous effects. The frame numbers returned by the -video board (and displayed by Vrec) are display frame numbers, and so -bear only a very complicated (and probably non-deterministic) relation -to PAL frame numbers. For recording simple videos this is probably no -problem. You can use Vrec and try using -d to see which gives the best -result. On the other hand, if you need every frame and no duplicates -either you have to use Vrecb and supply the -d and -f option. This -will give you exactly the fields as they appeared on the PAL tape. - - Video playback - -The easiest way to play back a video is to use Vplay. Calling it with -an argument of -? will make it list all its options. A few options may -need a bit of explanation: - -M magnify Magnify the images by the given factor. This still - takes any magnification specified in the film (if it - is a field film, for instance) in account. - -w width and - -h height Normally the window will be the correct size for the - film. You can set height and width, though, if you - want the window to be bigger. This is especially - useful if you want to record the film back to - videotape, since you can playback in a window that is - bigger than PAL size with a black background and you - will have no distracting window-manager thingies on - your videotape. - - Video Editing - -Vedit is a (very simple) video editor that allows you to select images -from the input movie and copy them to an output movie. Both input and -output films have a modest buffer that you can move around in. - -Vaddcache takes a movie and adds a frame location cache to it. This -will make some other programs run faster. - -rgb2video converts a set of SGI .rgb files to a movie. - -There are a few programs that can do image format conversion on movies -(i.e. convert an 8-bit dithered RGB movie to a greyscale movie), but -nothing very complete yet. Look at Vcopy.py for more information. diff --git a/Demo/sgi/video/video.py b/Demo/sgi/video/video.py deleted file mode 100755 index 1b81bd83f7..0000000000 --- a/Demo/sgi/video/video.py +++ /dev/null @@ -1,218 +0,0 @@ -import getopt -from gl import * -from GL import * -from DEVICE import * -import time -import sys -import al -import AL - -sys.path.append('/ufs/guido/src/video') # Increase chance to find colorsys -import colorsys - -BUFFERSIZE = 32000 - -class Struct(): pass -epoch = Struct() -epoch.correcttiming = 1 -EndOfFile = 'End of file' -bye = 'bye' - -def openspkr(): - conf = al.newconfig() - conf.setqueuesize(BUFFERSIZE) - conf.setwidth(AL.SAMPLE_16) - conf.setchannels(AL.MONO) - return al.openport('spkr','w',conf) - -def openvideo(name): - try: - f = open(name, 'r') - except: - sys.stderr.write(name + ': cannot open\n') - sys.exit(1) - line = f.readline() - if not line: raise EndOfFile - colorinfo = (8, 0, 0, 0) - if line[:4] == 'CMIF': - if line[:14] == 'CMIF video 2.0': - line = f.readline() - colorinfo = eval(line[:-1]) - line = f.readline() - x = eval(line[:-1]) - if len(x) == 3: w, h, pf = x - else: w, h = x; pf = 2 - if pf and w/pf % 4 <> 0: - sys.stderr.write( \ - 'warning: stride not a multiple of 4 -- may not work on Indigo XS\n') - return f, w, h, pf, colorinfo - -def loadframe(f,w,h,pf,af,spkr, (ybits,ibits,qbits,chrompack),mf): - line = f.readline() - if line == '': - raise EndOfFile - x = eval(line[:-1]) - if type(x) == type(0) or type(x) == type(0.0): - tijd = x - if pf == 0: - size = w*h*4 - else: - size = (w/pf) * (h/pf) - else: - tijd, size = x - data = f.read(size) - if len(data) <> size: - raise EndOfFile - if pf: - w = w/pf - h = h/pf - if chrompack: - cw = (w+chrompack-1)/chrompack - ch = (h+chrompack-1)/chrompack - chromdata = f.read(2*cw*ch) - rectzoom(pf*chrompack*mf,pf*chrompack*mf) - pixmode(PM_SIZE,16) - writemask(0x7ff - ((1< 1: - rectzoom(mf,mf) - lrectwrite(0,0,w-1,h-1,data) - # This is ugly here, but the only way to get the two - # channels started in sync - #if af <> None: - # playsound(af,spkr) - ct = time.millitimer() - epoch.epoch - if epoch.correcttiming and tijd > 0 and ct < tijd: - time.millisleep(tijd-ct) - #swapbuffers() - return tijd - -def initcmap(ybits,ibits,qbits,chrompack): - if ybits+ibits+qbits > 11: - raise 'Sorry, 11 bits max' - maxy = pow(2,ybits) - maxi = pow(2,ibits) - maxq = pow(2,qbits) - for i in range(2048,4096-256): - mapcolor(i, 0, 255, 0) - for y in range(maxy): - yv = float(y)/float(maxy-1) - for i in range(maxi): - if maxi == 1: iv = 0 - else: iv = (float(i)/float(maxi-1))-0.5 - for q in range(maxq): - if maxq == 1: qv = 0 - else: qv = (float(q)/float(maxq-1))-0.5 - index = 2048 + y + (i << ybits) + (q << (ybits+ibits)) - rv,gv,bv = colorsys.yiq_to_rgb(yv,iv,qv) - r,g,b = int(rv*255.0), int(gv*255.0), int(bv*255.0) - if index < 4096 - 256: - mapcolor(index, r,g,b) - -def playsound(af, spkr): - nsamp = spkr.getfillable() - data = af.read(nsamp*2) - spkr.writesamps(data) - -def main(): - looping = 0 - packfactor = 0 - magfactor = 1 - try: - opts, args = getopt.getopt(sys.argv[1:], 'm:p:lF') - except getopt.error: - sys.stderr.write('usage: video ' + \ - '[-l] [-p pf] [-m mag] [-F] [moviefile [soundfile [skipbytes]]]\n') - sys.exit(2) - for opt, arg in opts: - if opt == '-m': - magfactor = int(eval(arg)) - elif opt == '-p': - packfactor = int(eval(arg)) - elif opt == '-l': - looping = 1 - elif opt == '-F': - epoch.correcttiming = 0 - if args: - filename = args[0] - else: - filename = 'film.video' - f, w, h, pf, cinfo = openvideo(filename) - if 0 < packfactor <> pf: - w = w/pf*packfactor - h = h/pf*packfactor - pf = packfactor - if args[1:]: - audiofilename = args[1] - af = open(audiofilename, 'r') - spkr = openspkr() - afskip = 0 - if args[2:]: - afskip = eval(args[2]) - af.seek(afskip) - else: - af, spkr = None, None - foreground() - prefsize(w*magfactor,h*magfactor) - win = winopen(filename) - if pf: - #doublebuffer() - cmode() - else: - RGBmode() - #doublebuffer() - gconfig() - if pf: - initcmap(cinfo) - color(2048) - clear() - writemask(2047) - pixmode(PM_SIZE,8) # 8 bit pixels - qdevice(ESCKEY) - qdevice(WINSHUT) - qdevice(WINQUIT) - running = 1 - epoch.epoch = time.millitimer() - nframe = 0 - tijd = 1 - if looping: - looping = f.tell() - try: - while 1: - if running: - try: - tijd = loadframe(f, w, h, pf, af, spkr, cinfo,magfactor) - nframe = nframe + 1 - except EndOfFile: - running = 0 - t = time.millitimer() - if tijd > 0: - print 'Recorded at', - print 0.1 * int(nframe * 10000.0 / tijd), - print 'frames/sec' - print 'Played', nframe, 'frames at', - print 0.1 * int(nframe * 10000.0 / (t-epoch.epoch)), - print 'frames/sec' - if looping: - f.seek(looping) - epoch.epoch = time.millitimer() - nframe = 0 - running = 1 - if af <> None: - af.seek(afskip) - if af <> None: - playsound(af,spkr) - if not running or qtest(): - dev, val = qread() - if dev in (ESCKEY, WINSHUT, WINQUIT): - raise bye - elif dev == REDRAW: - reshapeviewport() - except bye: - pass - -main() diff --git a/Demo/sgi/video/video2rgb.py b/Demo/sgi/video/video2rgb.py deleted file mode 100755 index 7070a93342..0000000000 --- a/Demo/sgi/video/video2rgb.py +++ /dev/null @@ -1,159 +0,0 @@ -#! /ufs/guido/bin/sgi/python - -# Convert CMIF movie file(s) to a sequence of rgb images - - -# Help function - -def help(): - print 'Usage: video2rgb [options] [file] ...' - print - print 'Options:' - print '-q : quiet, no informative messages' - print '-m : create monochrome (greyscale) image files' - print '-f prefix : create image files with names "prefix0000.rgb"' - print 'file ... : file(s) to convert; default film.video' - - -# Imported modules - -import sys -sys.path.append('/ufs/jack/src/av/video') # Increase chance of finding VFile -import VFile -import time -import getopt -import string -import imgfile -import imgconv - - -# Global options - -quiet = 0 -prefix = 'film' -seqno = 0 -mono = 0 - - -# Main program -- mostly command line parsing - -def main(): - global quiet, prefix, mono - - # Parse command line - try: - opts, args = getopt.getopt(sys.argv[1:], 'qmf:') - except getopt.error, msg: - sys.stdout = sys.stderr - print 'Error:', msg, '\n' - help() - sys.exit(2) - - # Interpret options - try: - for opt, arg in opts: - if opt == '-q': quiet = 1 - if opt == '-f': prefix = arg - if opt == '-m': mono = 1 - except string.atoi_error: - sys.stdout = sys.stderr - print 'Option', opt, 'requires integer argument' - sys.exit(2) - - # Process all files - if not args: args = ['film.video'] - sts = 0 - for filename in args: - sts = (process(filename) or sts) - - # Exit with proper exit status - sys.exit(sts) - - -# Process one movie file - -def process(filename): - try: - vin = VFile.VinFile(filename) - except IOError, msg: - sys.stderr.write(filename + ': I/O error: ' + `msg` + '\n') - return 1 - except VFile.Error, msg: - sys.stderr.write(msg + '\n') - return 1 - except EOFError: - sys.stderr.write(filename + ': EOF in video header\n') - return 1 - - if not quiet: - vin.printinfo() - - width, height = int(vin.width), int(vin.height) - - try: - if mono: - cf = imgconv.getconverter(vin.format, 'grey') - else: - cf = imgconv.getconverter(vin.format, 'rgb') - except imgconv.error: - print 'Sorry, no converter available for type',vin.format - return - - if mono: - depth = 1 - bpp = 1 - else: - depth = 3 - bpp = 4 - - convert(vin, cf, width, height, depth, bpp, vin.packfactor) - -def convert(vin, cf, width, height, depth, bpp, pf): - global seqno - - if type(pf) == type(()): - xpf, ypf = pf - elif pf == 0: - xpf = ypf = 1 - else: - xpf = ypf = pf - while 1: - try: - time, data, cdata = vin.getnextframe() - except EOFError: - return - if cdata: - print 'Film contains chromdata!' - return - data = cf(data, width/xpf, height/abs(ypf)) - if pf: - data = applypackfactor(data, width, height, pf, bpp) - s = `seqno` - s = '0'*(4-len(s)) + s - fname = prefix + s + '.rgb' - seqno = seqno + 1 - if not quiet: - print 'Writing',fname,'...' - imgfile.write(fname, data, width, height, depth) - -def applypackfactor(image, w, h, pf, bpp): - import imageop - if type(pf) == type(()): - xpf, ypf = pf - elif pf == 0: - xpf = ypf = 1 - else: - xpf = ypf = pf - w1 = w/xpf - h1 = h/abs(ypf) - if ypf < 0: - ypf = -ypf - image = imageop.crop(image, bpp, w1, h1, 0, h1-1, w1-1, 0) - return imageop.scale(image, bpp, w1, h1, w, h) - -# Don't forget to call the main program - -try: - main() -except KeyboardInterrupt: - print '[Interrupt]' diff --git a/Demo/sgi/video/vinfo.py b/Demo/sgi/video/vinfo.py deleted file mode 100755 index 7f98237a97..0000000000 --- a/Demo/sgi/video/vinfo.py +++ /dev/null @@ -1,90 +0,0 @@ -from gl import * -from GL import * -from DEVICE import * -import time -import sys -import getopt - -class Struct(): pass -epoch = Struct() -EndOfFile = 'End of file' -bye = 'bye' - -def openvideo(filename): - f = open(filename, 'r') - line = f.readline() - if not line: raise EndOfFile - if line[:4] == 'CMIF': line = f.readline() - x = eval(line[:-1]) - if len(x) == 3: w, h, pf = x - else: w, h = x; pf = 2 - return f, w, h, pf - -def loadframe(f, w, h, pf): - line = f.readline() - if line == '': - raise EndOfFile - x = eval(line[:-1]) - if type(x) == type(0) or type(x) == type(0.0): - tijd = x - if pf == 0: - size = w*h*4 - else: - size = (w/pf) * (h/pf) - else: - tijd, size = x - f.seek(size, 1) - return tijd - -def main(): - delta = 0 - short = 0 - try: - opts, names = getopt.getopt(sys.argv[1:], 'ds') - except getopt.error, msg: - sys.stderr.write(msg + '\n') - sys.stderr.write('usage: vinfo [-d] [-s] [file] ...\n') - sys.exit(2) - for opt, arg in opts: - if opt == '-d': delta = 1 # print delta between frames - elif opt == '-s': short = 1 # short: don't print times - if names == []: - names = ['film.video'] - for name in names: - try: - f, w, h, pf = openvideo(name) - except: - sys.stderr.write(name + ': cannot open\n') - continue - if pf == 0: - size = w*h*4 - else: - size = (w/pf) * (h/pf) - print name, ':', w, 'x', h, '; pf =', pf, ', size =', size, - if pf == 0: - print '(color)', - else: - print '(' + `(w/pf)` + 'x' + `(h/pf)` + ')', - if (w/pf)%4 <> 0: print '!!!', - print - num = 0 - try: - otijd = 0 - while not short: - try: - tijd = loadframe(f, w, h, pf) - if delta: print '\t' + `tijd-otijd`, - else: print '\t' + `tijd`, - otijd = tijd - num = num + 1 - if num % 8 == 0: - print - except EndOfFile: - raise bye - except bye: - pass - if num % 8 <> 0: - print - f.close() - -main() diff --git a/Demo/sgi/video/vpregs.py b/Demo/sgi/video/vpregs.py deleted file mode 100755 index d33f1fe93e..0000000000 --- a/Demo/sgi/video/vpregs.py +++ /dev/null @@ -1,28 +0,0 @@ -VID_VP = 0x1000000 - -# Set vp1 register tokens -VP_GBXORG = (VID_VP +0x01) -VP_GBYORG = (VID_VP +0x02) -VP_FBXORG = (VID_VP +0x03) -VP_FBYORG = (VID_VP +0x04) -VP_WIDTH = (VID_VP +0x05) -VP_HEIGHT = (VID_VP +0x06) -VP_PIXCNT = (VID_VP +0x07) -VP_HBLANK = (VID_VP +0x08) -VP_VBLANK = (VID_VP +0x09) -VP_BRITE = (VID_VP +0x0A) -VP_CONT = (VID_VP +0x0B) -VP_HUE = (VID_VP +0x0C) -VP_SAT = (VID_VP +0x0D) -VP_ALPHA = (VID_VP +0X0E) -VP_FGMODE = (VID_VP +0x0F) -VP_MAPSRC = (VID_VP +0x10) -VP_MAPADD = (VID_VP +0x11) -VP_MAPRED = (VID_VP +0x12) -VP_MAPGREEN = (VID_VP +0x13) -VP_MAPBLUE = (VID_VP +0x14) -VP_MAPSTROBE = (VID_VP +0x15) -VP_DIGVAL = (VID_VP +0x16) -VP_STATUS0 = (VID_VP +0x17) -VP_STATUS1 = (VID_VP +0x18) -VP_CMD = (VID_VP +0x19) diff --git a/Demo/sgi/video/vtime.py b/Demo/sgi/video/vtime.py deleted file mode 100755 index c333e57983..0000000000 --- a/Demo/sgi/video/vtime.py +++ /dev/null @@ -1,106 +0,0 @@ -# -# Module vtime - Keep virtual time between two nodes. -# -# We try for synchronised clocks by sending a packet of the for -# (1,mytime,0) to the other side, and waiting (at most) a second for -# a reply. This reply has the form (2,mytime,histime), and we can -# estimate the time difference by defining histime to be exactly half-way -# between the time we sent our message and got our reply. We send a -# final (3,mynewtime,histime) message to allow the other side to do the -# same computations. -# -# Note that the protocol suffers heavily from the 2-army problem. -# It'll have to do until I can read up on time-sync protocols, though. -# -from socket import * -import time - -MSGSIZE = 100 -MSGTIMEOUT = 1000 - -recv_timeout = 'receive timeout' -bad_connect = 'Bad connection' - -def timeavg(a,b): - return int((long(a)+b)/2L) -def tryrecv(s): - cnt = 0 - while 1: - if s.avail(): - return s.recvfrom(MSGSIZE) - time.millisleep(100) - cnt = cnt + 100 - if cnt > MSGTIMEOUT: - raise recv_timeout - -class VTime(): - def init(self,(client,host,port)): - s = socket(AF_INET, SOCK_DGRAM) - host = gethostbyname(host) - localhost = gethostbyname(gethostname()) - raddr = (host,port) - s.bind((localhost,port)) - if client: - # - # We loop here because we want the *second* measurement - # for accuracy - for loopct in (0,2): - curtijd = time.millitimer() - check = `(loopct,curtijd,0)` - s.sendto(check,raddr) - while 1: - try: - if loopct: - data, other = s.recvfrom(MSGSIZE) - else: - data, other = tryrecv(s) - newtijd = time.millitimer() - if other <> raddr: - print 'Someone else syncing to us: ', other - raise bad_connect - data = eval(data) - if data[:2] == (loopct+1,curtijd): - break - if data[0] <> 2: - print 'Illegal sync reply: ', data - raise bad_connect - except recv_timeout: - curtijd = time.millitimer() - check = `(loopct,curtijd,0)` - s.sendto(check,raddr) - histime = data[2] - s.sendto(`(4,newtijd,histime)`,raddr) - mytime = timeavg(curtijd,newtijd) - #mytime = curtijd - self.timediff = histime - mytime - else: - while 1: - data,other = s.recvfrom(MSGSIZE) - if other <> raddr: - print 'Someone else syncing to us: ', other, ' Wanted ', raddr - raise bad_connect - data = eval(data) - if data[0] in (0,2): - curtijd = time.millitimer() - s.sendto(`(data[0]+1,data[1],curtijd)`,raddr) - elif data[0] == 4: - newtijd = time.millitimer() - histime = data[1] - mytime = timeavg(curtijd,newtijd) - #mytime = curtijd - self.timediff = histime-mytime - break - else: - print 'Funny data: ', data - raise bad_connect - return self - # - def his2mine(self,tijd): - return tijd - self.timediff - # - def mine2his(self, tijd): - return tijd + self.timediff - -def test(clt, host, port): - xx = VTime().init(clt,host,port) - print 'Time diff: ', xx.his2mine(0) diff --git a/Demo/sgi/video/watchcursor.py b/Demo/sgi/video/watchcursor.py deleted file mode 100755 index aae3f85d50..0000000000 --- a/Demo/sgi/video/watchcursor.py +++ /dev/null @@ -1,45 +0,0 @@ -# Define a 16x16 cursor looking like a watch - -# X11 bitmap file: -##define x_width 16 -##define x_height 16 -#static char x_bits[] = { -# 0xf0, 0x0f, 0xf8, 0x1f, 0x1c, 0x38, 0x8e, 0x71, 0x87, 0xe1, 0x83, 0xc1, -# 0x83, 0xc1, 0xf3, 0xc1, 0xf3, 0xc1, 0x03, 0xc0, 0x03, 0xc0, 0x07, 0xe0, -# 0x0e, 0x70, 0x1c, 0x38, 0xf8, 0x1f, 0xf0, 0x0f}; - - -watch = [ \ - 0x0ff0,\ - 0x1ff8,\ - 0x381c,\ - 0x718e,\ - 0xe187,\ - 0xc183,\ - 0xc183,\ - 0xc1f3,\ - 0xc1f3,\ - 0xc003,\ - 0xc003,\ - 0xe007,\ - 0x700e,\ - 0x381c,\ - 0x1ff8,\ - 0x0ff0,\ - ] - -watch.reverse() # Turn it upside-down - -def defwatch(index): - import gl - gl.defcursor(index, watch*8) - gl.curorigin(index, 8, 8) - -def test(): - import gl - gl.foreground() - gl.winopen('test watchcursor') - defwatch(1) - gl.setcursor(1, 0, 0) - import time - time.sleep(10) diff --git a/Demo/sockets/ChangeLog b/Demo/sockets/ChangeLog deleted file mode 100755 index c1d41b1f67..0000000000 --- a/Demo/sockets/ChangeLog +++ /dev/null @@ -1,35 +0,0 @@ -Mon Nov 16 17:55:30 1992 Guido van Rossum (guido@voorn.cwi.nl) - -* Restructured mcast. - -Tue Nov 3 13:08:41 1992 Guido van Rossum (guido@voorn.cwi.nl) - -* Fixed ftp.py to use 'global' instead of a hack - -25-Oct-1992 - -* Added gopher.py - -2-Oct-1992 - -* Changed /usr/local/python to /usr/local/bin/python - -Thu Sep 24 12:33:56 1992 Guido van Rossum (guido@voorn.cwi.nl) - -* Improved computation of mcast group bytes (use regsub.gsub()) - -Tue Sep 8 23:20:51 1992 Guido van Rossum (guido@voorn.cwi.nl) - -* Added mcast.py and IN.py. - -* Use setsockopt() instead of allowbroadcast() in broadcast.py. - -Mon Aug 10 12:45:43 1992 Guido van Rossum (guido@voorn.cwi.nl) - -* README: added broadcast.py, ftp.py, radio.py - -------------------------------------------------------------------------------- -^^^ Log entries after release of 0.9.6 ^^^ -------------------------------------------------------------------------------- - - diff --git a/Demo/sockets/README b/Demo/sockets/README deleted file mode 100644 index e844ac6be7..0000000000 --- a/Demo/sockets/README +++ /dev/null @@ -1,20 +0,0 @@ -This directory contains some demonstrations of the socket module: - -broadcast.py Broadcast the time to radio.py. -echosvr.py About the simplest TCP server possible. -finger.py Client for the 'finger' protocol. -ftp.py A very simple ftp client. -gopher.py A simple gopher client. -telnet.py Client for the 'telnet' protocol. -throughput.py Client and server to measure TCP throughput. -udpecho.py Client and server for the UDP echo protocol. -radio.py Receive time broadcasts from broadcast.py. - -The following file is only relevant on SGI machines (or other systems -that support multicast): - -mcast.py A Python translation of - /usr/people/4Dgifts/examples/network/mcast.c - (Note that IN.py is in ../../lib/sgi.) - -See also ../../lib/nntp.py for another example of socket code. diff --git a/Demo/sockets/broadcast.py b/Demo/sockets/broadcast.py deleted file mode 100755 index e7e6b9b1d1..0000000000 --- a/Demo/sockets/broadcast.py +++ /dev/null @@ -1,18 +0,0 @@ -# Send UDP broadcast packets - -MYPORT = 50000 - -import sys, time -from socket import * -from SOCKET import * - -s = socket(AF_INET, SOCK_DGRAM) -s.bind('', 0) -s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1) - -while 1: - data = `time.time()` + '\n' - s.sendto(data, ('', MYPORT)) - time.sleep(2) - - diff --git a/Demo/sockets/echosvr.py b/Demo/sockets/echosvr.py deleted file mode 100755 index d4a23f04a8..0000000000 --- a/Demo/sockets/echosvr.py +++ /dev/null @@ -1,31 +0,0 @@ -#! /usr/local/bin/python - -# Python implementation of an 'echo' tcp server: echo all data it receives. -# -# This is the simplest possible server, sevicing a single request only. - -import sys -from socket import * - -# The standard echo port isn't very useful, it requires root permissions! -# ECHO_PORT = 7 -ECHO_PORT = 50000 + 7 -BUFSIZE = 1024 - -def main(): - if len(sys.argv) > 1: - port = int(eval(sys.argv[1])) - else: - port = ECHO_PORT - s = socket(AF_INET, SOCK_STREAM) - s.bind('', port) - s.listen(0) - conn, (remotehost, remoteport) = s.accept() - print 'connected by', remotehost, remoteport - while 1: - data = conn.recv(BUFSIZE) - if not data: - break - conn.send(data) - -main() diff --git a/Demo/sockets/finger.py b/Demo/sockets/finger.py deleted file mode 100755 index 71e307ffa6..0000000000 --- a/Demo/sockets/finger.py +++ /dev/null @@ -1,58 +0,0 @@ -#! /usr/local/bin/python - -# Python interface to the Internet finger daemon. -# -# Usage: finger [options] [user][@host] ... -# -# If no host is given, the finger daemon on the local host is contacted. -# Options are passed uninterpreted to the finger daemon! - - -import sys, string -from socket import * - - -# Hardcode the number of the finger port here. -# It's not likely to change soon... -# -FINGER_PORT = 79 - - -# Function to do one remote finger invocation. -# Output goes directly to stdout (although this can be changed). -# -def finger(host, args): - s = socket(AF_INET, SOCK_STREAM) - s.connect(host, FINGER_PORT) - s.send(args + '\n') - while 1: - buf = s.recv(1024) - if not buf: break - sys.stdout.write(buf) - sys.stdout.flush() - - -# Main function: argument parsing. -# -def main(): - options = '' - i = 1 - while i < len(sys.argv) and sys.argv[i][:1] == '-': - options = options + sys.argv[i] + ' ' - i = i+1 - args = sys.argv[i:] - if not args: - args = [''] - for arg in args: - if '@' in arg: - at = string.index(arg, '@') - host = arg[at+1:] - arg = arg[:at] - else: - host = '' - finger(host, options + arg) - - -# Call the main function. -# -main() diff --git a/Demo/sockets/ftp.py b/Demo/sockets/ftp.py deleted file mode 100755 index f5bbdf504a..0000000000 --- a/Demo/sockets/ftp.py +++ /dev/null @@ -1,144 +0,0 @@ -# A simple FTP client. -# -# The information to write this program was gathered from RFC 959, -# but this is not a complete implementation! Yet it shows how a simple -# FTP client can be built, and you are welcome to extend it to suit -# it to your needs... -# -# How it works (assuming you've read the RFC): -# -# User commands are passed uninterpreted to the server. However, the -# user never needs to send a PORT command. Rather, the client opens a -# port right away and sends the appropriate PORT command to the server. -# When a response code 150 is received, this port is used to receive -# the data (which is written to stdout in this version), and when the -# data is exhausted, a new port is opened and a corresponding PORT -# command sent. In order to avoid errors when reusing ports quickly -# (and because there is no s.getsockname() method in Python yet) we -# cycle through a number of ports in the 50000 range. - - -import sys, posix, string -from socket import * - - -BUFSIZE = 1024 - -# Default port numbers used by the FTP protocol. -# -FTP_PORT = 21 -FTP_DATA_PORT = FTP_PORT - 1 - -# Change the data port to something not needing root permissions. -# -FTP_DATA_PORT = FTP_DATA_PORT + 50000 - - -# Main program (called at the end of this file). -# -def main(): - hostname = sys.argv[1] - control(hostname) - - -# Control process (user interface and user protocol interpreter). -# -def control(hostname): - # - # Create control connection - # - s = socket(AF_INET, SOCK_STREAM) - s.connect(hostname, FTP_PORT) - f = s.makefile('r') # Reading the replies is easier from a file... - # - # Control loop - # - r = None - while 1: - code = getreply(f) - if code in ('221', 'EOF'): break - if code == '150': - getdata(r) - code = getreply(f) - r = None - if not r: - r = newdataport(s, f) - cmd = getcommand() - if not cmd: break - s.send(cmd + '\r\n') - - -# Create a new data port and send a PORT command to the server for it. -# (Cycle through a number of ports to avoid problems with reusing -# a port within a short time.) -# -nextport = 0 -# -def newdataport(s, f): - global nextport - port = nextport + FTP_DATA_PORT - nextport = (nextport+1) % 16 - r = socket(AF_INET, SOCK_STREAM) - r.bind(gethostbyname(gethostname()), port) - r.listen(0) - sendportcmd(s, f, port) - return r - - -# Send an appropriate port command. -# -def sendportcmd(s, f, port): - hostname = gethostname() - hostaddr = gethostbyname(hostname) - hbytes = string.splitfields(hostaddr, '.') - pbytes = [`port/256`, `port%256`] - bytes = hbytes + pbytes - cmd = 'PORT ' + string.joinfields(bytes, ',') - s.send(cmd + '\r\n') - code = getreply(f) - - -# Process an ftp reply and return the 3-digit reply code (as a string). -# The reply should be a line of text starting with a 3-digit number. -# If the 4th char is '-', it is a multi-line reply and is -# terminate by a line starting with the same 3-digit number. -# Any text while receiving the reply is echoed to the file. -# -def getreply(f): - line = f.readline() - if not line: return 'EOF' - print line, - code = line[:3] - if line[3:4] == '-': - while 1: - line = f.readline() - if not line: break # Really an error - print line, - if line[:3] == code: break - return code - - -# Get the data from the data connection. -# -def getdata(r): - print '(accepting data connection)' - conn, host = r.accept() - print '(data connection accepted)' - while 1: - data = conn.recv(BUFSIZE) - if not data: break - sys.stdout.write(data) - print '(end of data connection)' - -# Get a command from the user. -# -def getcommand(): - try: - return raw_input('ftp.py> ') - except EOFError: - return '' - - -# Call the main program. -# -main() diff --git a/Demo/sockets/gopher.py b/Demo/sockets/gopher.py deleted file mode 100755 index f30ab0f1c8..0000000000 --- a/Demo/sockets/gopher.py +++ /dev/null @@ -1,347 +0,0 @@ -#! /usr/local/bin/python - -# A simple gopher client. -# -# Usage: gopher [ [selector] host [port] ] - -import string -import sys -import os -import socket - -# Default selector, host and port -DEF_SELECTOR = '' -DEF_HOST = 'gopher.micro.umn.edu' -DEF_PORT = 70 - -# Recognized file types -T_TEXTFILE = '0' -T_MENU = '1' -T_CSO = '2' -T_ERROR = '3' -T_BINHEX = '4' -T_DOS = '5' -T_UUENCODE = '6' -T_SEARCH = '7' -T_TELNET = '8' -T_BINARY = '9' -T_REDUNDANT = '+' -T_SOUND = 's' - -# Dictionary mapping types to strings -typename = {'0': '', '1': '', '2': '', '3': '', \ - '4': '', '5': '', '6': '', '7': '', \ - '8': '', '9': '', '+': '', 's': ''} - -# Oft-used characters and strings -CRLF = '\r\n' -TAB = '\t' - -# Open a TCP connection to a given host and port -def open_socket(host, port): - if not port: - port = DEF_PORT - elif type(port) == type(''): - port = string.atoi(port) - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect((host, port)) - return s - -# Send a selector to a given host and port, return a file with the reply -def send_request(selector, host, port): - s = open_socket(host, port) - s.send(selector + CRLF) - s.shutdown(1) - return s.makefile('r') - -# Get a menu in the form of a list of entries -def get_menu(selector, host, port): - f = send_request(selector, host, port) - list = [] - while 1: - line = f.readline() - if not line: - print '(Unexpected EOF from server)' - break - if line[-2:] == CRLF: - line = line[:-2] - elif line[-1:] in CRLF: - line = line[:-1] - if line == '.': - break - if not line: - print '(Empty line from server)' - continue - typechar = line[0] - parts = string.splitfields(line[1:], TAB) - if len(parts) < 4: - print '(Bad line from server:', `line`, ')' - continue - if len(parts) > 4: - print '(Extra info from server:', parts[4:], ')' - parts.insert(0, typechar) - list.append(parts) - f.close() - return list - -# Get a text file as a list of lines, with trailing CRLF stripped -def get_textfile(selector, host, port): - list = [] - get_alt_textfile(selector, host, port, list.append) - return list - -# Get a text file and pass each line to a function, with trailing CRLF stripped -def get_alt_textfile(selector, host, port, func): - f = send_request(selector, host, port) - while 1: - line = f.readline() - if not line: - print '(Unexpected EOF from server)' - break - if line[-2:] == CRLF: - line = line[:-2] - elif line[-1:] in CRLF: - line = line[:-1] - if line == '.': - break - if line[:2] == '..': - line = line[1:] - func(line) - f.close() - -# Get a binary file as one solid data block -def get_binary(selector, host, port): - f = send_request(selector, host, port) - data = f.read() - f.close() - return data - -# Get a binary file and pass each block to a function -def get_alt_binary(selector, host, port, func, blocksize): - f = send_request(selector, host, port) - while 1: - data = f.read(blocksize) - if not data: - break - func(data) - -# A *very* simple interactive browser - -# Browser main command, has default arguments -def browser(*args): - selector = DEF_SELECTOR - host = DEF_HOST - port = DEF_PORT - n = len(args) - if n > 0 and args[0]: - selector = args[0] - if n > 1 and args[1]: - host = args[1] - if n > 2 and args[2]: - port = args[2] - if n > 3: - raise RuntimeError, 'too many args' - try: - browse_menu(selector, host, port) - except socket.error, msg: - print 'Socket error:', msg - sys.exit(1) - except KeyboardInterrupt: - print '\n[Goodbye]' - -# Browse a menu -def browse_menu(selector, host, port): - list = get_menu(selector, host, port) - while 1: - print '----- MENU -----' - print 'Selector:', `selector` - print 'Host:', host, ' Port:', port - print - for i in range(len(list)): - item = list[i] - typechar, description = item[0], item[1] - print string.rjust(`i+1`, 3) + ':', description, - if typename.has_key(typechar): - print typename[typechar] - else: - print '' - print - while 1: - try: - str = raw_input('Choice [CR == up a level]: ') - except EOFError: - print - return - if not str: - return - try: - choice = string.atoi(str) - except string.atoi_error: - print 'Choice must be a number; try again:' - continue - if not 0 < choice <= len(list): - print 'Choice out of range; try again:' - continue - break - item = list[choice-1] - typechar = item[0] - [i_selector, i_host, i_port] = item[2:5] - if typebrowser.has_key(typechar): - browserfunc = typebrowser[typechar] - try: - browserfunc(i_selector, i_host, i_port) - except (IOError, socket.error): - print '***', sys.exc_type, ':', sys.exc_value - else: - print 'Unsupported object type' - -# Browse a text file -def browse_textfile(selector, host, port): - x = None - try: - p = os.popen('${PAGER-more}', 'w') - x = SaveLines(p) - get_alt_textfile(selector, host, port, x.writeln) - except IOError, msg: - print 'IOError:', msg - if x: - x.close() - f = open_savefile() - if not f: - return - x = SaveLines(f) - try: - get_alt_textfile(selector, host, port, x.writeln) - print 'Done.' - except IOError, msg: - print 'IOError:', msg - x.close() - -# Browse a search index -def browse_search(selector, host, port): - while 1: - print '----- SEARCH -----' - print 'Selector:', `selector` - print 'Host:', host, ' Port:', port - print - try: - query = raw_input('Query [CR == up a level]: ') - except EOFError: - print - break - query = string.strip(query) - if not query: - break - if '\t' in query: - print 'Sorry, queries cannot contain tabs' - continue - browse_menu(selector + TAB + query, host, port) - -# "Browse" telnet-based information, i.e. open a telnet session -def browse_telnet(selector, host, port): - if selector: - print 'Log in as', `selector` - if type(port) <> type(''): - port = `port` - sts = os.system('set -x; exec telnet ' + host + ' ' + port) - if sts: - print 'Exit status:', sts - -# "Browse" a binary file, i.e. save it to a file -def browse_binary(selector, host, port): - f = open_savefile() - if not f: - return - x = SaveWithProgress(f) - get_alt_binary(selector, host, port, x.write, 8*1024) - x.close() - -# "Browse" a sound file, i.e. play it or save it -def browse_sound(selector, host, port): - browse_binary(selector, host, port) - -# Dictionary mapping types to browser functions -typebrowser = {'0': browse_textfile, '1': browse_menu, \ - '4': browse_binary, '5': browse_binary, '6': browse_textfile, \ - '7': browse_search, \ - '8': browse_telnet, '9': browse_binary, 's': browse_sound} - -# Class used to save lines, appending a newline to each line -class SaveLines: - def __init__(self, f): - self.f = f - def writeln(self, line): - self.f.write(line + '\n') - def close(self): - sts = self.f.close() - if sts: - print 'Exit status:', sts - -# Class used to save data while showing progress -class SaveWithProgress: - def __init__(self, f): - self.f = f - def write(self, data): - sys.stdout.write('#') - sys.stdout.flush() - self.f.write(data) - def close(self): - print - sts = self.f.close() - if sts: - print 'Exit status:', sts - -# Ask for and open a save file, or return None if not to save -def open_savefile(): - try: - savefile = raw_input( \ - 'Save as file [CR == don\'t save; |pipeline or ~user/... OK]: ') - except EOFError: - print - return None - savefile = string.strip(savefile) - if not savefile: - return None - if savefile[0] == '|': - cmd = string.strip(savefile[1:]) - try: - p = os.popen(cmd, 'w') - except IOError, msg: - print `cmd`, ':', msg - return None - print 'Piping through', `cmd`, '...' - return p - if savefile[0] == '~': - savefile = os.path.expanduser(savefile) - try: - f = open(savefile, 'w') - except IOError, msg: - print `savefile`, ':', msg - return None - print 'Saving to', `savefile`, '...' - return f - -# Test program -def test(): - if sys.argv[4:]: - print 'usage: gopher [ [selector] host [port] ]' - sys.exit(2) - elif sys.argv[3:]: - browser(sys.argv[1], sys.argv[2], sys.argv[3]) - elif sys.argv[2:]: - try: - port = string.atoi(sys.argv[2]) - selector = '' - host = sys.argv[1] - except string.atoi_error: - selector = sys.argv[1] - host = sys.argv[2] - port = '' - browser(selector, host, port) - elif sys.argv[1:]: - browser('', sys.argv[1]) - else: - browser() - -# Call the test program as a main program -test() diff --git a/Demo/sockets/mcast.py b/Demo/sockets/mcast.py deleted file mode 100755 index 401138362e..0000000000 --- a/Demo/sockets/mcast.py +++ /dev/null @@ -1,97 +0,0 @@ -# Send/receive UDP multicast packets (SGI) -# After /usr/people/4Dgifts/examples/network/mcast.c -# Usage: -# mcast -s (sender) -# mcast -b (sender, using broadcast instead multicast) -# mcast (receivers) - -MYPORT = 8123 -MYGROUP = '225.0.0.250' - -import sys -import time -import struct -import regsub -from socket import * -from SOCKET import * -from IN import * # SGI specific!!! (Sorry) - - -# Main program -def main(): - flags = sys.argv[1:] - # - if flags: - sender(flags[0]) - else: - receiver() - - -# Sender subroutine (only one per local area network) -def sender(flag): - s = socket(AF_INET, SOCK_DGRAM) - if flag == '-b': - s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1) - mygroup = '' - else: - mygroup = MYGROUP - ttl = struct.pack('b', 1) # Time-to-live - s.setsockopt(IPPROTO_IP, IP_MULTICAST_TTL, ttl) - while 1: - data = `time.time()` -## data = data + (1400 - len(data)) * '\0' - s.sendto(data, (mygroup, MYPORT)) - time.sleep(1) - - -# Receiver subroutine (as many as you like) -def receiver(): - # Open and initialize the socket - s = openmcastsock(MYGROUP, MYPORT) - # - # Loop, printing any data we receive - while 1: - data, sender = s.recvfrom(1500) - while data[-1:] == '\0': data = data[:-1] # Strip trailing \0's - print sender, ':', `data` - - -# Open a UDP socket, bind it to a port and select a multicast group -def openmcastsock(group, port): - # Import modules used only here - import regsub - import socket - import struct - from SOCKET import * - from IN import * - # - # Create a socket - s = socket.socket(AF_INET, SOCK_DGRAM) - # - # Allow multiple copies of this program on one machine - # (not strictly needed) - s.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1) - # - # Bind it to the port - s.bind('', port) - # - # Look up multicast group address in name server - # (doesn't hurt if it is already in ddd.ddd.ddd.ddd format) - group = socket.gethostbyname(group) - # - # Construct binary group address - bytes = eval(regsub.gsub('\.', ',', group)) - grpaddr = 0 - for byte in bytes: grpaddr = (grpaddr << 8) | byte - # - # Construct struct mreq from grpaddr and ifaddr - ifaddr = INADDR_ANY - mreq = struct.pack('ll', grpaddr, ifaddr) - # - # Add group membership - s.setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq) - # - return s - - -main() diff --git a/Demo/sockets/radio.py b/Demo/sockets/radio.py deleted file mode 100755 index 5905ff2a3c..0000000000 --- a/Demo/sockets/radio.py +++ /dev/null @@ -1,14 +0,0 @@ -# Receive UDP packets transmitted by a broadcasting service - -MYPORT = 50000 - -import sys -from socket import * - -s = socket(AF_INET, SOCK_DGRAM) -s.bind('', MYPORT) - -while 1: - data, wherefrom = s.recvfrom(1500, 0) - sys.stderr.write(`wherefrom` + '\n') - sys.stdout.write(data) diff --git a/Demo/sockets/telnet.py b/Demo/sockets/telnet.py deleted file mode 100755 index 3bb36efdc2..0000000000 --- a/Demo/sockets/telnet.py +++ /dev/null @@ -1,109 +0,0 @@ -#! /usr/local/bin/python - -# Minimal interface to the Internet telnet protocol. -# -# It refuses all telnet options and does not recognize any of the other -# telnet commands, but can still be used to connect in line-by-line mode. -# It's also useful to play with a number of other services, -# like time, finger, smtp and even ftp. -# -# Usage: telnet host [port] -# -# The port may be a service name or a decimal port number; -# it defaults to 'telnet'. - - -import sys, posix, time -from socket import * - -BUFSIZE = 1024 - -# Telnet protocol characters - -IAC = chr(255) # Interpret as command -DONT = chr(254) -DO = chr(253) -WONT = chr(252) -WILL = chr(251) - -def main(): - host = sys.argv[1] - try: - hostaddr = gethostbyname(host) - except error: - sys.stderr.write(sys.argv[1] + ': bad host name\n') - sys.exit(2) - # - if len(sys.argv) > 2: - servname = sys.argv[2] - else: - servname = 'telnet' - # - if '0' <= servname[:1] <= '9': - port = eval(servname) - else: - try: - port = getservbyname(servname, 'tcp') - except error: - sys.stderr.write(servname + ': bad tcp service name\n') - sys.exit(2) - # - s = socket(AF_INET, SOCK_STREAM) - # - try: - s.connect(host, port) - except error, msg: - sys.stderr.write('connect failed: ' + `msg` + '\n') - sys.exit(1) - # - pid = posix.fork() - # - if pid == 0: - # child -- read stdin, write socket - while 1: - line = sys.stdin.readline() - s.send(line) - else: - # parent -- read socket, write stdout - iac = 0 # Interpret next char as command - opt = '' # Interpret next char as option - while 1: - data = s.recv(BUFSIZE) - if not data: - # EOF; kill child and exit - sys.stderr.write( '(Closed by remote host)\n') - posix.kill(pid, 9) - sys.exit(1) - cleandata = '' - for c in data: - if opt: - print ord(c) - s.send(opt + c) - opt = '' - elif iac: - iac = 0 - if c == IAC: - cleandata = cleandata + c - elif c in (DO, DONT): - if c == DO: print '(DO)', - else: print '(DONT)', - opt = IAC + WONT - elif c in (WILL, WONT): - if c == WILL: print '(WILL)', - else: print '(WONT)', - opt = IAC + DONT - else: - print '(command)', ord(c) - elif c == IAC: - iac = 1 - print '(IAC)', - else: - cleandata = cleandata + c - sys.stdout.write(cleandata) - sys.stdout.flush() - - -try: - main() -except KeyboardInterrupt: - pass diff --git a/Demo/sockets/throughput.py b/Demo/sockets/throughput.py deleted file mode 100755 index f1607f316e..0000000000 --- a/Demo/sockets/throughput.py +++ /dev/null @@ -1,93 +0,0 @@ -#! /usr/local/bin/python - -# Test network throughput. -# -# Usage: -# 1) on host_A: throughput -s [port] # start a server -# 2) on host_B: throughput -c count host_A [port] # start a client -# -# The server will service multiple clients until it is killed. -# -# The client performs one transfer of count*BUFSIZE bytes and -# measures the time it takes (roundtrip!). - - -import sys, time -from socket import * - -MY_PORT = 50000 + 42 - -BUFSIZE = 1024 - - -def main(): - if len(sys.argv) < 2: - usage() - if sys.argv[1] == '-s': - server() - elif sys.argv[1] == '-c': - client() - else: - usage() - - -def usage(): - sys.stdout = sys.stderr - print 'Usage: (on host_A) throughput -s [port]' - print 'and then: (on host_B) throughput -c count host_A [port]' - sys.exit(2) - - -def server(): - if len(sys.argv) > 2: - port = eval(sys.argv[2]) - else: - port = MY_PORT - s = socket(AF_INET, SOCK_STREAM) - s.bind('', port) - s.listen(0) - print 'Server ready...' - while 1: - conn, (host, remoteport) = s.accept() - while 1: - data = conn.recv(BUFSIZE) - if not data: - break - del data - conn.send('OK\n') - conn.close() - print 'Done with', host, 'port', remoteport - - -def client(): - if len(sys.argv) < 4: - usage() - count = int(eval(sys.argv[2])) - host = sys.argv[3] - if len(sys.argv) > 4: - port = eval(sys.argv[4]) - else: - port = MY_PORT - testdata = 'x' * (BUFSIZE-1) + '\n' - t1 = time.millitimer() - s = socket(AF_INET, SOCK_STREAM) - t2 = time.millitimer() - s.connect(host, port) - t3 = time.millitimer() - i = 0 - while i < count: - i = i+1 - s.send(testdata) - s.shutdown(1) # Send EOF - t4 = time.millitimer() - data = s.recv(BUFSIZE) - t5 = time.millitimer() - print data - print 'Raw timers:', t1, t2, t3, t4, t5 - print 'Intervals:', t2-t1, t3-t2, t4-t3, t5-t4 - print 'Total:', t5-t1 - print 'Throughput:', int(float(BUFSIZE*count) / float(t5-t1)), - print 'K/sec.' - - -main() diff --git a/Demo/sockets/udpecho.py b/Demo/sockets/udpecho.py deleted file mode 100755 index 8839eb8057..0000000000 --- a/Demo/sockets/udpecho.py +++ /dev/null @@ -1,63 +0,0 @@ -#! /usr/local/bin/python - -# Client and server for udp (datagram) echo. -# -# Usage: udpecho -s [port] (to start a server) -# or: udpecho -c host [port] 2: - port = eval(sys.argv[2]) - else: - port = ECHO_PORT - s = socket(AF_INET, SOCK_DGRAM) - s.bind('', port) - print 'udp echo server ready' - while 1: - data, addr = s.recvfrom(BUFSIZE) - print 'server received', `data`, 'from', `addr` - s.sendto(data, addr) - -def client(): - if len(sys.argv) < 3: - usage() - host = sys.argv[2] - if len(sys.argv) > 3: - port = eval(sys.argv[3]) - else: - port = ECHO_PORT - addr = host, port - s = socket(AF_INET, SOCK_DGRAM) - s.bind('', 0) - print 'udp echo client ready, reading stdin' - while 1: - line = sys.stdin.readline() - if not line: - break - s.sendto(line, addr) - data, fromaddr = s.recvfrom(BUFSIZE) - print 'client received', `data`, 'from', `fromaddr` - -main() diff --git a/Demo/stdwin/FormTest.py b/Demo/stdwin/FormTest.py deleted file mode 100755 index ce62802ebf..0000000000 --- a/Demo/stdwin/FormTest.py +++ /dev/null @@ -1,30 +0,0 @@ -#! /usr/local/bin/python - -testlabels = 'Name', 'Address', 'City', 'Country', 'Comments' - -def main(): - import stdwin - from WindowParent import WindowParent, MainLoop - from FormSplit import FormSplit - from Buttons import Label - from TextEdit import TextEdit - # - stdwin.setdefscrollbars(0, 0) - # - w = WindowParent().create('FormTest', (0, 0)) - f = FormSplit().create(w) - # - h, v = 0, 0 - for label in testlabels: - f.placenext(h, v) - lbl = Label().definetext(f, label) - f.placenext(h + 100, v) - txt = TextEdit().createboxed(f, (40, 2), (2, 2)) - #txt = TextEdit().create(f, (40, 2)) - v = v + 2*stdwin.lineheight() + 10 - # - w.realize() - # - MainLoop() - -main() diff --git a/Demo/stdwin/README b/Demo/stdwin/README deleted file mode 100644 index 2d0bd85c5b..0000000000 --- a/Demo/stdwin/README +++ /dev/null @@ -1,16 +0,0 @@ -Contents of this directory: - -FormTest.py Show how a form can be built to enter multiple fields -RadioGroups.py Show how to use multiple groups of radio buttons -TestCSplit.py Test CSplit widget (a clock-like split) -TestDirList.py Test DirList widget (lists directory contents) -TestFormSplit.py Test FormSplit widget (arbitrary grouping) -TestSched.py Test WindowSched widget (event scheduling) -TestTextEdit.py Test TextEdit widget (probably doen't work any more) -clock.py A simple clock, with alarm -jukebox.py Play audio files (SGI only, needs SOX and SFPLAY) -lpwin.py Watch line printer queues -microedit.py The smallest window editor -miniedit.py A small multi-window editor -python.py A window interface to the Python interpreter -wdiff.py A window-based directory diff diff --git a/Demo/stdwin/RadioGroups.py b/Demo/stdwin/RadioGroups.py deleted file mode 100755 index fcd693f65b..0000000000 --- a/Demo/stdwin/RadioGroups.py +++ /dev/null @@ -1,98 +0,0 @@ -#! /usr/local/bin/python - -# radiogroups.py -# -# Demonstrate multiple groups of radio buttons - -import stdwin -from Buttons import * -from WindowParent import WindowParent, MainLoop -from HVSplit import HSplit, VSplit - -def main(): - # - # Create the widget hierarchy, top-down - # - # 1. Create the window - # - window = WindowParent().create('Radio Groups', (0, 0)) - # - # 2. Create a horizontal split to contain the groups - # - topsplit = HSplit().create(window) - # - # 3. Create vertical splits, one for each group - # - group1 = VSplit().create(topsplit) - group2 = VSplit().create(topsplit) - group3 = VSplit().create(topsplit) - # - # 4. Create individual radio buttons, each in their own split - # - b11 = RadioButton().definetext(group1, 'Group 1 button 1') - b12 = RadioButton().definetext(group1, 'Group 1 button 2') - b13 = RadioButton().definetext(group1, 'Group 1 button 3') - # - b21 = RadioButton().definetext(group2, 'Group 2 button 1') - b22 = RadioButton().definetext(group2, 'Group 2 button 2') - b23 = RadioButton().definetext(group2, 'Group 2 button 3') - # - b31 = RadioButton().definetext(group3, 'Group 3 button 1') - b32 = RadioButton().definetext(group3, 'Group 3 button 2') - b33 = RadioButton().definetext(group3, 'Group 3 button 3') - # - # 5. Define the grouping for the radio buttons. - # Note: this doesn't have to be the same as the - # grouping is splits (although it usually is). - # Also set the 'hook' procedure for each button - # - list1 = [b11, b12, b13] - list2 = [b21, b22, b23] - list3 = [b31, b32, b33] - # - for b in list1: - b.group = list1 - b.on_hook = myhook - for b in list2: - b.group = list2 - b.on_hook = myhook - for b in list3: - b.group = list3 - b.on_hook = myhook - # - # 6. Select a default button in each group - # - b11.select(1) - b22.select(1) - b33.select(1) - # - # 6. Realize the window - # - window.realize() - # - # 7. Dispatch events until the window is closed - # - MainLoop() - # - # 8. Report final selections - # - print 'You selected the following choices:' - if b11.selected: print '1.1' - if b12.selected: print '1.2' - if b13.selected: print '1.3' - if b21.selected: print '2.1' - if b22.selected: print '2.2' - if b23.selected: print '2.3' - if b31.selected: print '3.1' - if b32.selected: print '3.2' - if b33.selected: print '3.3' - - -# My 'hook' procedure -# This is placed as 'hook' attribute on each button. -# The example just prints the title of the selected button. -# -def myhook(self): - print 'Selected:', self.text - -main() diff --git a/Demo/stdwin/TestCSplit.py b/Demo/stdwin/TestCSplit.py deleted file mode 100755 index 9297e46b60..0000000000 --- a/Demo/stdwin/TestCSplit.py +++ /dev/null @@ -1,25 +0,0 @@ -#! /usr/local/bin/python - -# TestCSplit - -import stdwin -from WindowParent import WindowParent, MainLoop -from Buttons import PushButton - -def main(n): - from CSplit import CSplit - # - stdwin.setdefscrollbars(0, 0) - # - the_window = WindowParent().create('TestCSplit', (0, 0)) - the_csplit = CSplit().create(the_window) - # - for i in range(n): - the_child = PushButton().define(the_csplit) - the_child.settext(`(i+n-1)%n+1`) - # - the_window.realize() - # - MainLoop() - -main(12) diff --git a/Demo/stdwin/TestDirList.py b/Demo/stdwin/TestDirList.py deleted file mode 100755 index 7fb45ae4d0..0000000000 --- a/Demo/stdwin/TestDirList.py +++ /dev/null @@ -1,18 +0,0 @@ -#! /usr/local/bin/python - -# TestDirList - -from DirList import DirListWindow -from WindowParent import MainLoop - -def main(): - import sys - args = sys.argv[1:] - if not args: - args = ['.'] - # Mac: args = [':'] - for arg in args: - w = DirListWindow().create(arg) - MainLoop() - -main() diff --git a/Demo/stdwin/TestFormSplit.py b/Demo/stdwin/TestFormSplit.py deleted file mode 100755 index 2750378311..0000000000 --- a/Demo/stdwin/TestFormSplit.py +++ /dev/null @@ -1,27 +0,0 @@ -#! /usr/local/bin/python - -# TestFormSplit - -import stdwin -from WindowParent import WindowParent, MainLoop -from Buttons import PushButton - -def main(n): - from FormSplit import FormSplit - # - stdwin.setdefscrollbars(1, 1) - # - the_window = WindowParent().create('TestFormSplit', (0, 0)) - the_form = FormSplit().create(the_window) - # - for i in range(n): - if i % 3 == 0: - the_form.placenext(i*40, 0) - the_child = PushButton().define(the_form) - the_child.settext('XXX-' + `i` + '-YYY') - # - the_window.realize() - # - MainLoop() - -main(6) diff --git a/Demo/stdwin/TestSched.py b/Demo/stdwin/TestSched.py deleted file mode 100755 index f6bbe23688..0000000000 --- a/Demo/stdwin/TestSched.py +++ /dev/null @@ -1,38 +0,0 @@ -#! /usr/local/bin/python - -# TestSched - -import stdwin -from WindowParent import WindowParent, MainLoop -import WindowSched -from Buttons import PushButton - -def my_ringer(child): - child.my_id = None - stdwin.fleep() - -def my_hook(child): - # schedule for the bell to ring in N seconds; cancel previous - if child.my_id: - WindowSched.cancel(child.my_id) - child.my_id = \ - WindowSched.enter(child.my_number*1000, 0, my_ringer, (child,)) - -def main(n): - from CSplit import CSplit - - window = WindowParent().create('TestSched', (0, 0)) - csplit = CSplit().create(window) - - for i in range(n): - child = PushButton().define(csplit) - child.my_number = i - child.my_id = None - child.settext(`(i+n-1)%n+1`) - child.hook = my_hook - - window.realize() - - WindowSched.run() - -main(12) diff --git a/Demo/stdwin/TestTextEdit.py b/Demo/stdwin/TestTextEdit.py deleted file mode 100755 index 9f4c86117d..0000000000 --- a/Demo/stdwin/TestTextEdit.py +++ /dev/null @@ -1,13 +0,0 @@ -#! /usr/local/bin/python - -# Test TextEdit widgets - -def main(): - from TextEdit import TextEdit - from WindowParent import WindowParent, MainLoop - w = WindowParent().create('Test TextEdit', (0, 0)) - t = TextEdit().create(w, (40, 4)) - w.realize() - MainLoop() - -main() diff --git a/Demo/stdwin/clock.py b/Demo/stdwin/clock.py deleted file mode 100755 index 975154a5e8..0000000000 --- a/Demo/stdwin/clock.py +++ /dev/null @@ -1,204 +0,0 @@ -#! /usr/local/bin/python - -# 'clock' -- A simple alarm clock - -# The alarm can be set at 5 minute intervals on a 12 hour basis. -# It is controlled with the mouse: -# - Click and drag around the circle to set the alarm. -# - Click far outside the circle to clear the alarm. -# - Click near the center to set the alarm at the last time set. -# The alarm time is indicated by a small triangle just outside the circle, -# and also by a digital time at the bottom. -# The indicators disappear when the alarm is not set. -# When the alarm goes off, it beeps every minute for five minutes, -# and the clock turns into inverse video. -# Click or activate the window to turn the ringing off. - -import stdwin -from stdwinevents import WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP, \ - WE_TIMER, WE_DRAW, WE_SIZE, WE_CLOSE, WE_ACTIVATE -import mainloop -import time -from math import sin, cos, atan2, pi, sqrt - -DEFWIDTH, DEFHEIGHT = 200, 200 - -MOUSE_EVENTS = (WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP) -ORIGIN = 0, 0 -FARAWAY = 2000, 2000 -EVERYWHERE = ORIGIN, FARAWAY - -# TZDIFF = 5*3600 # THINK C 3.0 returns UCT if local time is EST -TZDIFF = 0 # THINK C 4.0 always returns local time - - -def main(): - win = makewindow() - del win - mainloop.mainloop() - -def makewindow(): - stdwin.setdefwinsize(DEFWIDTH, DEFHEIGHT + stdwin.lineheight()) - win = stdwin.open('clock') - setdimensions(win) - win.set = 1 # True when alarm is set - win.time = 11*60 + 40 # Time when alarm must go off - win.ring = 0 # True when alarm is ringing - win.dispatch = cdispatch - mainloop.register(win) - settimer(win) - return win - -def cdispatch(event): - type, win, detail = event - if type == WE_DRAW: - drawproc(win, detail) - elif type == WE_TIMER: - settimer(win) - drawproc(win, EVERYWHERE) - elif type in MOUSE_EVENTS: - mouseclick(win, type, detail) - elif type == WE_ACTIVATE: - if win.ring: - # Turn the ringing off - win.ring = 0 - win.begindrawing().invert(win.mainarea) - elif type == WE_SIZE: - win.change(EVERYWHERE) - setdimensions(win) - elif type == WE_CLOSE: - mainloop.unregister(win) - win.close() - -def setdimensions(win): - width, height = win.getwinsize() - height = height - stdwin.lineheight() - if width < height: size = width - else: size = height - halfwidth = width/2 - halfheight = height/2 - win.center = halfwidth, halfheight - win.radius = size*45/100 - win.width = width - win.height = height - win.corner = width, height - win.mainarea = ORIGIN, win.corner - win.lineheight = stdwin.lineheight() - win.farcorner = width, height + win.lineheight - win.statusarea = (0, height), win.farcorner - win.fullarea = ORIGIN, win.farcorner - -def settimer(win): - now = getlocaltime() - win.times = calctime(now) - delay = 61 - now % 60 - win.settimer(10 * delay) - minutes = (now/60) % 720 - if win.ring: - # Is it time to stop the alarm ringing? - since = (minutes - win.time + 720) % 720 - if since >= 5: - # Stop it now - win.ring = 0 - else: - # Ring again, once every minute - stdwin.fleep() - elif win.set and minutes == win.time: - # Start the alarm ringing - win.ring = 1 - stdwin.fleep() - -def drawproc(win, area): - hours, minutes, seconds = win.times - d = win.begindrawing() - d.cliprect(area) - d.erase(EVERYWHERE) - d.circle(win.center, win.radius) - d.line(win.center, calcpoint(win, hours*30 + minutes/2, 0.6)) - d.line(win.center, calcpoint(win, minutes*6, 1.0)) - str = dd(hours) + ':' + dd(minutes) - p = (win.width - d.textwidth(str))/2, win.height * 3 / 4 - d.text(p, str) - if win.set: - drawalarm(win, d) - drawalarmtime(win, d) - if win.ring: - d.invert(win.mainarea) - -def mouseclick(win, type, detail): - d = win.begindrawing() - if win.ring: - # First turn the ringing off - win.ring = 0 - d.invert(win.mainarea) - h, v = detail[0] - ch, cv = win.center - x, y = h-ch, cv-v - dist = sqrt(x*x + y*y) / float(win.radius) - if dist > 1.2: - if win.set: - drawalarm(win, d) - erasealarmtime(win, d) - win.set = 0 - elif dist < 0.8: - if not win.set: - win.set = 1 - drawalarm(win, d) - drawalarmtime(win, d) - else: - # Convert to half-degrees (range 0..720) - alpha = atan2(y, x) - hdeg = alpha*360.0/pi - hdeg = 180.0 - hdeg - hdeg = (hdeg + 720.0) % 720.0 - atime = 5*int(hdeg/5.0 + 0.5) - if atime <> win.time or not win.set: - if win.set: - drawalarm(win, d) - erasealarmtime(win, d) - win.set = 1 - win.time = atime - drawalarm(win, d) - drawalarmtime(win, d) - -def drawalarm(win, d): - p1 = calcpoint(win, float(win.time)/2.0, 1.02) - p2 = calcpoint(win, float(win.time)/2.0 - 4.0, 1.1) - p3 = calcpoint(win, float(win.time)/2.0 + 4.0, 1.1) - d.xorline(p1, p2) - d.xorline(p2, p3) - d.xorline(p3, p1) - -def erasealarmtime(win, d): - d.erase(win.statusarea) - -def drawalarmtime(win, d): - # win.time is in the range 0..720 with origin at 12 o'clock - # Convert to hours (0..12) and minutes (12*(0..60)) - hh = win.time/60 - mm = win.time%60 - str = 'Alarm@' + dd(hh) + ':' + dd(mm) - p1 = (win.width - d.textwidth(str))/2, win.height - d.text(p1, str) - -def calcpoint(win, degrees, size): - alpha = pi/2.0 - float(degrees) * pi/180.0 - x, y = cos(alpha), sin(alpha) - h, v = win.center - r = float(win.radius) - return h + int(x*size*r), v - int(y*size*r) - -def calctime(now): - seconds = now % 60 - minutes = (now/60) % 60 - hours = (now/3600) % 12 - return hours, minutes, seconds - -def dd(n): - s = `n` - return '0'*(2-len(s)) + s - -def getlocaltime(): - return int(time.time() - TZDIFF) - -main() diff --git a/Demo/stdwin/ibrowse/README b/Demo/stdwin/ibrowse/README deleted file mode 100644 index 22e403928d..0000000000 --- a/Demo/stdwin/ibrowse/README +++ /dev/null @@ -1,34 +0,0 @@ -This directory contains a browser written in Python for "Info files" -as used by the Emacs documentation system. The browser requires that -Python is built with the "stdwin" option and runs under X11 or the -Mac window system. - -Now you can read Info files even if you can't spare the memory, time or -disk space to run Emacs. (I have used this extensively on a Macintosh -with 1 Megabyte main memory and a 20 Meg harddisk.) - -You can give this to someone with great fear of complex computer -systems, as long as they can use a mouse. - -Another reason to use this is to encourage the use of Info for on-line -documentation of software that is not related to Emacs or GNU. -(In particular, I plan to redo the Python and STDWIN documentation -in texinfo.) - -The main program is in file "ib.py"; this accepts a file name and a -node name as optional command line arguments, i.e., its usage is - - python ib.py [file [node]] - - -Configuration: - -- The pathname of the directory (or directories) containing -the standard Info files should be set by editing the -value assigned to INFOPATH in module ifile.py. - -- The default font should be set by editing the value of FONT -in this module (ibrowse.py). - -- For fastest I/O, you may look at BLOCKSIZE and a few other -constants in ifile.py. diff --git a/Demo/stdwin/ibrowse/dir b/Demo/stdwin/ibrowse/dir deleted file mode 100755 index 21d1989cac..0000000000 --- a/Demo/stdwin/ibrowse/dir +++ /dev/null @@ -1,62 +0,0 @@ --*- Text -*- -This is the file .../ibrowse/dir, which contains the topmost node of the -Info hierarchy. The first time you invoke Ibrowse you start off -looking at that node, which is (dir)Top. (This is a copy of the Info -dir node, except that the reference to Info is replaced by one to Ibrowse.) - -File: dir Node: Top This is the top of the INFO tree - This (the Directory node) gives a menu of major topics. - Typing "d" returns here, "q" exits, "?" lists all INFO commands, "h" - gives a primer for first-timers, "mTexinfo" visits Texinfo topic, - etc. - --- PLEASE ADD DOCUMENTATION TO THIS TREE. (See INFO topic first.) --- - -* Menu: The list of major topics begins on the next line. - -* Ibrowse: (ibrowse). Documentation browsing system. - -* Emacs: (emacs). The extensible self-documenting text editor. - -* VIP: (vip). A VI-emulation for Emacs. - -* Texinfo: (texinfo). - With one source file, make either a printed manual - (through TeX) or an Info file (through texinfo). - Full documentation in this menu item. - -* Termcap: (termcap). - The termcap library, which enables application programs - to handle all types of character-display terminals. - -* Regex: (regex). - The GNU regular expression library. - -* Bison: (bison.info). - The GNU yacc-compatible parser generator. - -* GCC: (gcc.info). - The GNU C compiler. - -* G++: (g-whiz). - The GNU C++ compiler. - -* LibG++: (libg++). - The GNU C++ library. - -* GDB: (gdb.info). - The GNU debugger. - -* CPP: (cpp.info). - The GNU C preprocessor. - -* Lispref: (lispref). - The GNU Emacs Lisp reference manual. - -* Make: (make-info). - The GNU make program. - -* M4: (m4). - The GNU m4 program. - -* Gawk: (gawk-info). - GNU awk. diff --git a/Demo/stdwin/ibrowse/ib b/Demo/stdwin/ibrowse/ib deleted file mode 100755 index 04cb790732..0000000000 --- a/Demo/stdwin/ibrowse/ib +++ /dev/null @@ -1,2 +0,0 @@ -: ${ARCH}=`arch` -exec /ufs/guido/bin/$ARCH/python ib.py ${1+"$@"} diff --git a/Demo/stdwin/ibrowse/ib.py b/Demo/stdwin/ibrowse/ib.py deleted file mode 100755 index 588270ed49..0000000000 --- a/Demo/stdwin/ibrowse/ib.py +++ /dev/null @@ -1,21 +0,0 @@ -#! /usr/local/bin/python - -# Call ibrowse (the info file browser) under UNIX. - -import sys -import ibrowse - -if len(sys.argv) > 1: - file = sys.argv[1] - if len(sys.argv) > 2: - if len(sys.argv) > 3: - sys.stdout = sys.stderr - print 'usage:', sys.argv[0], '[file [node]]' - sys.exit(2) - else: - node = sys.argv[2] - else: - node = '' - ibrowse.start('(' + file + ')' + node) -else: - ibrowse.main() diff --git a/Demo/stdwin/ibrowse/ibrowse b/Demo/stdwin/ibrowse/ibrowse deleted file mode 100755 index 8b0dcde30e..0000000000 --- a/Demo/stdwin/ibrowse/ibrowse +++ /dev/null @@ -1,719 +0,0 @@ -This file documents the ibrowse program. -*-Text-*- -The H command of ibrowse goes to the node Help in this file. - -File: ibrowse Node: Top Up: (DIR) Next: Expert - -Ibrowse is a program for reading documentation, which you are using now. -** Ibrowse uses the file format of the Emacs Info program, and its -** commands are similar, but not identical. - -To learn how to use Ibrowse, type the command "h". It will bring you -to a programmed instruction sequence. - -* Menu: - -* Expert:: Advanced Ibrowse commands: c, k, g, s, 1 - 9, arrows. -* Add:: Describes how to add new nodes to the hierarchy. - Also tells what nodes look like. -* Menus:: How to add to or create menus in Info nodes. -* Cross-refs:: How to add cross-references to Info nodes. -* Tags:: How to make tag tables for Info files. -* Checking:: How to check the consistency of an Info file. -* Texinfo: (texinfo). - How to generate an Info file and a printed manual - from the same source file. - -File: ibrowse Node: Summary Next: Help - -Ibrowse is a Python program for browsing through the Emacs Info -documentation tree. Documentation in Info is divided into "nodes", -each of which discusses one topic and contains references to other -nodes which discuss related topics. Ibrowse has commands to follow the -references and show you other nodes. - -h Invoke the Ibrowse tutorial. -? Display this Summary node. -q Quit Ibrowse. -w Close current window. - -Selecting other nodes: -n Move to the "next" node of this node. -p Move to the "previous" node of this node. -m Pick menu item specified by name (or abbreviation). -1-9 Pick first..ninth in node's menu. - Menu items select nodes that are "subsections" of this node. -u Move "up" from this node (i.e., from a subsection to a section). -f Follow a cross reference by name (or abbrev). Type `l' to get back. -l Move back to the last node you were in. - -Moving within a node: -Space Scroll forward a full screen. DEL, BS Scroll backward. -b Go to beginning of node. - -Advanced commands: -k Clone current window (create an independent duplicate). -c Copy text selection to clipboard (for paste in another application). -g Move to node specified by name. - You may include a filename as well, as (FILENAME)NODENAME. -d Go to the main directory of Info files. -t Go to Top node of this file. -s Search through this Info file for node with specified regexp. - -File: ibrowse Node: Help-Small-Screen Next: Help - -Since your terminal has an unusually small number of lines on its -screen, it is necessary to give you special advice at the beginning. - -If you see the text "--All----" at near the bottom right corner of -the screen, it means the entire text you are looking at fits on the -screen. If you see "--Top----" instead, it means that there is more -text below that does not fit. To move forward through the text and -see another screen full, press the Space bar. To move back up, press -the key labeled Rubout or Delete or DEL. - -Here are 40 lines of junk, so you can try Spaces and Rubout and -see what they do. At the end are instructions of what you should do -next. - -This is line 17 -This is line 18 -This is line 19 -This is line 20 -This is line 21 -This is line 22 -This is line 23 -This is line 24 -This is line 25 -This is line 26 -This is line 27 -This is line 28 -This is line 29 -This is line 30 -This is line 31 -This is line 32 -This is line 33 -This is line 34 -This is line 35 -This is line 36 -This is line 37 -This is line 38 -This is line 39 -This is line 40 -This is line 41 -This is line 42 -This is line 43 -This is line 44 -This is line 45 -This is line 46 -This is line 47 -This is line 48 -This is line 49 -This is line 50 -This is line 51 -This is line 52 -This is line 53 -This is line 54 -This is line 55 -This is line 56 - -If you have managed to get here, go back to the beginning with -Rubout, and come back here again, then you understand Space and -Rubout. So now type an "n"--just one character; don't type the -quotes and don't type a Return afterward-- to get to the normal start -of the course. - -File: ibrowse Node: Help Next: Help-P Previous: Help-Small-Screen - -You are talking to the program Ibrowse, for reading documentation. - - Right now you are looking at one "Node" of Information. -A node contains text describing a specific topic at a specific -level of detail. This node's topic is "how to use Ibrowse". - - The top line of a node is its "header". This node's header (look at -it now) says that it is the node named "Help" in the file "ibrowse". -It says that the Next node after this one is the node called "Help-P". -An advanced Ibrowse command lets you go to any node whose name you know. - - Besides a "Next", a node can have a "Previous" or an "Up". -This node has a "Previous" but no "Up", as you can see. - - Now it's time to move on to the Next node, named "Help-P". - ->> Type "n" to move there. Type just one character; - don't type the quotes and don't type a Return afterward. - -">>" in the margin means it is really time to try a command. - -File: ibrowse Node: Help-P Next: Help-Page Previous: Help - -This node is called "Help-P". The "Previous" node, as you see, is -"Help", which is the one you just came from using the "N" command. -Another "N" command now would take you to the Next node, "Help-Page". - ->> But don't do that yet. First, try the "p" command, which takes -you to the Previous node. When you get there, you can do an "n" -again to return here. - - This all probably seems insultingly simple so far, but DON'T be -led into skimming. Things will get more complicated soon. Also, -don't try a new command until you are told it's time to. Otherwise, -you may make Ibrowse skip past an important warning that was coming up. - ->> Now do an "n" to get to the node "Help-Page" and learn more. - -File: ibrowse Node: Help-Page Next: Help-M Previous: Help-P - -Space, Backspace, and B commands. - - This node's header tells you that you are now at node "Help-Page", and -that "P" would get you back to "Help-P". The line starting "Space," -is a "Title", saying what the node is about (most nodes have titles). - - This is a big node and it doesn't all fit on your display screen. -You can tell that there is more that isn't visible because you -the scroll bar on the side of the window has become active (gray). - - The Space, Backspace and B commands exist to allow you to "move -around" in a node that doesn't all fit on the screen at once. -Space moves forward, to show what was below the bottom of the screen. -Backspace moves backward, to show what was above the top of the screen -(there isn't anything above the top until you have typed some spaces). - ->> Now try typing a Space (afterward, type a Backspace to return here). - - When you type the space, the two lines that were at the bottom of the -screen appear at the top, followed by more lines. Backspace takes the -two lines from the top and moves them to the bottom, USUALLY, but if -there are not a full screen's worth of lines above them they may not -make it all the way to the bottom. - - If you type a Space when there is no more to see, it will ring the -bell and otherwise do nothing. The same goes for a Backspace when -the header of the node is visible. - - Of course you can use the mouse and directly move the scroll bar -as well, but Ibrowse has keyboard commands for almost everything, -including scrolling. These keyboard commands are called "shortcuts", -because it generally takes less effort to press a key on the -keyboard than to move the mouse. On the other hand, if you are -an infrequent user of Ibrowse, you can do everything with the -mouse that you can do with the keyboard. Just look in the menus -(I'm sure you must know how to use the menus on this system, or -else you couldn't have gotten this far...). In fact you'll see that -the commands and shortcuts listed in the menus are the same as those -described in this course. You can use the shortcuts either with or -without the "Command" or "Meta" key. - - Two menus are always available: the "Ibrowse" menu contains commands -pertaining to the Ibrowse program at large, while the "Navigation" menu -contains commands that move around between nodes. There may be other -menus; these will be explained later. - - To move back to the beginning of the node you are on, you can type -a lot of Backspaces. You can also type simply "b" for beginning. ->> Try that now. (I have put in enough verbiage to make sure you are - not on the first screenful now). Then come back, with Spaces. - - You have just learned a considerable number of commands. If you -want to use one but have trouble remembering which, just pull down -the menus to get a summary of commands and shortcuts. Some additional -shortcuts (not listed in the menus) are listed by the "Short help" -command. This brings up a dialog box which you can acknowledge -by clicking the OK button or pressing the Return key. - - From now on, you will encounter large nodes without warning, and -will be expected to know how to use Space and Backspace to move -around in them without being told. Since you could change the -size of the window used, it would be impossible to warn you anyway. - ->> Now type "n" to see the description of the "m" command. - -File: ibrowse Node: Help-M Next: Help-Adv Previous: Help-Page - -Menus and the "m" command - - With only the "n" and "p" commands for moving between nodes, nodes -are restricted to a linear sequence. Menus allow a branching -structure. A menu is a list of other nodes you can move to. It is -actually just part of the text of the node formatted specially so that -Ibrowse can interpret it. The beginning of a menu is always identified -by a line which starts with "* Menu:". A node contains a menu if and -only if it has a line in it which starts that way. The only menu you -can use at any moment is the one in the node you are in. To use a -menu in any other node, you must move to that node first. - - (There is an unfortunate confusion of terms here. "Menu" may refer -to one of the Ibrowse menus at the top, such as as the "Ibrowse" and -"Navigation" menus explained in the previous node, or to the menu in -a node. Where confusion is possible, these will be disambiguated by -calling them "Ibrowse menus" or "node menu".) - - After the start of the menu, each line that starts with a "*" -identifies one subtopic. The line will usually contain a brief name -for the subtopic (followed by a ":"), the name of the node that talks -about that subtopic, and optionally some further description of the -subtopic. Lines in the menu that don't start with a "*" have no -special meaning - they are only for the human reader's benefit and do -not define additional subtopics. Here is an example: -* Foo: FOO's Node This tells about FOO -The subtopic name is Foo, and the node describing it is "FOO's Node". -The rest of the line is just for the reader's Information. -[[ But this line is not a real menu item, simply because there is -no line above it which starts with "* Menu:".]] - - When you use a menu to go to another node (in a way that will be -described soon), what you specify is the subtopic name, the first -thing in the menu line. Ibrowse uses it to find the menu line, extracts -the node name from it, and goes to that node. The reason that there -is both a subtopic name and a node name is that the node name must be -meaningful to the computer and may therefore have to be ugly looking. -The subtopic name can be chosen just to be convenient for the user to -specify. Often the node name is convenient for the user to specify -and so both it and the subtopic name are the same. There is an -abbreviation for this: -* Foo:: This tells about FOO -This means that the subtopic name and node name are the same; they are -both "Foo". - ->> Now use Spaces to find the menu in this node, then come back to -the front with a "b". As you see, a menu is actually visible -in its node. If you can't find a menu in a node by looking at it, -then the node doesn't have a menu and the "m" command is not available. - - (Actually, a quicker way to see if there is a node menu, is to look -for an Ibrowse menu at the top named "Menu".) - - The command to go to one of the subnodes is "m" - but DON'T DO IT -YET! Before you use "m", you must understand the difference between -commands and arguments. So far, you have learned several commands -that do not need arguments. When you type one, Ibrowse processes it and -is instantly ready for another command. The "m" command is different: -it is incomplete without the NAME OF THE SUBTOPIC. Once you have -typed "m", Ibrowse wants to read the subtopic name. - - Thanks to modern user interface technology, this will be obvious: -you are prompted for the subtopic name in a dialog box. When you are -finished typing the name, press Return or click the OK button. You can -cancel the dialog box by clicking the Cancel button. The first subtopic -is provided as a default choice, so if you want to go there, you can -just press Return. - - You can abbreviate the subtopic name. If the abbreviation is not -unique, the first matching subtopic is chosen. Some menus will put -the shortest possible abbreviation for each subtopic name in capital -letters, so you can see how much you need to type. It does not -matter whether you use upper case or lower case when you type the -subtopic. You should not put any spaces at the end, or inside of the -item name, except for one space where a space appears in the item in -the menu. - - Here is a menu to give you a chance to practice. - -* Menu: The menu starts here. - -This menu gives you three ways of going to one place, Help-FOO. - -* Foo: Help-FOO A node you can visit for fun -* Bar: Help-FOO Strange! two ways to get to the same place. -* Help-FOO:: And yet another! - ->> Now type just an "m" and see what happens. (Read ahead before ->> trying this out, as the dialog box will probably cover these ->> instructions!) - - Now you are "inside" an "m" command. Commands can't be used now; -the next thing you will type must be the name of a subtopic. - - You can change your mind about doing the "m" by clicking the Cancel -button. ->> Try that now; notice the dialog box disappear. ->> Then type another "m". - ->> Now type "BAR", the item name. Don't type Return yet. - - While you are typing the item name, you can use the Backspace -key to cancel one character at a time if you make a mistake. ->> Type one to cancel the "R". You could type another "R" to -replace it. You don't have to, since "BA" is a valid abbreviation. ->> Now you are ready to go. Type a Return. - - After visiting Help-FOO, you should return here (it will tell how). - ->> Type "n" to see more commands. - -File: ibrowse Node: Help-FOO Up: Help-M - -The "u" command - - Congratulations! This is the node Help-FOO. Unlike the other -nodes you have seen, this one has an "Up": "Help-M", the node you -just came from via the "m" command. This is the usual convention-- -the nodes you reach from a menu have Ups that lead back to the menu. -Menus move Down in the tree, and Up moves Up. Previous, on the other -hand, is usually used to "stay on the same level but go backwards". - - You can go back to the node Help-M by typing the command -"u" for "Up". That will put you at the FRONT of the node - to get -back to where you were reading you will have to type some Spaces. - ->> Now type "u" to move back up to Help-M. - -File: ibrowse Node: Help-Adv Next: Help-Q Previous: Help-M - -Some advanced Ibrowse commands - - The course is almost over, so please stick with it to the end. - - If you have been moving around to different nodes and wish to -retrace your steps, the "l" command ("l" for "last") will do that, one -node at a time. If you have been following directions, an "l" command -now will get you back to Help-M. Another "l" command would undo the "u" -and get you back to Help-FOO. Another "l" would undo the M and get you -back to Help-M. - ->> Try typing three "l"'s, pausing in between to see what each "l" does. -Then follow directions again and you will end up back here. - - Note the difference between "l" and "p": "l" moves to where YOU -last were, whereas "p" always moves to the node which the header says -is the "Previous" node (from this node, to Help-M). - - The "d" command gets you instantly to the Directory node. -This node, which is the first one you saw when you entered Ibrowse, -has a menu which leads (directly, or indirectly through other menus), -to all the nodes that exist. - ->> Try doing a "d", then do an "l" to return here (yes, DO return). - - Sometimes, in Ibrowse documentation, you will see a cross reference. -Cross references look like this: *Note Cross: Help-Cross. That is a -real, live cross reference which is named "Cross" and points at the -node named "Help-Cross". - - If you wish to follow a cross reference, you must use the "f" -command. The "f" prompts for the cross reference name (in this case, -"Cross") with a dialog box. - ->> Type "f", followed by "Cross", and a Return. - - The "f" command allows abbreviations just like "m". - - To get a list of all the cross references in the current node, -look in the Ibrowse menu at the top labeled "Footnotes". This menu is -only present if there are cross references in the current node, and -can be used to directly follow a cross reference, just like the "Menu" -menu is another way to choose an item of the node's menu. - ->> Now type "n" to see the last node of the course. - -File: ibrowse Node: Help-Cross - - This is the node reached by the cross reference named "Cross". - - While this node is specifically intended to be reached by a cross -reference, most cross references lead to nodes that "belong" someplace -else far away in the structure of Ibrowse. So you can't expect the -footnote to have a Next, Previous or Up pointing back to where you -came from. In general, the "l" (el) command is the only way to get -back there. - ->> Type "l" to return to the node where the cross reference was. - -File: ibrowse Node: Help-Q Previous: Help-Adv Up: Top - - To get out of Ibrowse, type "q" for "Quit". All Ibrowse windows -will be closed (on UNIX, only those managed by the same process). -To close just one window, use the standard method of closing windows -on your system; you can also use "w". - - This is the end of the course on using Ibrowse. There are some other -commands that are not essential or meant for experienced users; they -are useful, and you can find them by looking in the directory for -documentation on Ibrowse. Finding them will be a good exercise in using -Ibrowse in the usual manner. - ->> Close this window and find back the window where you typed "h" - to enter this tutorial. - Then type "d" to go to the Ibrowse directory node if necessary, - and choose the "Ibrowse" menu item, to get to the node about - Ibrowse and see what other help is available. - -File: ibrowse, Node: Expert, Up: Top, Previous: Top, Next: Add - -Some Advanced Ibrowse Commands ("c", "k", "g", "s", "1" - "9", arrows). - -The "c" command lets you copy text from the window to the clipboard. -You must first select the text to be copied with the mouse. - -The "k" command means "klone" (we are running out of letters now...). -It creates a new Ibrowse window, showing the same node as the current. -You can then make an excursion in the new window to different nodes or -files, while the old window keeps showing the original node. Each -window has its own history for use by the "l" command. - -If you know a node's name, you can go there with the "g" command. -This prompts for a node name with a dialog box. Entering, "Top" -would go to the node called Top in this file (its directory node). -Pressing "g" again and entering "Expert" would come back here. - -Unlike "m", "g" does not allow the use of abbreviations. - -To go to a node in another file, you can include the filename in the -node name by putting it at the front, in parentheses. Thus, -"(dir)Top" would go to the Ibrowse Directory node, which is -node Top in the file dir. - -The node name "*" specifies the whole file. So you can look at all -of the current file by typing "*" or all of any other file -with "(FILENAME)*". - -File names are converted to lower case before they are tried; this -is necessary to be compatible with Emacs Info. (File names are -generally relative to the Info directory, but needn't be.) - -The "s" command allows you to search a whole file for a regular -expression. Unlike the corresponding Emacs Info command, it will -not search beyond the end of the current node. - -Regular expressions are like in UNIX egrep; if you don't know what -regular expressions are, limit your search strings to letters, digits -and spaces. Searches in Ibrowse are case-sensitive; searching for -"foo" will not find "Foo" or "FOO"! - -A description of regular expressions as they occur in Emacs is -available. (*Note Emacs Regular Expressions: (regex)syntax.) -Ibrowse regular expressions are slightly different: the meaning -of \( \| \) is swapped with that of ( | ), and there are no -escapes to handle "words" specially. - -Searching starts after the current focus position. The "B" command -resets the focus to the beginning of the file, but space and backspace -leave it unchanged (so they may render the focus invisible). - -If you grudge the system each character of type-in it requires, -you might like to use the commands "1", "2", "3", through "9". -They are short for the first nine entries of the node menu. - -The left, right and up arrow keys are duplicates of "p", "n" and "u". - -The down arrow key, as well as the Return key, goes to the first item -of the node's menu if there is one, else it executes "n". This is a -quick way to visit all nodes in a tree in pre-order: use Return to go -down and right as far as possible, then use "u" and "n" to go right -at the next higher level. - -File: ibrowse, Node: Add, Up: Top, Previous: Expert, Next: Menus - -To add a new topic to the list in the directory, you must - 1) enter the Emacs text editor. *Note Emacs: (emacs). - 2) create a node, in some file, to document that topic. - 3) put that topic in the menu in the directory. *Note Menu: Menus. - - The new node can live in an existing documentation file, or in a new -one. It must have a ^_ character before it (invisible to the user; -this node has one but you can't see it), and it ends with either a ^_, -or the end of file. A nice way to make a node boundary be a -page boundary as well is to put a ^L RIGHT AFTER the ^_. - - The ^_ starting a node must be followed by a newline or a ^L newline, -after which comes the node's header line. The header line must give -the node's name (by which Ibrowse will find it), and state the names of -the Next, Previous, and Up nodes (if there are any). As you can see, -this node's Up node is the node Top, which points at all the -documentation for Ibrowse. The Next node is "Menus". - - The keywords "Node", "Previous", "Up" and "Next", may appear in -any order, anywhere in the header line, but the recommended order is -the one in this sentence. Each keyword must be followed by a colon, -spaces and tabs, and then the appropriate name. The name may be -terminated with a tab, a comma, or a newline. A space does not end -it; node names may contain spaces. The case of letters in the names -is insignificant. "Previous" can be abbreviated to "Prev". - - A node name has two forms. A node in the current file is named by -what appears after the "Node: " in that node's first line. For -example, this node's name is "Add". A node in another file is named -by "(FILENAME)NODE-WITHIN-FILE", as in "(ibrowse)Add" for this node. -If the file name is relative, it is taken starting from the standard -Info file directory of your site. The name "(FILENAME)Top" can be -abbreviated to just "(FILENAME)". By convention, the name "Top" is -used for the "highest" node in any single file - the node whose "Up" -points out of the file. The Directory node is "(dir)". The Top node -of a document file listed in the Directory should have an "Up: (dir)" -in it. - - The node name "*" is special: it refers to the entire file. Thus, -g* will show you the whole current file. The use of the node * is to -make it possible to make old-fashioned, unstructured files into nodes -of the tree. Footnotes and node menus appearing in a file are disabled -when it is viewed in this way. - - The "Node:" name, in which a node states its own name, must not -contain a filename, since Ibrowse when searching for a node does not -expect one to be there. The Next, Previous and Up names may contain -them. In this node, since the Up node is in the same file, it was not -necessary to use one. - - Note that the nodes in this file have a File name in the header -line. The File names are ignored by Ibrowse, but they serve as -comments to help identify the node for the user. - -File: ibrowse, Node: Menus, Previous: Add, Up: Top, Next: Cross-refs - -How to Create Menus: - - Any node in the Ibrowse hierarchy may have a MENU--a list of subnodes. -The "m" command searches the current node's menu for the topic which it -reads from the terminal. - - A menu begins with a line starting with "* Menu:". The rest of the -line is a comment. After the starting line, every line that begins -with a "* " lists a single topic. The name of the topic--the arg -that the user must give to the "m" command to select this topic-- -comes right after the star and space, and is followed by -a colon, spaces and tabs, and the name of the node which discusses -that topic. The node name, like node names following Next, -Previous and Up, may be terminated with a tab, comma, or newline; -it may also be terminated with a period. - - If the node name and topic name are the same, than rather than -giving the name twice, the abbreviation "* NAME::" may be used -(and should be used, whenever possible, as it reduces the visual -clutter in the menu). - - It is considerate to choose the topic names so that they differ -from each other very near the beginning--this allows the user to type -short abbreviations. In a long menu, it is a good idea to capitalize -the beginning of each item name which is the minimum acceptable -abbreviation for it (a long menu is more than 5 or so entries). - - The node's listed in a node's menu are called its "subnodes", and -it is their "superior". They should each have an "Up:" pointing at -the superior. It is often useful to arrange all or most of the -subnodes in a sequence of Next's/Previous's so that someone who -wants to see them all need not keep revisiting the Menu. - - The Info Directory is simply the menu of the node "(dir)Top"--that -is, node Top in file .../info/dir. You can put new entries in that -menu just like any other menu. The Info Directory is NOT the same as -the file directory called "info". It happens that many of Ibrowse's -files live on that file directory, but they don't have to; and files -on that directory are not automatically listed in the Info Directory -node. - - The Ibrowse program uses a second directory called .../ibrowse, -which contains versions of the "dir" and "info" files adapted to -Ibrowse (the latter renamed to "ibrowse", obviously). It searches -any file first in the "ibrowse", then in the "info" directory. -(Actually, the search path is configurable.) - - Also, although the Info node graph is claimed to be a "hierarchy", -in fact it can be ANY directed graph. Shared structures and pointer -cycles are perfectly possible, and can be used if they are -appropriate to the meaning to be expressed. There is no need for all -the nodes in a file to form a connected structure. In fact, this -file has two connected components. You are in one of them, which is -under the node Top; the other contains the node Help which the "h" -command goes to. In fact, since there is no garbage collector, -nothing terrible happens if a substructure is not pointed to, but -such a substructure will be rather useless since nobody will ever -find out that it exists. - -File: ibrowse, Node: Cross-refs, Previous: Menus, Up: Top, Next: Tags - -Creating Cross References: - - A cross reference can be placed anywhere in the text, unlike a menu -item which must go at the front of a line. A cross reference looks -like a menu item except that it has "*note" instead of "*". It CANNOT -be terminated by a ")", because ")"'s are so often part of node names. -If you wish to enclose a cross reference in parentheses, terminate it -with a period first. Here are two examples of cross references pointers: - - *Note details: commands. (See *note 3: Full Proof.) - -They are just examples. The places they "lead to" don't really exist! - -File: ibrowse, Node: Tags, Previous: Cross-refs, Up: Top, Next: Checking - -Tag Tables for Info Files: - - You can speed up the access to nodes of a large Info file by giving -it a tag table. Unlike the tag table for a program, the tag table for -an Info file lives inside the file itself and will automatically be -used whenever Ibrowse reads in the file. - - To make a tag table, go to a node in the file using Emacs Info and type -M-x Info-tagify. Then you must use C-x C-s to save the file. - - Once the Info file has a tag table, you must make certain it is up -to date. If, as a result of deletion of text, any node moves back -more than a thousand characters in the file from the position -recorded in the tag table, Ibrowse will no longer be able to find that -node. To update the tag table, use the Info-tagify command again. - - An Info file tag table appears at the end of the file and looks like -this: - -^_^L -Tag Table: -File: ibrowse, Node: Cross-refs21419 -File: ibrowse, Node: Tags22145 -^_ -End Tag Table - -Note that it contains one line per node, and this line contains -the beginning of the node's header (ending just after the node name), -a rubout (DEL) character, and the character position in the file of the -beginning of the node. The words "Tag Table" may occur in lower case -as well. - -It is also possible for an extra level of indirection to be present. -In this case, the first line of the Tag table contains the string -"(Indirect)", and preceding the tag table is another "pseudo node" -whose header reads "Indirect:". Each following line has the form -"filename: offset", meaning that nodes at that offset or larger (but -less than the offset in the next line) really occur in the file named -here, and that the file's offset should be subtracted from the node's -offset. (Indirect tables are created by texinfo for large files. -*Note Texinfo: (texinfo). *Note Splitting files: (texinfo)Splitting.) - -File: ibrowse, Node: Checking, Previous: Tags, Up: Top - -Checking an Info File: - - When creating an Info file, it is easy to forget the name of a node -when you are making a pointer to it from another node. If you put in -the wrong name for a node, this will not be detected until someone -tries to go through the pointer using Ibrowse. Verification of the Info -file is an automatic process which checks all pointers to nodes and -reports any pointers which are invalid. Every Next, Previous, and Up -is checked, as is every menu item and every cross reference. In addition, -any Next which doesn't have a Previous pointing back is reported. -Only pointers within the file are checked, because checking pointers -to other files would be terribly slow. But those are usually few. - - To check an Info file, do M-x Info-validate while looking at any -node of the file with Emacs Info. - -Tag table: -Node: Top117 -Node: Summary952 -Node: Help-Small-Screen997 -Node: Help2628 -Node: Help-P3588 -Node: Help-Page4348 -Node: Help-M7763 -Node: Help-FOO13183 -Node: Help-Adv13887 -Node: Help-Cross15923 -Node: Help-Q16443 -Node: Expert17326 -Node: Add20280 -Node: Menus23273 -Node: Cross-refs26394 -Node: Tags27050 -Node: Checking28966 - -End tag table diff --git a/Demo/stdwin/ibrowse/ibrowse.py b/Demo/stdwin/ibrowse/ibrowse.py deleted file mode 100755 index 41574adba7..0000000000 --- a/Demo/stdwin/ibrowse/ibrowse.py +++ /dev/null @@ -1,617 +0,0 @@ -# Browser for "Info files" as used by the Emacs documentation system. -# -# Now you can read Info files even if you can't spare the memory, time or -# disk space to run Emacs. (I have used this extensively on a Macintosh -# with 1 Megabyte main memory and a 20 Meg harddisk.) -# -# You can give this to someone with great fear of complex computer -# systems, as long as they can use a mouse. -# -# Another reason to use this is to encourage the use of Info for on-line -# documentation of software that is not related to Emacs or GNU. -# (In particular, I plan to redo the Python and STDWIN documentation -# in texinfo.) - - -# NB: this is not a self-executing script. You must startup Python, -# import ibrowse, and call ibrowse.main(). On UNIX, the script 'ib' -# runs the browser. - - -# Configuration: -# -# - The pathname of the directory (or directories) containing -# the standard Info files should be set by editing the -# value assigned to INFOPATH in module ifile.py. -# -# - The default font should be set by editing the value of FONT -# in this module (ibrowse.py). -# -# - For fastest I/O, you may look at BLOCKSIZE and a few other -# constants in ifile.py. - - -# This is a fairly large Python program, split in the following modules: -# -# ibrowse.py Main program and user interface. -# This is the only module that imports stdwin. -# -# ifile.py This module knows about the format of Info files. -# It is imported by all of the others. -# -# itags.py This module knows how to read prebuilt tag tables, -# including indirect ones used by large texinfo files. -# -# icache.py Caches tag tables and visited nodes. - - -# XXX There should really be a different tutorial, as the user interface -# XXX differs considerably from Emacs... - - -import sys -import regexp -import stdwin -from stdwinevents import * -import string -from ifile import NoSuchFile, NoSuchNode -import icache - - -# Default font. -# This should be an acceptable argument for stdwin.setfont(); -# on the Mac, this can be a pair (fontname, pointsize), while -# under X11 it should be a standard X11 font name. -# For best results, use a constant width font like Courier; -# many Info files contain tabs that don't align with other text -# unless all characters have the same width. -# -#FONT = ('Monaco', 9) # Mac -FONT = '-schumacher-clean-medium-r-normal--14-140-75-75-c-70-iso8859-1' # X11 - - -# Try not to destroy the list of windows when reload() is used. -# This is useful during debugging, and harmless in production... -# -try: - dummy = windows - del dummy -except NameError: - windows = [] - - -# Default main function -- start at the '(dir)' node. -# -def main(): - start('(dir)') - - -# Start at an arbitrary node. -# The default file is 'ibrowse'. -# -def start(ref): - stdwin.setdefscrollbars(0, 1) - stdwin.setfont(FONT) - stdwin.setdefwinsize(76*stdwin.textwidth('x'), 22*stdwin.lineheight()) - makewindow('ibrowse', ref) - mainloop() - - -# Open a new browser window. -# Arguments specify the default file and a node reference -# (if the node reference specifies a file, the default file is ignored). -# -def makewindow(file, ref): - win = stdwin.open('Info file Browser, by Guido van Rossum') - win.mainmenu = makemainmenu(win) - win.navimenu = makenavimenu(win) - win.textobj = win.textcreate((0, 0), win.getwinsize()) - win.file = file - win.node = '' - win.last = [] - win.pat = '' - win.dispatch = idispatch - win.nodemenu = None - win.footmenu = None - windows.append(win) - imove(win, ref) - -# Create the 'Ibrowse' menu for a new browser window. -# -def makemainmenu(win): - mp = win.menucreate('Ibrowse') - mp.callback = [] - additem(mp, 'New window (clone)', 'K', iclone) - additem(mp, 'Help (tutorial)', 'H', itutor) - additem(mp, 'Command summary', '?', isummary) - additem(mp, 'Close this window', 'W', iclose) - additem(mp, '', '', None) - additem(mp, 'Copy to clipboard', 'C', icopy) - additem(mp, '', '', None) - additem(mp, 'Search regexp...', 'S', isearch) - additem(mp, '', '', None) - additem(mp, 'Reset node cache', '', iresetnodecache) - additem(mp, 'Reset entire cache', '', iresetcache) - additem(mp, '', '', None) - additem(mp, 'Quit', 'Q', iquit) - return mp - -# Create the 'Navigation' menu for a new browser window. -# -def makenavimenu(win): - mp = win.menucreate('Navigation') - mp.callback = [] - additem(mp, 'Menu item...', 'M', imenu) - additem(mp, 'Follow reference...', 'F', ifollow) - additem(mp, 'Go to node...', 'G', igoto) - additem(mp, '', '', None) - additem(mp, 'Next node in tree', 'N', inext) - additem(mp, 'Previous node in tree', 'P', iprev) - additem(mp, 'Up in tree', 'U', iup) - additem(mp, 'Last visited node', 'L', ilast) - additem(mp, 'Top of tree', 'T', itop) - additem(mp, 'Directory node', 'D', idir) - return mp - -# Add an item to a menu, and a function to its list of callbacks. -# (Specifying all in one call is the only way to keep the menu -# and the list of callbacks in synchrony.) -# -def additem(mp, text, shortcut, function): - if shortcut: - mp.additem(text, shortcut) - else: - mp.additem(text) - mp.callback.append(function) - - -# Stdwin event processing main loop. -# Return when there are no windows left. -# Note that windows not in the windows list don't get their events. -# -def mainloop(): - while windows: - event = stdwin.getevent() - if event[1] in windows: - try: - event[1].dispatch(event) - except KeyboardInterrupt: - # The user can type Control-C (or whatever) - # to leave the browser without closing - # the window. Mainly useful for - # debugging. - break - except: - # During debugging, it was annoying if - # every mistake in a callback caused the - # whole browser to crash, hence this - # handler. In a production version - # it may be better to disable this. - # - msg = sys.exc_type - if sys.exc_value: - val = sys.exc_value - if type(val) <> type(''): - val = `val` - msg = msg + ': ' + val - msg = 'Oops, an exception occurred: ' + msg - event = None - stdwin.message(msg) - event = None - - -# Handle one event. The window is taken from the event's window item. -# This function is placed as a method (named 'dispatch') on the window, -# so the main loop will be able to handle windows of a different kind -# as well, as long as they are all placed in the list of windows. -# -def idispatch(event): - type, win, detail = event - if type == WE_CHAR: - if not keybindings.has_key(detail): - detail = string.lower(detail) - if keybindings.has_key(detail): - keybindings[detail](win) - return - if detail in '0123456789': - i = eval(detail) - 1 - if i < 0: i = len(win.menu) + i - if 0 <= i < len(win.menu): - topic, ref = win.menu[i] - imove(win, ref) - return - stdwin.fleep() - return - if type == WE_COMMAND: - if detail == WC_LEFT: - iprev(win) - elif detail == WC_RIGHT: - inext(win) - elif detail == WC_UP: - iup(win) - elif detail == WC_DOWN: - idown(win) - elif detail == WC_BACKSPACE: - ibackward(win) - elif detail == WC_RETURN: - idown(win) - else: - stdwin.fleep() - return - if type == WE_MENU: - mp, item = detail - if mp == None: - pass # A THINK C console menu was selected - elif mp in (win.mainmenu, win.navimenu): - mp.callback[item](win) - elif mp == win.nodemenu: - topic, ref = win.menu[item] - imove(win, ref) - elif mp == win.footmenu: - topic, ref = win.footnotes[item] - imove(win, ref) - return - if type == WE_SIZE: - win.textobj.move((0, 0), win.getwinsize()) - (left, top), (right, bottom) = win.textobj.getrect() - win.setdocsize(0, bottom) - return - if type == WE_CLOSE: - iclose(win) - return - if not win.textobj.event(event): - pass - - -# Paging callbacks - -def ibeginning(win): - win.setorigin(0, 0) - win.textobj.setfocus(0, 0) # To restart searches - -def iforward(win): - lh = stdwin.lineheight() # XXX Should really use the window's... - h, v = win.getorigin() - docwidth, docheight = win.getdocsize() - width, height = win.getwinsize() - if v + height >= docheight: - stdwin.fleep() - return - increment = max(lh, ((height - 2*lh) / lh) * lh) - v = v + increment - win.setorigin(h, v) - -def ibackward(win): - lh = stdwin.lineheight() # XXX Should really use the window's... - h, v = win.getorigin() - if v <= 0: - stdwin.fleep() - return - width, height = win.getwinsize() - increment = max(lh, ((height - 2*lh) / lh) * lh) - v = max(0, v - increment) - win.setorigin(h, v) - - -# Ibrowse menu callbacks - -def iclone(win): - stdwin.setdefwinsize(win.getwinsize()) - makewindow(win.file, win.node) - -def itutor(win): - # The course looks best at 76x22... - stdwin.setdefwinsize(76*stdwin.textwidth('x'), 22*stdwin.lineheight()) - makewindow('ibrowse', 'Help') - -def isummary(win): - stdwin.setdefwinsize(76*stdwin.textwidth('x'), 22*stdwin.lineheight()) - makewindow('ibrowse', 'Summary') - -def iclose(win): - # - # Remove the window from the windows list so the mainloop - # will notice if all windows are gone. - # Delete the textobj since it constitutes a circular reference - # to the window which would prevent it from being closed. - # (Deletion is done by assigning None to avoid crashes - # when closing a half-initialized window.) - # - if win in windows: - windows.remove(win) - win.textobj = None - -def icopy(win): - focustext = win.textobj.getfocustext() - if not focustext: - stdwin.fleep() - else: - stdwin.rotatecutbuffers(1) - stdwin.setcutbuffer(0, focustext) - # XXX Should also set the primary selection... - -def isearch(win): - try: - pat = stdwin.askstr('Search pattern:', win.pat) - except KeyboardInterrupt: - return - if not pat: - pat = win.pat - if not pat: - stdwin.message('No previous pattern') - return - try: - cpat = regexp.compile(pat) - except regexp.error, msg: - stdwin.message('Bad pattern: ' + msg) - return - win.pat = pat - f1, f2 = win.textobj.getfocus() - text = win.text - match = cpat.match(text, f2) - if not match: - stdwin.fleep() - return - a, b = match[0] - win.textobj.setfocus(a, b) - - -def iresetnodecache(win): - icache.resetnodecache() - -def iresetcache(win): - icache.resetcache() - -def iquit(win): - for win in windows[:]: - iclose(win) - - -# Navigation menu callbacks - -def imenu(win): - ichoice(win, 'Menu item (abbreviated):', win.menu, whichmenuitem(win)) - -def ifollow(win): - ichoice(win, 'Follow reference named (abbreviated):', \ - win.footnotes, whichfootnote(win)) - -def igoto(win): - try: - choice = stdwin.askstr('Go to node (full name):', '') - except KeyboardInterrupt: - return - if not choice: - stdwin.message('Sorry, Go to has no default') - return - imove(win, choice) - -def inext(win): - prev, next, up = win.header - if next: - imove(win, next) - else: - stdwin.fleep() - -def iprev(win): - prev, next, up = win.header - if prev: - imove(win, prev) - else: - stdwin.fleep() - -def iup(win): - prev, next, up = win.header - if up: - imove(win, up) - else: - stdwin.fleep() - -def ilast(win): - if not win.last: - stdwin.fleep() - else: - i = len(win.last)-1 - lastnode, lastfocus = win.last[i] - imove(win, lastnode) - if len(win.last) > i+1: - # The move succeeded -- restore the focus - win.textobj.setfocus(lastfocus) - # Delete the stack top even if the move failed, - # else the whole stack would remain unreachable - del win.last[i:] # Delete the entry pushed by imove as well! - -def itop(win): - imove(win, '') - -def idir(win): - imove(win, '(dir)') - - -# Special and generic callbacks - -def idown(win): - if win.menu: - default = whichmenuitem(win) - for topic, ref in win.menu: - if default == topic: - break - else: - topic, ref = win.menu[0] - imove(win, ref) - else: - inext(win) - -def ichoice(win, prompt, list, default): - if not list: - stdwin.fleep() - return - if not default: - topic, ref = list[0] - default = topic - try: - choice = stdwin.askstr(prompt, default) - except KeyboardInterrupt: - return - if not choice: - return - choice = string.lower(choice) - n = len(choice) - for topic, ref in list: - topic = string.lower(topic) - if topic[:n] == choice: - imove(win, ref) - return - stdwin.message('Sorry, no topic matches ' + `choice`) - - -# Follow a reference, in the same window. -# -def imove(win, ref): - savetitle = win.gettitle() - win.settitle('Looking for ' + ref + '...') - # - try: - file, node, header, menu, footnotes, text = \ - icache.get_node(win.file, ref) - except NoSuchFile, file: - win.settitle(savetitle) - stdwin.message(\ - 'Sorry, I can\'t find a file named ' + `file` + '.') - return - except NoSuchNode, node: - win.settitle(savetitle) - stdwin.message(\ - 'Sorry, I can\'t find a node named ' + `node` + '.') - return - # - win.settitle('Found (' + file + ')' + node + '...') - # - if win.file and win.node: - lastnode = '(' + win.file + ')' + win.node - win.last.append(lastnode, win.textobj.getfocus()) - win.file = file - win.node = node - win.header = header - win.menu = menu - win.footnotes = footnotes - win.text = text - # - win.setorigin(0, 0) # Scroll to the beginnning - win.textobj.settext(text) - win.textobj.setfocus(0, 0) - (left, top), (right, bottom) = win.textobj.getrect() - win.setdocsize(0, bottom) - # - if win.footmenu: win.footmenu.close() - if win.nodemenu: win.nodemenu.close() - win.footmenu = None - win.nodemenu = None - # - win.menu = menu - if menu: - win.nodemenu = win.menucreate('Menu') - digit = 1 - for topic, ref in menu: - if digit < 10: - win.nodemenu.additem(topic, `digit`) - else: - win.nodemenu.additem(topic) - digit = digit + 1 - # - win.footnotes = footnotes - if footnotes: - win.footmenu = win.menucreate('Footnotes') - for topic, ref in footnotes: - win.footmenu.additem(topic) - # - win.settitle('(' + win.file + ')' + win.node) - - -# Find menu item at focus -# -findmenu = regexp.compile('^\* [mM]enu:').match -findmenuitem = regexp.compile( \ - '^\* ([^:]+):[ \t]*(:|\([^\t]*\)[^\t,\n.]*|[^:(][^\t,\n.]*)').match -# -def whichmenuitem(win): - if not win.menu: - return '' - match = findmenu(win.text) - if not match: - return '' - a, b = match[0] - i = b - f1, f2 = win.textobj.getfocus() - lastmatch = '' - while i < len(win.text): - match = findmenuitem(win.text, i) - if not match: - break - (a, b), (a1, b1), (a2, b2) = match - if a > f1: - break - lastmatch = win.text[a1:b1] - i = b - return lastmatch - - -# Find footnote at focus -# -findfootnote = \ - regexp.compile('\*[nN]ote ([^:]+):[ \t]*(:|[^:][^\t,\n.]*)').match -# -def whichfootnote(win): - if not win.footnotes: - return '' - i = 0 - f1, f2 = win.textobj.getfocus() - lastmatch = '' - while i < len(win.text): - match = findfootnote(win.text, i) - if not match: - break - (a, b), (a1, b1), (a2, b2) = match - if a > f1: - break - lastmatch = win.text[a1:b1] - i = b - return lastmatch - - -# Now all the "methods" are defined, we can initialize the table -# of key bindings. -# -keybindings = {} - -# Window commands - -keybindings['k'] = iclone -keybindings['h'] = itutor -keybindings['?'] = isummary -keybindings['w'] = iclose - -keybindings['c'] = icopy - -keybindings['s'] = isearch - -keybindings['q'] = iquit - -# Navigation commands - -keybindings['m'] = imenu -keybindings['f'] = ifollow -keybindings['g'] = igoto - -keybindings['n'] = inext -keybindings['p'] = iprev -keybindings['u'] = iup -keybindings['l'] = ilast -keybindings['d'] = idir -keybindings['t'] = itop - -# Paging commands - -keybindings['b'] = ibeginning -keybindings['.'] = ibeginning -keybindings[' '] = iforward diff --git a/Demo/stdwin/ibrowse/icache.py b/Demo/stdwin/ibrowse/icache.py deleted file mode 100755 index 0629bf9f61..0000000000 --- a/Demo/stdwin/ibrowse/icache.py +++ /dev/null @@ -1,74 +0,0 @@ -# Cache management for info file processing. -# The function get_node() is the standard interface; -# its signature is the same as ifile.get_node() but it uses -# the cache and supports indirect tag tables. - - -import string -import ifile -from ifile import NoSuchNode, NoSuchFile -import itags - - -# Special hack to save the cache when using reload(). -# This can just be "cache = {}" in a production version. -# -try: - dummy = cache - del dummy -except NameError: - cache = {} - - -# Clear the entire cache. -# -def resetcache(): - for key in cache.keys(): - del cache[key] - - -# Clear the node info from the cache (the most voluminous data). -# -def resetnodecache(): - for key in cache.keys(): - tags, nodes = cache[key] - cache[key] = tags, {} - - -# Get a node. -# -def get_node(curfile, ref): - file, node = ifile.parse_ref(curfile, ref) - file = string.lower(file) - node = string.lower(node) - if node == '*': - # Don't cache whole file references; - # reading the data is faster than displaying it anyway. - return ifile.get_whole_file(file) # May raise NoSuchFile - if not cache.has_key(file): - cache[file] = get_tags(file), {} # May raise NoSuchFile - tags, nodes = cache[file] - if not nodes.has_key(node): - if not tags.has_key(node): - raise NoSuchNode, ref - file1, offset, line = tags[node] - if not file1: - file1 = file - file1, node1, header, menu, footnotes, text = \ - ifile.get_file_node(file1, offset, node) - nodes[node] = file, node1, header, menu, footnotes, text - return nodes[node] - - -# Get the tag table for a file. -# Either construct one or get the one found in the file. -# Raise NoSuchFile if the file isn't found. -# -def get_tags(file): - f = ifile.try_open(file) # May raise NoSuchFile - tags = itags.get_tags(f) - if not tags: - ###print 'Scanning file...' - f.seek(0) - tags = ifile.make_tags(f) - return tags diff --git a/Demo/stdwin/ibrowse/ifile.py b/Demo/stdwin/ibrowse/ifile.py deleted file mode 100755 index 1ea880ea27..0000000000 --- a/Demo/stdwin/ibrowse/ifile.py +++ /dev/null @@ -1,328 +0,0 @@ -# Tools for info file processing. - -# XXX Need to be more careful with reading ahead searching for nodes. - - -import regexp -import string - - -# Exported exceptions. -# -NoSuchFile = 'no such file' -NoSuchNode = 'no such node' - - -# The search path for info files; this is site-specific. -# Directory names should end in a partname delimiter, -# so they can simply be concatenated to a relative pathname. -# -#INFOPATH = ['', ':Info.Ibrowse:', ':Info:'] # Mac -INFOPATH = ['', '/usr/local/emacs/info/'] # X11 on UNIX - - -# Tunable constants. -# -BLOCKSIZE = 512 # Qty to align reads to, if possible -FUZZ = 2*BLOCKSIZE # Qty to back-up before searching for a node -CHUNKSIZE = 4*BLOCKSIZE # Qty to read at once when reading lots of data - - -# Regular expressions used. -# Note that it is essential that Python leaves unrecognized backslash -# escapes in a string so they can be seen by regexp.compile! -# -findheader = regexp.compile('\037\014?\n(.*\n)').match -findescape = regexp.compile('\037').match -parseheader = regexp.compile('[nN]ode:[ \t]*([^\t,\n]*)').match -findfirstline = regexp.compile('^.*\n').match -findnode = regexp.compile('[nN]ode:[ \t]*([^\t,\n]*)').match -findprev = regexp.compile('[pP]rev[ious]*:[ \t]*([^\t,\n]*)').match -findnext = regexp.compile('[nN]ext:[ \t]*([^\t,\n]*)').match -findup = regexp.compile('[uU]p:[ \t]*([^\t,\n]*)').match -findmenu = regexp.compile('^\* [mM]enu:').match -findmenuitem = regexp.compile( \ - '^\* ([^:]+):[ \t]*(:|\([^\t]*\)[^\t,\n.]*|[^:(][^\t,\n.]*)').match -findfootnote = regexp.compile( \ - '\*[nN]ote ([^:]+):[ \t]*(:|[^:][^\t,\n.]*)').match -parsenoderef = regexp.compile('^\((.*)\)(.*)$').match - - -# Get a node and all information pertaining to it. -# This doesn't work if there is an indirect tag table, -# and in general you are better off using icache.get_node() instead. -# Functions get_whole_file() and get_file_node() provide part -# functionality used by icache. -# Raise NoSuchFile or NoSuchNode as appropriate. -# -def get_node(curfile, ref): - file, node = parse_ref(curfile, ref) - if node == '*': - return get_whole_file(file) - else: - return get_file_node(file, 0, node) -# -def get_whole_file(file): - f = try_open(file) # May raise NoSuchFile - text = f.read() - header, menu, footnotes = ('', '', ''), [], [] - return file, '*', header, menu, footnotes, text -# -def get_file_node(file, offset, node): - f = try_open(file) # May raise NoSuchFile - text = find_node(f, offset, node) # May raise NoSuchNode - node, header, menu, footnotes = analyze_node(text) - return file, node, header, menu, footnotes, text - - -# Parse a node reference into a file (possibly default) and node name. -# Possible reference formats are: "NODE", "(FILE)", "(FILE)NODE". -# Default file is the curfile argument; default node is Top. -# A node value of '*' is a special case: the whole file should -# be interpreted (by the caller!) as a single node. -# -def parse_ref(curfile, ref): - match = parsenoderef(ref) - if not match: - file, node = curfile, ref - else: - (a, b), (a1, b1), (a2, b2) = match - file, node = ref[a1:b1], ref[a2:b2] - if not file: - file = curfile # (Is this necessary?) - if not node: - node = 'Top' - return file, node - - -# Extract node name, links, menu and footnotes from the node text. -# -def analyze_node(text): - # - # Get node name and links from the header line - # - match = findfirstline(text) - if match: - (a, b) = match[0] - line = text[a:b] - else: - line = '' - node = get_it(text, findnode) - prev = get_it(text, findprev) - next = get_it(text, findnext) - up = get_it(text, findup) - # - # Get the menu items, if there is a menu - # - menu = [] - match = findmenu(text) - if match: - (a, b) = match[0] - while 1: - match = findmenuitem(text, b) - if not match: - break - (a, b), (a1, b1), (a2, b2) = match - topic, ref = text[a1:b1], text[a2:b2] - if ref == ':': - ref = topic - menu.append(topic, ref) - # - # Get the footnotes - # - footnotes = [] - b = 0 - while 1: - match = findfootnote(text, b) - if not match: - break - (a, b), (a1, b1), (a2, b2) = match - topic, ref = text[a1:b1], text[a2:b2] - if ref == ':': - ref = topic - footnotes.append(topic, ref) - # - return node, (prev, next, up), menu, footnotes -# -def get_it(line, matcher): - match = matcher(line) - if not match: - return '' - else: - (a, b), (a1, b1) = match - return line[a1:b1] - - -# Find a node in an open file. -# The offset (from the tags table) is a hint about the node's position. -# Pass zero if there is no tags table. -# Raise NoSuchNode if the node isn't found. -# NB: This seeks around in the file. -# -def find_node(f, offset, node): - node = string.lower(node) # Just to be sure - # - # Position a little before the given offset, - # so we may find the node even if it has moved around - # in the file a little. - # - offset = max(0, ((offset-FUZZ) / BLOCKSIZE) * BLOCKSIZE) - f.seek(offset) - # - # Loop, hunting for a matching node header. - # - while 1: - buf = f.read(CHUNKSIZE) - if not buf: - break - i = 0 - while 1: - match = findheader(buf, i) - if match: - (a,b), (a1,b1) = match - start = a1 - line = buf[a1:b1] - i = b - match = parseheader(line) - if match: - (a,b), (a1,b1) = match - key = string.lower(line[a1:b1]) - if key == node: - # Got it! Now read the rest. - return read_node(f, buf[start:]) - elif findescape(buf, i): - next = f.read(CHUNKSIZE) - if not next: - break - buf = buf + next - else: - break - # - # If we get here, we didn't find it. Too bad. - # - raise NoSuchNode, node - - -# Finish off getting a node (subroutine for find_node()). -# The node begins at the start of buf and may end in buf; -# if it doesn't end there, read additional data from f. -# -def read_node(f, buf): - i = 0 - match = findescape(buf, i) - while not match: - next = f.read(CHUNKSIZE) - if not next: - end = len(buf) - break - i = len(buf) - buf = buf + next - match = findescape(buf, i) - else: - # Got a match - (a, b) = match[0] - end = a - # Strip trailing newlines - while end > 0 and buf[end-1] == '\n': - end = end-1 - buf = buf[:end] - return buf - - -# Read reverse starting at offset until the beginning of a node is found. -# Then return a buffer containing the beginning of the node, -# with f positioned just after the buffer. -# The buffer will contain at least the full header line of the node; -# the caller should finish off with read_node() if it is the right node. -# (It is also possible that the buffer extends beyond the node!) -# Return an empty string if there is no node before the given offset. -# -def backup_node(f, offset): - start = max(0, ((offset-CHUNKSIZE) / BLOCKSIZE) * BLOCKSIZE) - end = offset - while start < end: - f.seek(start) - buf = f.read(end-start) - i = 0 - hit = -1 - while 1: - match = findheader(buf, i) - if match: - (a,b), (a1,b1) = match - hit = a1 - i = b - elif end < offset and findescape(buf, i): - next = f.read(min(offset-end, BLOCKSIZE)) - if not next: - break - buf = buf + next - end = end + len(next) - else: - break - if hit >= 0: - return buf[hit:] - end = start - start = max(0, end - CHUNKSIZE) - return '' - - -# Make a tag table for the given file by scanning the file. -# The file must be open for reading, and positioned at the beginning -# (or wherever the hunt for tags must begin; it is read till the end). -# -def make_tags(f): - tags = {} - while 1: - offset = f.tell() - buf = f.read(CHUNKSIZE) - if not buf: - break - i = 0 - while 1: - match = findheader(buf, i) - if match: - (a,b), (a1,b1) = match - start = offset+a1 - line = buf[a1:b1] - i = b - match = parseheader(line) - if match: - (a,b), (a1,b1) = match - key = string.lower(line[a1:b1]) - if tags.has_key(key): - print 'Duplicate node:', - print key - tags[key] = '', start, line - elif findescape(buf, i): - next = f.read(CHUNKSIZE) - if not next: - break - buf = buf + next - else: - break - return tags - - -# Try to open a file, return a file object if succeeds. -# Raise NoSuchFile if the file can't be opened. -# Should treat absolute pathnames special. -# -def try_open(file): - for dir in INFOPATH: - try: - return open(dir + file, 'r') - except IOError: - pass - raise NoSuchFile, file - - -# A little test for the speed of make_tags(). -# -TESTFILE = 'texinfo-1' -def test_make_tags(): - import time - f = try_open(TESTFILE) - t1 = time.millitimer() - tags = make_tags(f) - t2 = time.millitimer() - print 'Making tag table for', `TESTFILE`, 'took', t2-t1, 'msec.' diff --git a/Demo/stdwin/ibrowse/itags.py b/Demo/stdwin/ibrowse/itags.py deleted file mode 100755 index f30f3fd5a1..0000000000 --- a/Demo/stdwin/ibrowse/itags.py +++ /dev/null @@ -1,127 +0,0 @@ -# Utility module for 'icache.py': interpret tag tables and indirect nodes. - -# (This module is a bit chatty when confronted with the unexpected.) - - -import regexp -import string -import ifile - - -# Get the tag table of an open file, as a dictionary. -# Seeks around in the file; after reading, the position is undefined. -# Return an empty tag table if none is found. -# -def get_tags(f): - # - # First see if the last "node" is the end of tag table marker. - # - f.seek(0, 2) # Seek to EOF - end = f.tell() - buf = ifile.backup_node(f, end) - if not labelmatch(buf, 0, 'end tag table\n'): - return {} # No succes - # - # Next backup to the previous "node" -- the tag table itself. - # - ###print 'Getting prebuilt tag table...' - end = f.tell() - len(buf) - buf = ifile.backup_node(f, end) - label = 'tag table:\n' - if not labelmatch(buf, 0, label): - print 'Weird: end tag table marker but no tag table?' - print 'Node begins:', `buf[:50]` - return {} - # - # Now read the whole tag table. - # - end = f.tell() - len(buf) # Do this first! - buf = ifile.read_node(f, buf) - # - # First check for an indirection table. - # - indirlist = [] - if labelmatch(buf, len(label), '(indirect)\n'): - indirbuf = ifile.backup_node(f, end) - if not labelmatch(indirbuf, 0, 'indirect:\n'): - print 'Weird: promised indirection table not found' - print 'Node begins:', `indirbuf[:50]` - # Carry on. Things probably won't work though. - else: - indirbuf = ifile.read_node(f, indirbuf) - indirlist = parse_indirlist(indirbuf) - # - # Now parse the tag table. - # - findtag = regexp.compile('^(.*[nN]ode:[ \t]*(.*))\177([0-9]+)$').match - i = 0 - tags = {} - while 1: - match = findtag(buf, i) - if not match: - break - (a,b), (a1,b1), (a2,b2), (a3,b3) = match - i = b - line = buf[a1:b1] - node = string.lower(buf[a2:b2]) - offset = eval(buf[a3:b3]) # XXX What if it overflows? - if tags.has_key(node): - print 'Duplicate key in tag table:', `node` - file, offset = map_offset(offset, indirlist) - tags[node] = file, offset, line - # - return tags - - -# Return true if buf[i:] begins with a label, after lower case conversion. -# The label argument must be in lower case. -# -def labelmatch(buf, i, label): - return string.lower(buf[i:i+len(label)]) == label - - -# Parse the indirection list. -# Return a list of (filename, offset) pairs ready for use. -# -def parse_indirlist(buf): - list = [] - findindir = regexp.compile('^(.+):[ \t]*([0-9]+)$').match - i = 0 - while 1: - match = findindir(buf, i) - if not match: - break - (a,b), (a1,b1), (a2,b2) = match - file = buf[a1:b1] - offset = eval(buf[a2:b2]) # XXX What if this gets overflow? - list.append(file, offset) - i = b - return list - - -# Map an offset through the indirection list. -# Return (filename, new_offset). -# If the list is empty, return the given offset and an empty file name. -# -def map_offset(offset, indirlist): - if not indirlist: - return '', offset - # - # XXX This could be done more elegant. - # - filex, offx = indirlist[0] - for i in range(len(indirlist)): - file1, off1 = indirlist[i] - if i+1 >= len(indirlist): - file2, off2 = '', 0x7fffffff - else: - file2, off2 = indirlist[i+1] - if off1 <= offset < off2: - # Add offx+2 to compensate for extra header. - # No idea whether this is always correct. - return file1, offset-off1 + offx+2 - # - # XXX Shouldn't get here. - # - print 'Oops, map_offset fell through' - return '', offset # Not likely to get good results diff --git a/Demo/stdwin/jukebox.py b/Demo/stdwin/jukebox.py deleted file mode 100755 index bc43cb5ae5..0000000000 --- a/Demo/stdwin/jukebox.py +++ /dev/null @@ -1,409 +0,0 @@ -#! /usr/local/bin/python - -# XXX This only works on SGIs running IRIX 4.0 or higher - -# JUKEBOX: browse directories full of sampled sound files. -# -# One or more "list windows" display the files and subdirectories of -# the arguments. Double-clicking on a subdirectory opens a new window -# displaying its contents (and so on recursively). Double clicking -# on a file plays it as a sound file (assuming it is one). -# -# Playing is asynchronous: the application keeps listening for events -# while the sample is playing, so you can cancel playing or start a -# new sample right away. Synchronous playing is available through the -# -s option. -# -# The control window displays a "stop button" that cancel the current -# play request. -# -# Most sound file formats recognized by SOX or SFPLAY are recognized. -# Since conversion is costly, converted files are cached in -# /usr/tmp/@j* until the user quits or changes the sampling rate via -# the Rate menu. - -import commands -import getopt -import os -from stat import * -import rand -import stdwin -from stdwinevents import * -import sys -import tempfile -import sndhdr - -from WindowParent import WindowParent -from Buttons import PushButton - -# Pathnames - -DEF_DB = '/usr/local/sounds' # Default directory of sounds -SOX = '/usr/local/bin/sox' # Sound format conversion program -SFPLAY = '/usr/sbin/sfplay' # Sound playing program - - -# Global variables - -class struct: pass # Class to define featureless structures - -G = struct() # oHlds writable global variables - - -# Main program - -def main(): - G.synchronous = 0 # If set, use synchronous audio.write() - G.debug = 0 # If set, print debug messages - G.busy = 0 # Set while asynchronous playing is active - G.windows = [] # List of open windows, except control - G.mode = '' # File type (default any that sfplay knows) - G.rate = 0 # Sampling rate (default " " " ") - G.tempprefix = tempfile.mktemp() - # - try: - optlist, args = getopt.getopt(sys.argv[1:], 'dr:st:') - except getopt.error, msg: - sys.stdout = sys.stderr - print msg - print 'usage: jukebox [-d] [-s] [-t type] [-r rate]' - print ' -d debugging (-dd event debugging)' - print ' -s synchronous playing' - print ' -t type file type' - print ' -r rate sampling rate' - sys.exit(2) - # - for optname, optarg in optlist: - if optname == '-d': - G.debug = G.debug + 1 - elif optname == '-r': - G.rate = int(eval(optarg)) - elif optname == '-s': - G.synchronous = 1 - elif optname == '-t': - G.mode = optarg - # - if not args: - args = [DEF_DB] - # - G.cw = opencontrolwindow() - for dirname in args: - G.windows.append(openlistwindow(dirname)) - # - # - try: - maineventloop() - finally: - clearcache() - killchild() - -# Entries in Rate menu: -rates = ['default', '7350', \ - '8000', '11025', '16000', '22050', '32000', '41000', '48000'] - -def maineventloop(): - mouse_events = WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP - while G.windows: - try: - type, w, detail = event = stdwin.getevent() - except KeyboardInterrupt: - killchild() - continue - if w == G.cw.win: - if type == WE_CLOSE: - return - if type == WE_TIMER: - checkchild() - if G.busy: - G.cw.win.settimer(1) - elif type == WE_MENU: - menu, item = detail - if menu is G.ratemenu: - clearcache() - if item == 0: - G.rate = 0 - else: - G.rate = eval(rates[item]) - for i in range(len(rates)): - menu.check(i, (i == item)) - else: - G.cw.dispatch(event) - else: - if type == WE_DRAW: - w.drawproc(w, detail) - elif type in mouse_events: - w.mouse(w, type, detail) - elif type == WE_CLOSE: - w.close(w) - del w, event - else: - if G.debug > 1: print type, w, detail - -def checkchild(): - if G.busy: - waitchild(1) - -def killchild(): - if G.busy: - os.kill(G.busy, 9) - waitchild(0) - -def waitchild(options): - pid, sts = os.wait(G.busy, options) - if pid == G.busy: - G.busy = 0 - G.stop.enable(0) - - -# Control window -- to set gain and cancel play operations in progress - -def opencontrolwindow(): - stdwin.setdefscrollbars(0, 0) - cw = WindowParent().create('Jukebox', (0, 0)) - # - stop = PushButton().definetext(cw, ' Stop ') - stop.hook = stop_hook - stop.enable(0) - G.stop = stop - # - cw.realize() - # - G.ratemenu = cw.win.menucreate('Rate') - for r in rates: - G.ratemenu.additem(r) - if G.rate == 0: - G.ratemenu.check(0, 1) - else: - for i in len(range(rates)): - if rates[i] == `G.rate`: - G.ratemenu.check(i, 1) - # - return cw - -def stop_hook(self): - killchild() - - -# List windows -- to display list of files and subdirectories - -def openlistwindow(dirname): - list = os.listdir(dirname) - list.sort() - i = 0 - while i < len(list): - if list[i][0] == '.': - del list[i] - else: - i = i+1 - for i in range(len(list)): - fullname = os.path.join(dirname, list[i]) - if os.path.isdir(fullname): - info = '/' - else: - try: - size = os.stat(fullname)[ST_SIZE] - info = `(size + 1023)/1024` + 'k' - except IOError: - info = '???' - info = '(' + info + ')' - list[i] = list[i], info - width = maxwidth(list) - # width = width + stdwin.textwidth(' ') # XXX X11 stdwin bug workaround - height = len(list) * stdwin.lineheight() - stdwin.setdefwinsize(width, min(height, 500)) - stdwin.setdefscrollbars(0, 1) - w = stdwin.open(dirname) - stdwin.setdefwinsize(0, 0) - w.setdocsize(width, height) - w.drawproc = drawlistwindow - w.mouse = mouselistwindow - w.close = closelistwindow - w.dirname = dirname - w.list = list - w.selected = -1 - return w - -def maxwidth(list): - width = 1 - for name, info in list: - w = stdwin.textwidth(name + ' ' + info) - if w > width: width = w - return width - -def drawlistwindow(w, area): -## (left, top), (right, bottom) = area - d = w.begindrawing() - d.erase((0, 0), (1000, 10000)) - lh = d.lineheight() - h, v = 0, 0 - for name, info in w.list: - if info == '/': - text = name + '/' - else: - text = name + ' ' + info - d.text((h, v), text) - v = v + lh - showselection(w, d) - d.close() - -def hideselection(w, d): - if w.selected >= 0: - invertselection(w, d) - -def showselection(w, d): - if w.selected >= 0: - invertselection(w, d) - -def invertselection(w, d): - lh = d.lineheight() - h1, v1 = p1 = 0, w.selected*lh - h2, v2 = p2 = 1000, v1 + lh - d.invert(p1, p2) - -def mouselistwindow(w, type, detail): - (h, v), clicks, button = detail[:3] - d = w.begindrawing() - lh = d.lineheight() - if 0 <= v < lh*len(w.list): - i = v / lh - else: - i = -1 - if w.selected <> i: - hideselection(w, d) - w.selected = i - showselection(w, d) - d.close() - if type == WE_MOUSE_DOWN and clicks >= 2 and i >= 0: - setcursors('watch') - name, info = w.list[i] - fullname = os.path.join(w.dirname, name) - if info == '/': - if clicks == 2: - G.windows.append(openlistwindow(fullname)) - else: - playfile(fullname) - setcursors('cross') - -def closelistwindow(w): - G.windows.remove(w) - -def setcursors(cursor): - for w in G.windows: - w.setwincursor(cursor) - G.cw.win.setwincursor(cursor) - - -# Playing tools - -cache = {} - -def clearcache(): - for x in cache.keys(): - cmd = 'rm -f ' + cache[x] - if G.debug: print cmd - sts = os.system(cmd) - if sts: - print cmd - print 'Exit status', sts - del cache[x] - -validrates = (8000, 11025, 16000, 22050, 32000, 44100, 48000) - -def playfile(filename): - killchild() - try: - tuple = sndhdr.what(filename) - except IOError, msg: - print 'Can\'t open', filename, msg - stdwin.fleep() - return - raw = 0 - if tuple: - mode, rate = tuple[:2] - if rate == 0: - rate = G.rate - if rate == 0: - rate = 8000 - else: - mode = G.mode - rate = G.rate - if G.debug: print 'mode =', mode, 'rate =', rate - if mode in ('au', 'aiff', 'wav', 'aifc', 'ul', 'ub', 'sb') and \ - rate in validrates: - tempname = filename - if mode in ('ul', 'ub', 'sb'): - raw = 1 - elif cache.has_key(filename): - tempname = cache[filename] - else: - tempname = G.tempprefix + `rand.rand()` + '.aiff' - cmd = SOX - if G.debug: - cmd = cmd + ' -V' - if mode <> '': - cmd = cmd + ' -t ' + mode - cmd = cmd + ' ' + commands.mkarg(filename) - cmd = cmd + ' -t aiff' - if rate not in validrates: - rate = 32000 - if rate: - cmd = cmd + ' -r ' + `rate` - cmd = cmd + ' ' + tempname - if G.debug: print cmd - sts = os.system(cmd) - if sts: - print cmd - print 'Exit status', sts - stdwin.fleep() - try: - os.unlink(tempname) - except: - pass - return - cache[filename] = tempname - if raw: - pid = sfplayraw(tempname, tuple) - else: - pid = sfplay(tempname, []) - if G.synchronous: - sts = os.wait(pid, 0) - else: - G.busy = pid - G.stop.enable(1) - G.cw.win.settimer(1) - -def sfplayraw(filename, tuple): - args = ['-i'] - type, rate, channels, frames, bits = tuple - if type == 'ul': - args.append('mulaw') - elif type == 'ub': - args = args + ['integer', '8', 'unsigned'] - elif type == 'sb': - args = args + ['integer', '8', '2scomp'] - else: - print 'sfplayraw: warning: unknown type in', tuple - if channels > 1: - args = args + ['channels', `channels`] - if not rate: - rate = G.rate - if rate: - args = args + ['rate', `rate`] - args.append('end') - return sfplay(filename, args) - -def sfplay(filename, args): - if G.debug: - args = ['-p'] + args - args = [SFPLAY, '-r'] + args + [filename] - if G.debug: print 'sfplay:', args - pid = os.fork() - if pid == 0: - # Child - os.exec(SFPLAY, args) - # NOTREACHED - else: - # Parent - return pid - -main() diff --git a/Demo/stdwin/lpwin.py b/Demo/stdwin/lpwin.py deleted file mode 100755 index eaf98bea34..0000000000 --- a/Demo/stdwin/lpwin.py +++ /dev/null @@ -1,198 +0,0 @@ -#! /usr/local/bin/python - -# Watch line printer queues (only works with BSD 4.3 lpq). -# -# This brings up a window containing one line per printer argument. -# -# Each line gives a small summary of the printer's status and queue. -# The status tries to give as much relevant information as possible, -# and gives extra info if you have jobs in the queue. -# -# The line's background color gives a hint at the status: navajo white -# for idle, green if your job is now printing, yellow/orange for -# small/large queue, red for errors. -# -# To reduce the duration of the unresponsive time while it is waiting -# for an lpq subprocess to finish, it polls one printer every -# delay/len(printers) seconds. A tiny dot indicates the last printer -# updated. Hit the mouse button in the window to update the next one. -# -# To do: -# - add an argument to override the default delay -# - add arguments to override the default colors -# - better heuristic for small/large queue (and more colors!) -# - mouse clicks should update the printer clicked in -# - better visual appearance, e.g., boxes around the lines? - -import posix -import sys -import time -import string - -import stdwin -from stdwinevents import * -import mainloop - -# Default parameters -DEF_PRINTER = 'oce' # This is CWI specific! -DEF_DELAY = 10 - -# Color assignments -c_unknown = stdwin.fetchcolor('white') -c_idle = stdwin.fetchcolor('navajo white') -c_ontop = stdwin.fetchcolor('green') -c_smallqueue = stdwin.fetchcolor('yellow') -c_bigqueue = stdwin.fetchcolor('orange') -c_error = stdwin.fetchcolor('red') - -def main(): - delay = DEF_DELAY - # - try: - thisuser = posix.environ['LOGNAME'] - except: - thisuser = posix.environ['USER'] - # - printers = sys.argv[1:] - if printers: - # Strip '-P' from printer names just in case - # the user specified it... - for i in range(len(printers)): - if printers[i][:2] == '-P': - printers[i] = printers[i][2:] - else: - if posix.environ.has_key('PRINTER'): - printers = [posix.environ['PRINTER']] - else: - printers = [DEF_PRINTER] - # - width = stdwin.textwidth('in')*20 - height = len(printers) * stdwin.lineheight() + 5 - stdwin.setdefwinsize(width, height) - stdwin.setdefscrollbars(0, 0) - # - win = stdwin.open('lpwin') - # - win.printers = printers - win.colors = [c_unknown] * len(printers) - win.texts = printers[:] - win.next = 0 - win.delay = DEF_DELAY - win.thisuser = thisuser - win.dispatch = lpdispatch - # - win.settimer(1) - # - mainloop.register(win) - mainloop.mainloop() - -def lpdispatch(event): - type, win, detail = event - if type == WE_CLOSE or type == WE_CHAR and detail in ('q', 'Q'): - mainloop.unregister(win) - elif type == WE_DRAW: - drawproc(win) - elif type == WE_TIMER: - update(win) - win.change((0,0), (10000, 10000)) - elif type == WE_MOUSE_UP: - win.settimer(1) - -def drawproc(win): - d = win.begindrawing() - offset = d.textwidth('.') - h, v = 0, 0 - for i in range(len(win.printers)): - text = win.texts[i] - color = win.colors[i] - d.setbgcolor(color) - d.erase((h, v), (h+10000, v+d.lineheight())) - if (i+1) % len(win.printers) == win.next and color <> c_unknown: - d.text((h, v), '.') - d.text((h+offset, v), text) - v = v + d.lineheight() - -def update(win): - i = win.next - win.next = (i+1) % len(win.printers) - win.texts[i], win.colors[i] = makestatus(win.printers[i], win.thisuser) - win.settimer(int(win.delay * 10.0 / len(win.printers))) - -def makestatus(name, thisuser): - pipe = posix.popen('lpq -P' + name + ' 2>&1', 'r') - lines = [] - users = {} - aheadbytes = 0 - aheadjobs = 0 - userseen = 0 - totalbytes = 0 - totaljobs = 0 - color = c_unknown - while 1: - line = pipe.readline() - if not line: break - fields = string.split(line) - n = len(fields) - if len(fields) >= 6 and fields[n-1] == 'bytes': - rank = fields[0] - user = fields[1] - job = fields[2] - files = fields[3:-2] - bytes = eval(fields[n-2]) - if user == thisuser: - userseen = 1 - if aheadjobs == 0: - color = c_ontop - elif not userseen: - aheadbytes = aheadbytes + bytes - aheadjobs = aheadjobs + 1 - totalbytes = totalbytes + bytes - totaljobs = totaljobs + 1 - if color == c_unknown: - color = c_smallqueue - elif color == c_smallqueue: - color = c_bigqueue - if users.has_key(user): - ujobs, ubytes = users[user] - else: - ujobs, ubytes = 0, 0 - ujobs = ujobs + 1 - ubytes = ubytes + bytes - users[user] = ujobs, ubytes - else: - if fields and fields[0] <> 'Rank': - line = string.strip(line) - if line == 'no entries': - line = name + ': idle' - if color == c_unknown: - color = c_idle - elif line[-22:] == ' is ready and printing': - line = line[:-22] - else: - line = name + ': ' + line - color = c_error - lines.append(line) - # - if totaljobs: - line = `(totalbytes+1023)/1024` + ' K' - if totaljobs <> len(users): - line = line + ' (' + `totaljobs` + ' jobs)' - if len(users) == 1: - line = line + ' for ' + users.keys()[0] - else: - line = line + ' for ' + `len(users)` + ' users' - if userseen: - if aheadjobs == 0: - line = line + ' (' + thisuser + ' first)' - else: - line = line + ' (' + `(aheadbytes+1023)/1024` - line = line + ' K before ' + thisuser + ')' - lines.append(line) - # - sts = pipe.close() - if sts: - lines.append('lpq exit status ' + `sts`) - color = c_error - return string.joinfields(lines, ': '), color - -main() diff --git a/Demo/stdwin/microedit.py b/Demo/stdwin/microedit.py deleted file mode 100755 index eca093a188..0000000000 --- a/Demo/stdwin/microedit.py +++ /dev/null @@ -1,183 +0,0 @@ -#! /usr/local/bin/python - -# A minimal single-window text editor using STDWIN's text objects. -# -# Usage: microedit file -# -# This is not intended as a real application but as an introduction -# to STDWIN programming in Python, especially text objects. -# Once you understand microedit.py, study miniedit.py to learn -# about multiple windows and menus, cut and paste, etc. - - -import sys -import stdwin -from stdwinevents import * - - -# Main program -# -def main(): - # - # Get the filename argument and read its contents as one very - # large string. - # An exception will terminate the program if there is no argument - # or if the file could not be read... - # - filename = sys.argv[1] - fp = open(filename, 'r') - contents = fp.read() - del fp # Close the file - # - # Create the window, using the filename as window title - # - window = stdwin.open(filename) - # - # Add a simple File menu to the window with two items - # - filemenu = window.menucreate('File') - filemenu.additem('Save', 'S') # Item 0 (shortcut Meta-S) - filemenu.additem('Save As...') # Item 1 - # - # Create a text object occupying the entire window - # and fill it with the file's contents - # - corner = window.getwinsize() # (width, height) - area = (0, 0), corner # Rectangle as large as the window - text = window.textcreate(area) - text.settext(contents) - del contents # Get rid of contents object - fix_textsize(window, text) # Set document size accordingly - # - # Main event loop -- stop if a close request comes in. - # - # STDWIN applications should regularly call stdwin.getevent() - # otherwise the windows won't function as expected. - # - while 1: - # - # Get the next event - # - type, w, detail = e = stdwin.getevent() - # - # Event decoding switch - # - if type == WE_CLOSE: - break # Stop (no check for saved file!) - elif type == WE_SIZE: - # - # The window was resized -- - # let the text object recompute the line breaks - # and change the document size accordingly, - # so scroll bars will work - # - fix_textsize(window, text) - elif type == WE_MENU: - # - # Execute a file menu request (our only menu) - # - menu, item = detail - if item == 0: - # - # "Save": save to the current filename - # - dummy = save_file(window, text, filename) - elif item == 1: - # - # "Save As": ask a new filename, save to it, - # and make it the current filename - # - # NB: askfile raises KeyboardInterrupt - # if the user cancels the dialog, hence - # the try statement - # - try: - newfile = stdwin.askfile( \ - 'Save as:', filename, 1) - except KeyboardInterrupt: - newfile = '' - if newfile: - if save_file(window, text, newfile): - filename = newfile - window.settitle(filename) - elif text.event(e): - # - # The text object has handled the event. - # Fix the document size if necessary. - # Note: this sometimes fixes the size - # unnecessarily, e.g., for arrow keys. - # - if type in (WE_CHAR, WE_COMMAND): - fix_docsize(window, text) - - -# Save the window's contents to the filename. -# If the open() fails, put up a warning message and return 0; -# if the save succeeds, return 1. -# -def save_file(window, text, filename): - # - # Open the file for writing, handling exceptions - # - try: - fp = open(filename, 'w') - except RuntimeError: - stdwin.message('Cannot create ' + filename) - return 0 - # - # Get the contents of the text object as one very long string - # - contents = text.gettext() - # - # Write the contents to the file - # - fp.write(contents) - # - # The file is automatically closed when this routine returns - # - return 1 - - -# Change the size of the text object to fit in the window, -# and then fix the window's document size to fit around the text object. -# -def fix_textsize(window, text): - # - # Compute a rectangle as large as the window - # - corner = window.getwinsize() # (width, height) - area = (0, 0), (corner) - # - # Move the text object to this rectangle. - # Note: text.move() ignores the bottom coordinate! - # - text.move(area) - # - # Now fix the document size accordingly - # - fix_docsize(window, text) - - -# Fix the document size, after the text has changed -# -def fix_docsize(window, text): - # - # Get the actual rectangle occupied by the text object. - # This has the same left, top and right, but a different bottom. - # - area = text.getrect() - # - # Compute the true height of the text object - # - origin, corner = area - width, height = corner - # - # Set the document height to the text object's height. - # The width is zero since we don't want a horizontal scroll bar. - # - window.setdocsize(0, height) - - -# Once all functions are defined, call main() -# -main() diff --git a/Demo/stdwin/miniedit.py b/Demo/stdwin/miniedit.py deleted file mode 100755 index 3d4aeeaa0d..0000000000 --- a/Demo/stdwin/miniedit.py +++ /dev/null @@ -1,356 +0,0 @@ -#! /usr/local/bin/python - -# A miniature multi-window editor using STDWIN's text objects. -# -# Usage: miniedit [file] ... -# -# The user interface is similar to that of the miniedit demo application -# in C that comes with STDWIN. -# -# XXX need to comment the functions -# XXX Not yet implemented: -# disabling menu entries for inapplicable actions -# Find operations - - -import sys -import stdwin -from stdwinevents import * - - -# Constant: list of WE_COMMAND events that (may) change the text buffer -# so we can decide whether to set the 'changed' flag. -# Note that it is possible for such a command to fail (a backspace -# at the beginning of the buffer) but we'll set the changed flag anyway -# -- it's too complicated to check this condition right now. -# -changing = [WC_RETURN, WC_TAB, WC_BACKSPACE] - - -# The list of currently open windows; -# this is maintained so we can stop when there are no windows left -# -windows = [] - - -# A note on window data attributes (set by open_window): -# -# w.textobject the window's text object -# w.changed true when the window's text is changed -# w.filename filename connected to the window; '' if none - - -# Main program -# -def main(): - # - # Set a reasonable default window size. - # If we are using a fixed-width font this will open a 80x24 window; - # for variable-width fonts we approximate this based on an average - # - stdwin.setdefwinsize(40*stdwin.textwidth('in'), 24*stdwin.lineheight()) - # - # Create global menus (as local variables) - # - filemenu = make_file_menu(stdwin) - editmenu = make_edit_menu(stdwin) - findmenu = make_find_menu(stdwin) - # - # Get the list of files from the command line (maybe none) - # - files = sys.argv[1:] - # - # Open any files -- errors will be reported but do won't stop us - # - for filename in files: - open_file(filename) - # - # If there were no files, or none of them could be opened, - # put up a dialog asking for a filename - # - if not windows: - try: - open_dialog(None) - except KeyboardInterrupt: - pass # User cancelled - # - # If the dialog was cancelled, create an empty new window - # - if not windows: - new_window(None) - # - # Main event loop -- stop when we have no open windows left - # - while windows: - # - # Get the next event -- ignore interrupts - # - try: - type, window, detail = event = stdwin.getevent() - except KeyboardInterrupt: - type, window, detail = event = WE_NONE, None, None - # - # Event decoding switch - # - if not window: - pass # Ignore such events - elif type == WE_MENU: - # - # Execute menu operation - # - menu, item = detail - try: - menu.actions[item](window) - except KeyboardInterrupt: - pass # User cancelled - elif type == WE_CLOSE: - # - # Close a window - # - try: - close_dialog(window) - except KeyboardInterrupt: - pass # User cancelled - elif type == WE_SIZE: - # - # A window was resized -- - # let the text object recompute the line breaks - # and change the document size accordingly, - # so scroll bars will work - # - fix_textsize(window) - elif window.textobject.event(event): - # - # The event was eaten by the text object -- - # set the changed flag if not already set - # - if type == WE_CHAR or \ - type == WE_COMMAND and detail in changing: - window.changed = 1 - fix_docsize(window) - # - # Delete all objects that may still reference the window - # in the event -- this is needed otherwise the window - # won't actually be closed and may receive further - # events, which will confuse the event decoder - # - del type, window, detail, event - - -def make_file_menu(object): - menu = object.menucreate('File') - menu.actions = [] - additem(menu, 'New', 'N', new_window) - additem(menu, 'Open..', 'O', open_dialog) - additem(menu, '', '', None) - additem(menu, 'Save', 'S', save_dialog) - additem(menu, 'Save As..', '', save_as_dialog) - additem(menu, 'Save a Copy..', '', save_copy_dialog) - additem(menu, 'Revert', 'R', revert_dialog) - additem(menu, 'Quit', 'Q', quit_dialog) - return menu - - -def make_edit_menu(object): - menu = object.menucreate('Edit') - menu.actions = [] - additem(menu, 'Cut', 'X', do_cut) - additem(menu, 'Copy', 'C', do_copy) - additem(menu, 'Paste', 'V', do_paste) - additem(menu, 'Clear', 'B', do_clear) - additem(menu, 'Select All', 'A', do_select_all) - return menu - - -def make_find_menu(object): - menu = object.menucreate('Find') - menu.actions = [] - # XXX - return menu - - -def additem(menu, text, shortcut, function): - if shortcut: - menu.additem(text, shortcut) - else: - menu.additem(text) - menu.actions.append(function) - - -def open_dialog(current_ignored): - filename = stdwin.askfile('Open file:', '', 0) - open_file(filename) - - -def open_file(filename): - try: - fp = open(filename, 'r') - except RuntimeError: - stdwin.message(filename + ': cannot open') - return # Error, forget it - try: - contents = fp.read() - except RuntimeError: - stdwin.message(filename + ': read error') - return # Error, forget it - del fp # Close the file - open_window(filename, filename, contents) - - -def new_window(current_ignored): - open_window('', 'Untitled', '') - - -def open_window(filename, title, contents): - try: - window = stdwin.open(title) - except RuntimeError: - stdwin.message('cannot open new window') - return # Error, forget it - window.textobject = window.textcreate((0, 0), window.getwinsize()) - window.textobject.settext(contents) - window.changed = 0 - window.filename = filename - fix_textsize(window) - windows.append(window) - - -def quit_dialog(window): - for window in windows[:]: - close_dialog(window) - - -def close_dialog(window): - if window.changed: - prompt = 'Save changes to ' + window.gettitle() + ' ?' - if stdwin.askync(prompt, 1): - save_dialog(window) - if window.changed: - return # Save failed (not) cancelled - windows.remove(window) - del window.textobject - - -def save_dialog(window): - if not window.filename: - save_as_dialog(window) - return - if save_file(window, window.filename): - window.changed = 0 - - -def save_as_dialog(window): - prompt = 'Save ' + window.gettitle() + ' as:' - filename = stdwin.askfile(prompt, window.filename, 1) - if save_file(window, filename): - window.filename = filename - window.settitle(filename) - window.changed = 0 - - -def save_copy_dialog(window): - prompt = 'Save a copy of ' + window.gettitle() + ' as:' - filename = stdwin.askfile(prompt, window.filename, 1) - void = save_file(window, filename) - - -def save_file(window, filename): - try: - fp = open(filename, 'w') - except RuntimeError: - stdwin.message(filename + ': cannot create') - return 0 - contents = window.textobject.gettext() - try: - fp.write(contents) - except RuntimeError: - stdwin.message(filename + ': write error') - return 0 - return 1 - - -def revert_dialog(window): - if not window.filename: - stdwin.message('This window has no file to revert from') - return - if window.changed: - prompt = 'Really read ' + window.filename + ' back from file?' - if not stdwin.askync(prompt, 1): - return - try: - fp = open(window.filename, 'r') - except RuntimeError: - stdwin.message(filename + ': cannot open') - return - contents = fp.read() - del fp # Close the file - window.textobject.settext(contents) - window.changed = 0 - fix_docsize(window) - - -def fix_textsize(window): - corner = window.getwinsize() - area = (0, 0), (corner) - window.textobject.move(area) - fix_docsize(window) - - -def fix_docsize(window): - area = window.textobject.getrect() - origin, corner = area - width, height = corner - window.setdocsize(0, height) - - -def do_cut(window): - selection = window.textobject.getfocustext() - if not selection: - stdwin.fleep() # Nothing to cut - elif not window.setselection(WS_PRIMARY, selection): - stdwin.fleep() # Window manager glitch... - else: - stdwin.rotatecutbuffers(1) - stdwin.setcutbuffer(0, selection) - window.textobject.replace('') - window.changed = 1 - fix_docsize(window) - - -def do_copy(window): - selection = window.textobject.getfocustext() - if not selection: - stdwin.fleep() # Nothing to cut - elif not window.setselection(WS_PRIMARY, selection): - stdwin.fleep() # Window manager glitch... - else: - stdwin.rotatecutbuffers(1) - stdwin.setcutbuffer(0, selection) - - -def do_paste(window): - selection = stdwin.getselection(WS_PRIMARY) - if not selection: - selection = stdwin.getcutbuffer(0) - if not selection: - stdwin.fleep() # Nothing to paste - else: - window.textobject.replace(selection) - window.changed = 1 - fix_docsize(window) - -def do_clear(window): - first, last = window.textobject.getfocus() - if first == last: - stdwin.fleep() # Nothing to clear - else: - window.textobject.replace('') - window.changed = 1 - fix_docsize(window) - - -def do_select_all(window): - window.textobject.setfocus(0, 0x7fffffff) # XXX Smaller on the Mac! - - -main() diff --git a/Demo/stdwin/python.py b/Demo/stdwin/python.py deleted file mode 100755 index 2506078630..0000000000 --- a/Demo/stdwin/python.py +++ /dev/null @@ -1,448 +0,0 @@ -#! /usr/local/bin/python - -# A STDWIN-based front end for the Python interpreter. -# -# This is useful if you want to avoid console I/O and instead -# use text windows to issue commands to the interpreter. -# -# It supports multiple interpreter windows, each with its own context. -# -# BUGS AND CAVEATS: -# -# This was written long ago as a demonstration, and slightly hacked to -# keep it up-to-date, but never as an industry-strength alternative -# interface to Python. It should be rewritten using more classes, and -# merged with something like wdb. -# -# Although this supports multiple windows, the whole application -# is deaf and dumb when a command is running in one window. -# -# Interrupt is (ab)used to signal EOF on input requests. -# -# On UNIX (using X11), interrupts typed in the window will not be -# seen until the next input or output operation. When you are stuck -# in an infinite loop, try typing ^C in the shell window where you -# started this interpreter. (On the Mac, interrupts work normally.) - - -import sys -import builtin -import stdwin -from stdwinevents import * -import rand -import mainloop -import os - - -# Stack of windows waiting for [raw_]input(). -# Element [0] is the top. -# If there are multiple windows waiting for input, only the -# one on top of the stack can accept input, because the way -# raw_input() is implemented (using recursive mainloop() calls). -# -inputwindows = [] - - -# Exception raised when input is available -# -InputAvailable = 'input available for raw_input (not an error)' - - -# Main program -- create the window and call the mainloop -# -def main(): - # Hack so 'import python' won't load another copy - # of this if we were loaded though 'python python.py'. - # (Should really look at sys.argv[0]...) - if 'inputwindows' in dir(sys.modules['__main__']) and \ - sys.modules['__main__'].inputwindows is inputwindows: - sys.modules['python'] = sys.modules['__main__'] - # - win = makewindow() - mainloop.mainloop() - - -# Create a new window -# -def makewindow(): - # stdwin.setdefscrollbars(0, 1) # Not in Python 0.9.1 - # stdwin.setfont('monaco') # Not on UNIX! and not Python 0.9.1 - # width, height = stdwin.textwidth('in')*40, stdwin.lineheight()*24 - # stdwin.setdefwinsize(width, height) - win = stdwin.open('Python interpreter ready') - win.editor = win.textcreate((0,0), win.getwinsize()) - win.globals = {} # Dictionary for user's globals - win.command = '' # Partially read command - win.busy = 0 # Ready to accept a command - win.auto = 1 # [CR] executes command - win.insertOutput = 1 # Insert output at focus - win.insertError = 1 # Insert error output at focus - win.setwincursor('ibeam') - win.filename = '' # Empty if no file for this window - makefilemenu(win) - makeeditmenu(win) - win.dispatch = pdispatch # Event dispatch function - mainloop.register(win) - return win - - -# Make a 'File' menu -# -def makefilemenu(win): - win.filemenu = mp = win.menucreate('File') - mp.callback = [] - additem(mp, 'New', 'N', do_new) - additem(mp, 'Open...', 'O', do_open) - additem(mp, '', '', None) - additem(mp, 'Close', 'W', do_close) - additem(mp, 'Save', 'S', do_save) - additem(mp, 'Save as...', '', do_saveas) - additem(mp, '', '', None) - additem(mp, 'Quit', 'Q', do_quit) - - -# Make an 'Edit' menu -# -def makeeditmenu(win): - win.editmenu = mp = win.menucreate('Edit') - mp.callback = [] - additem(mp, 'Cut', 'X', do_cut) - additem(mp, 'Copy', 'C', do_copy) - additem(mp, 'Paste', 'V', do_paste) - additem(mp, 'Clear', '', do_clear) - additem(mp, '', '', None) - win.iauto = len(mp.callback) - additem(mp, 'Autoexecute', '', do_auto) - mp.check(win.iauto, win.auto) - win.insertOutputNum = len(mp.callback) - additem(mp, 'Insert Output', '', do_insertOutputOption) - win.insertErrorNum = len(mp.callback) - additem(mp, 'Insert Error', '', do_insertErrorOption) - additem(mp, 'Exec', '\r', do_exec) - - -# Helper to add a menu item and callback function -# -def additem(mp, text, shortcut, handler): - if shortcut: - mp.additem(text, shortcut) - else: - mp.additem(text) - mp.callback.append(handler) - - -# Dispatch a single event to the interpreter. -# Resize events cause a resize of the editor. -# Some events are treated specially. -# Most other events are passed directly to the editor. -# -def pdispatch(event): - type, win, detail = event - if not win: - win = stdwin.getactive() - if not win: return - if type == WE_CLOSE: - do_close(win) - return - elif type == WE_SIZE: - win.editor.move((0, 0), win.getwinsize()) - elif type == WE_COMMAND and detail == WC_RETURN: - if win.auto: - do_exec(win) - else: - void = win.editor.event(event) - elif type == WE_COMMAND and detail == WC_CANCEL: - if win.busy: - raise KeyboardInterrupt - else: - win.command = '' - settitle(win) - elif type == WE_MENU: - mp, item = detail - mp.callback[item](win) - else: - void = win.editor.event(event) - if win in mainloop.windows: - # May have been deleted by close... - win.setdocsize(0, win.editor.getrect()[1][1]) - if type in (WE_CHAR, WE_COMMAND): - win.editor.setfocus(win.editor.getfocus()) - - -# Helper to set the title of the window -# -def settitle(win): - if win.filename == '': - win.settitle('Python interpreter ready') - else: - win.settitle(win.filename) - - -# Helper to replace the text of the focus -# -def replace(win, text): - win.editor.replace(text) - # Resize the window to display the text - win.setdocsize(0, win.editor.getrect()[1][1]) # update the size before - win.editor.setfocus(win.editor.getfocus()) # move focus to the change - - -# File menu handlers -# -def do_new(win): - win = makewindow() -# -def do_open(win): - try: - filename = stdwin.askfile('Open file', '', 0) - win = makewindow() - win.filename = filename - win.editor.replace(open(filename, 'r').read()) - win.editor.setfocus(0, 0) - win.settitle(win.filename) - # - except KeyboardInterrupt: - pass # Don't give an error on cancel -# -def do_save(win): - try: - if win.filename == '': - win.filename = stdwin.askfile('Open file', '', 1) - f = open(win.filename, 'w') - f.write(win.editor.gettext()) - # - except KeyboardInterrupt: - pass # Don't give an error on cancel - -def do_saveas(win): - currentFilename = win.filename - win.filename = '' - do_save(win) # Use do_save with empty filename - if win.filename == '': # Restore the name if do_save did not set it - win.filename = currentFilename -# -def do_close(win): - if win.busy: - stdwin.message('Can\'t close busy window') - return # need to fail if quitting?? - win.editor = None # Break circular reference - #del win.editmenu # What about the filemenu?? - mainloop.unregister(win) - win.close() -# -def do_quit(win): - # Call win.dispatch instead of do_close because there - # may be 'alien' windows in the list. - for win in mainloop.windows[:]: - mainloop.dispatch((WE_CLOSE, win, None)) - # need to catch failed close - - -# Edit menu handlers -# -def do_cut(win): - text = win.editor.getfocustext() - if not text: - stdwin.fleep() - return - stdwin.setcutbuffer(0, text) - replace(win, '') -# -def do_copy(win): - text = win.editor.getfocustext() - if not text: - stdwin.fleep() - return - stdwin.setcutbuffer(0, text) -# -def do_paste(win): - text = stdwin.getcutbuffer(0) - if not text: - stdwin.fleep() - return - replace(win, text) -# -def do_clear(win): - replace(win, '') - - -# These would be better in a preferences dialog: -# -def do_auto(win): - win.auto = (not win.auto) - win.editmenu.check(win.iauto, win.auto) -# -def do_insertOutputOption(win): - win.insertOutput = (not win.insertOutput) - title = ['Append Output', 'Insert Output'][win.insertOutput] - win.editmenu.setitem(win.insertOutputNum, title) -# -def do_insertErrorOption(win): - win.insertError = (not win.insertError) - title = ['Error Dialog', 'Insert Error'][win.insertError] - win.editmenu.setitem(win.insertErrorNum, title) - - -# Extract a command from the editor and execute it, or pass input to -# an interpreter waiting for it. -# Incomplete commands are merely placed in the window's command buffer. -# All exceptions occurring during the execution are caught and reported. -# (Tracebacks are currently not possible, as the interpreter does not -# save the traceback pointer until it reaches its outermost level.) -# -def do_exec(win): - if win.busy: - if win not in inputwindows: - stdwin.message('Can\'t run recursive commands') - return - if win <> inputwindows[0]: - stdwin.message('Please complete recursive input first') - return - # - # Set text to the string to execute. - a, b = win.editor.getfocus() - alltext = win.editor.gettext() - n = len(alltext) - if a == b: - # There is no selected text, just an insert point; - # so execute the current line. - while 0 < a and alltext[a-1] <> '\n': # Find beginning of line - a = a-1 - while b < n and alltext[b] <> '\n': # Find end of line after b - b = b+1 - text = alltext[a:b] + '\n' - else: - # Execute exactly the selected text. - text = win.editor.getfocustext() - if text[-1:] <> '\n': # Make sure text ends with \n - text = text + '\n' - while b < n and alltext[b] <> '\n': # Find end of line after b - b = b+1 - # - # Set the focus to expect the output, since there is always something. - # Output will be inserted at end of line after current focus, - # or appended to the end of the text. - b = [n, b][win.insertOutput] - win.editor.setfocus(b, b) - # - # Make sure there is a preceeding newline. - if alltext[b-1:b] <> '\n': - win.editor.replace('\n') - # - # - if win.busy: - # Send it to raw_input() below - raise InputAvailable, text - # - # Like the real Python interpreter, we want to execute - # single-line commands immediately, but save multi-line - # commands until they are terminated by a blank line. - # Unlike the real Python interpreter, we don't do any syntax - # checking while saving up parts of a multi-line command. - # - # The current heuristic to determine whether a command is - # the first line of a multi-line command simply checks whether - # the command ends in a colon (followed by a newline). - # This is not very robust (comments and continuations will - # confuse it), but it is usable, and simple to implement. - # (It even has the advantage that single-line loops etc. - # don't need te be terminated by a blank line.) - # - if win.command: - # Already continuing - win.command = win.command + text - if win.command[-2:] <> '\n\n': - win.settitle('Unfinished command...') - return # Need more... - else: - # New command - win.command = text - if text[-2:] == ':\n': - win.settitle('Unfinished command...') - return - command = win.command - win.command = '' - win.settitle('Executing command...') - # - # Some hacks: - # - The standard files are replaced by an IOWindow instance. - # - A 2nd argument to exec() is used to specify the directory - # holding the user's global variables. (If this wasn't done, - # the exec would be executed in the current local environment, - # and the user's assignments to globals would be lost...) - # - save_stdin = sys.stdin - save_stdout = sys.stdout - save_stderr = sys.stderr - try: - sys.stdin = sys.stdout = sys.stderr = IOWindow(win) - win.busy = 1 - try: - exec(command, win.globals) - except KeyboardInterrupt: - print '[Interrupt]' - except: - msg = sys.exc_type - if sys.exc_value <> None: - msg = msg + ': ' + `sys.exc_value` - if win.insertError: - stdwin.fleep() - replace(win, msg + '\n') - else: - win.settitle('Unhandled exception') - stdwin.message(msg) - finally: - # Restore redirected I/O in *all* cases - win.busy = 0 - sys.stderr = save_stderr - sys.stdout = save_stdout - sys.stdin = save_stdin - settitle(win) - - -# Class emulating file I/O from/to a window -# -class IOWindow: - # - def __init__(self, win): - self.win = win - # - def readline(self, *unused_args): - n = len(inputwindows) - save_title = self.win.gettitle() - title = n*'(' + 'Requesting input...' + ')'*n - self.win.settitle(title) - inputwindows.insert(0, self.win) - try: - try: - mainloop.mainloop() - finally: - del inputwindows[0] - self.win.settitle(save_title) - except InputAvailable, val: # See do_exec above - return val - except KeyboardInterrupt: - raise EOFError # Until we have a "send EOF" key - # If we didn't catch InputAvailable, something's wrong... - raise EOFError - # - def write(self, text): - mainloop.check() - replace(self.win, text) - mainloop.check() - - -# Currently unused function to test a command's syntax without executing it -# -def testsyntax(s): - import string - lines = string.splitfields(s, '\n') - for i in range(len(lines)): lines[i] = '\t' + lines[i] - lines.insert(0, 'if 0:') - lines.append('') - exec(string.joinfields(lines, '\n')) - - -# Call the main program -# -main() diff --git a/Demo/stdwin/wdiff.py b/Demo/stdwin/wdiff.py deleted file mode 100755 index cb48fe4c94..0000000000 --- a/Demo/stdwin/wdiff.py +++ /dev/null @@ -1,483 +0,0 @@ -#! /usr/local/bin/python - -# A window-oriented recursive diff utility. -# NB: This uses undocumented window classing modules. - -# TO DO: -# - faster update after moving/copying one file -# - diff flags (-b, etc.) should be global or maintained per window -# - use a few fixed windows instead of creating new ones all the time -# - ways to specify patterns to skip -# (best by pointing at a file and clicking a special menu entry!) -# - add rcsdiff menu commands -# - add a way to view status of selected files without opening them -# - add a way to diff two files with different names -# - add a way to rename files -# - keep backups of overwritten/deleted files -# - a way to mark specified files as uninteresting for dircmp - -import sys -import os -import rand -import commands -import dircache -import statcache -import cmp -import cmpcache -import stdwin -import gwin -import textwin -import filewin -import tablewin -import anywin - -mkarg = commands.mkarg -mk2arg = commands.mk2arg - -# List of names to ignore in dircmp() -# -skiplist = ['RCS', '.Amake', 'tags', '.', '..'] - -# Function to determine whether a name should be ignored in dircmp(). -# -def skipthis(file): - return file[-1:] == '~' or file in skiplist - - -def anydiff(a, b, flags): # Display differences between any two objects - print 'diff', flags, a, b - if os.path.isdir(a) and os.path.isdir(b): - w = dirdiff(a, b, flags) - else: - w = filediff(a, b, flags) - addstatmenu(w, [a, b]) - w.original_close = w.close - w.close = close_dirwin - return w - -def close_dirwin(w): - close_subwindows(w, (), 0) - w.original_close(w) - -def filediff(a, b, flags): # Display differences between two text files - diffcmd = 'diff' - if flags: diffcmd = diffcmd + mkarg(flags) - diffcmd = diffcmd + mkarg(a) + mkarg(b) - difftext = commands.getoutput(diffcmd) - return textwin.open_readonly(mktitle(a, b), difftext) - -def dirdiff(a, b, flags): # Display differences between two directories - data = diffdata(a, b, flags) - w = tablewin.open(mktitle(a, b), data) - w.flags = flags - w.a = a - w.b = b - addviewmenu(w) - addactionmenu(w) - return w - -def diffdata(a, b, flags): # Compute directory differences. - # - a_only = [('A only:', header_action), ('', header_action)] - b_only = [('B only:', header_action), ('', header_action)] - ab_diff = [('A <> B:', header_action), ('', header_action)] - ab_same = [('A == B:', header_action), ('', header_action)] - data = [a_only, b_only, ab_diff, ab_same] - # - a_list = dircache.listdir(a)[:] - b_list = dircache.listdir(b)[:] - dircache.annotate(a, a_list) - dircache.annotate(b, b_list) - a_list.sort() - b_list.sort() - # - for x in a_list: - if x in ['./', '../']: - pass - elif x not in b_list: - a_only.append(x, a_only_action) - else: - ax = os.path.join(a, x) - bx = os.path.join(b, x) - if os.path.isdir(ax) and os.path.isdir(bx): - if flags == '-r': - same = dircmp(ax, bx) - else: - same = 0 - else: - try: - same = cmp.cmp(ax, bx) - except (RuntimeError, os.error): - same = 0 - if same: - ab_same.append(x, ab_same_action) - else: - ab_diff.append(x, ab_diff_action) - # - for x in b_list: - if x in ['./', '../']: - pass - elif x not in a_list: - b_only.append(x, b_only_action) - # - return data - -# Re-read the directory. -# Attempt to find the selected item back. - -def update(w): - setbusy(w) - icol, irow = w.selection - if 0 <= icol < len(w.data) and 2 <= irow < len(w.data[icol]): - selname = w.data[icol][irow][0] - else: - selname = '' - statcache.forget_dir(w.a) - statcache.forget_dir(w.b) - tablewin.select(w, (-1, -1)) - tablewin.update(w, diffdata(w.a, w.b, w.flags)) - if selname: - for icol in range(len(w.data)): - for irow in range(2, len(w.data[icol])): - if w.data[icol][irow][0] == selname: - tablewin.select(w, (icol, irow)) - break - -# Action functions for table items in directory diff windows - -def header_action(w, string, (icol, irow), (pos, clicks, button, mask)): - tablewin.select(w, (-1, -1)) - -def a_only_action(w, string, (icol, irow), (pos, clicks, button, mask)): - tablewin.select(w, (icol, irow)) - if clicks == 2: - w2 = anyopen(os.path.join(w.a, string)) - if w2: - w2.parent = w - -def b_only_action(w, string, (icol, irow), (pos, clicks, button, mask)): - tablewin.select(w, (icol, irow)) - if clicks == 2: - w2 = anyopen(os.path.join(w.b, string)) - if w2: - w2.parent = w - -def ab_diff_action(w, string, (icol, irow), (pos, clicks, button, mask)): - tablewin.select(w, (icol, irow)) - if clicks == 2: - w2 = anydiff(os.path.join(w.a, string), os.path.join(w.b, string),'') - w2.parent = w - -def ab_same_action(w, string, sel, detail): - ax = os.path.join(w.a, string) - if os.path.isdir(ax): - ab_diff_action(w, string, sel, detail) - else: - a_only_action(w, string, sel, detail) - -def anyopen(name): # Open any kind of document, ignore errors - try: - w = anywin.open(name) - except (RuntimeError, os.error): - stdwin.message('Can\'t open ' + name) - return 0 - addstatmenu(w, [name]) - return w - -def dircmp(a, b): # Compare whether two directories are the same - # To make this as fast as possible, it uses the statcache - print ' dircmp', a, b - a_list = dircache.listdir(a) - b_list = dircache.listdir(b) - for x in a_list: - if skipthis(x): - pass - elif x not in b_list: - return 0 - else: - ax = os.path.join(a, x) - bx = os.path.join(b, x) - if statcache.isdir(ax) and statcache.isdir(bx): - if not dircmp(ax, bx): return 0 - else: - try: - if not cmpcache.cmp(ax, bx): return 0 - except (RuntimeError, os.error): - return 0 - for x in b_list: - if skipthis(x): - pass - elif x not in a_list: - return 0 - return 1 - - -# View menu (for dir diff windows only) - -def addviewmenu(w): - w.viewmenu = m = w.menucreate('View') - m.action = [] - add(m, 'diff -r A B', diffr_ab) - add(m, 'diff A B', diff_ab) - add(m, 'diff -b A B', diffb_ab) - add(m, 'diff -c A B', diffc_ab) - add(m, 'gdiff A B', gdiff_ab) - add(m, ('Open A ', 'A'), open_a) - add(m, ('Open B ', 'B'), open_b) - add(m, 'Rescan', rescan) - add(m, 'Rescan -r', rescan_r) - -# Action menu (for dir diff windows only) - -def addactionmenu(w): - w.actionmenu = m = w.menucreate('Action') - m.action = [] - add(m, 'cp A B', cp_ab) - add(m, 'rm B', rm_b) - add(m, '', nop) - add(m, 'cp B A', cp_ba) - add(m, 'rm A', rm_a) - -# Main menu (global): - -def mainmenu(): - m = stdwin.menucreate('Wdiff') - m.action = [] - add(m, ('Quit wdiff', 'Q'), quit_wdiff) - add(m, 'Close subwindows', close_subwindows) - return m - -def add(m, text, action): - m.additem(text) - m.action.append(action) - -def quit_wdiff(w, m, item): - if askyesno('Really quit wdiff altogether?', 1): - sys.exit(0) - -def close_subwindows(w, m, item): - while 1: - for w2 in gwin.windows: - if w2.parent == w: - close_subwindows(w2, m, item) - w2.close(w2) - break # inner loop, continue outer loop - else: - break # outer loop - -def diffr_ab(w, m, item): - dodiff(w, '-r') - -def diff_ab(w, m, item): - dodiff(w, '') - -def diffb_ab(w, m, item): - dodiff(w, '-b') - -def diffc_ab(w, m, item): - dodiff(w, '-c') - -def gdiff_ab(w, m, item): # Call SGI's gdiff utility - x = getselection(w) - if x: - a, b = os.path.join(w.a, x), os.path.join(w.b, x) - if os.path.isdir(a) or os.path.isdir(b): - stdwin.fleep() # This is for files only - else: - diffcmd = 'gdiff' - diffcmd = diffcmd + mkarg(a) + mkarg(b) + ' &' - print diffcmd - sts = os.system(diffcmd) - if sts: print 'Exit status', sts - -def dodiff(w, flags): - x = getselection(w) - if x: - w2 = anydiff(os.path.join(w.a, x), os.path.join(w.b, x), flags) - w2.parent = w - -def open_a(w, m, item): - x = getselection(w) - if x: - w2 = anyopen(os.path.join(w.a, x)) - if w2: - w2.parent = w - -def open_b(w, m, item): - x = getselection(w) - if x: - w2 = anyopen(os.path.join(w.b, x)) - if w2: - w2.parent = w - -def rescan(w, m, item): - w.flags = '' - update(w) - -def rescan_r(w, m, item): - w.flags = '-r' - update(w) - -def rm_a(w, m, item): - x = getselection(w) - if x: - if x[-1:] == '/': x = x[:-1] - x = os.path.join(w.a, x) - if os.path.isdir(x): - if askyesno('Recursively remove A directory ' + x, 1): - runcmd('rm -rf' + mkarg(x)) - else: - runcmd('rm -f' + mkarg(x)) - update(w) - -def rm_b(w, m, item): - x = getselection(w) - if x: - if x[-1:] == '/': x = x[:-1] - x = os.path.join(w.b, x) - if os.path.isdir(x): - if askyesno('Recursively remove B directory ' + x, 1): - runcmd('rm -rf' + mkarg(x)) - else: - runcmd('rm -f' + mkarg(x)) - update(w) - -def cp_ab(w, m, item): - x = getselection(w) - if x: - if x[-1:] == '/': x = x[:-1] - ax = os.path.join(w.a, x) - bx = os.path.join(w.b, x) - if os.path.isdir(ax): - if os.path.exists(bx): - m = 'Can\'t copy directory to existing target' - stdwin.message(m) - return - runcmd('cp -r' + mkarg(ax) + mkarg(w.b)) - else: - runcmd('cp' + mkarg(ax) + mk2arg(w.b, x)) - update(w) - -def cp_ba(w, m, item): - x = getselection(w) - if x: - if x[-1:] == '/': x = x[:-1] - ax = os.path.join(w.a, x) - bx = os.path.join(w.b, x) - if os.path.isdir(bx): - if os.path.exists(ax): - m = 'Can\'t copy directory to existing target' - stdwin.message(m) - return - runcmd('cp -r' + mkarg(bx) + mkarg(w.a)) - else: - runcmd('cp' + mk2arg(w.b, x) + mkarg(ax)) - update(w) - -def nop(args): - pass - -def getselection(w): - icol, irow = w.selection - if 0 <= icol < len(w.data): - if 0 <= irow < len(w.data[icol]): - return w.data[icol][irow][0] - stdwin.message('no selection') - return '' - -def runcmd(cmd): - print cmd - sts, output = commands.getstatusoutput(cmd) - if sts or output: - if not output: - output = 'Exit status ' + `sts` - stdwin.message(output) - - -# Status menu (for all kinds of windows) - -def addstatmenu(w, files): - w.statmenu = m = w.menucreate('Stat') - m.files = files - m.action = [] - for file in files: - m.additem(commands.getstatus(file)) - m.action.append(stataction) - -def stataction(w, m, item): # Menu item action for stat menu - file = m.files[item] - try: - m.setitem(item, commands.getstatus(file)) - except os.error: - stdwin.message('Can\'t get status for ' + file) - - -# Compute a suitable window title from two paths - -def mktitle(a, b): - if a == b: return a - i = 1 - while a[-i:] == b[-i:]: i = i+1 - i = i-1 - if not i: - return a + ' ' + b - else: - return '{' + a[:-i] + ',' + b[:-i] + '}' + a[-i:] - - -# Ask a confirmation question - -def askyesno(prompt, default): - try: - return stdwin.askync(prompt, default) - except KeyboardInterrupt: - return 0 - - -# Display a message "busy" in a window, and mark it for updating - -def setbusy(w): - left, top = w.getorigin() - width, height = w.getwinsize() - right, bottom = left + width, top + height - d = w.begindrawing() - d.erase((0, 0), (10000, 10000)) - text = 'Busy...' - textwidth = d.textwidth(text) - textheight = d.lineheight() - h, v = left + (width-textwidth)/2, top + (height-textheight)/2 - d.text((h, v), text) - del d - w.change((0, 0), (10000, 10000)) - - -# Main function - -def main(): - print 'wdiff: warning: this program does NOT make backups' - argv = sys.argv - flags = '' - if len(argv) >= 2 and argv[1][:1] == '-': - flags = argv[1] - del argv[1] - m = mainmenu() # Create menu earlier than windows - if len(argv) == 2: # 1 argument - w = anyopen(argv[1]) - if not w: return - elif len(argv) == 3: # 2 arguments - w = anydiff(argv[1], argv[2], flags) - w.parent = () - else: - sys.stdout = sys.stderr - print 'usage:', argv[0], '[diff-flags] dir-1 [dir-2]' - sys.exit(2) - del w # It's preserved in gwin.windows - while 1: - try: - gwin.mainloop() - break - except KeyboardInterrupt: - pass # Just continue... - -# Start the main function (this is a script) -main() diff --git a/Demo/threads/README b/Demo/threads/README deleted file mode 100644 index 01566fc98d..0000000000 --- a/Demo/threads/README +++ /dev/null @@ -1,8 +0,0 @@ -This directory contains some demonstrations of the thread module. -This module is only (optionally) available for the SGI, for now. - -These are mostly "proof of concept" type applications: - -find.py Parallelized "find(1)". -telnet.py Version of ../sockets/telnet.py using threads. -wpi.py Version of ../scripts/pi.py using threads and stdwin. diff --git a/Demo/threads/find.py b/Demo/threads/find.py deleted file mode 100644 index e97bd99be0..0000000000 --- a/Demo/threads/find.py +++ /dev/null @@ -1,153 +0,0 @@ -# A parallelized "find(1)" using the thread module (SGI only for now). - -# This demonstrates the use of a work queue and worker threads. -# It really does do more stats/sec when using multiple threads, -# although the improvement is only about 20-30 percent. - -# I'm too lazy to write a command line parser for the full find(1) -# command line syntax, so the predicate it searches for is wired-in, -# see function selector() below. (It currently searches for files with -# group or world write permission.) - -# Usage: parfind.py [-w nworkers] [directory] ... -# Default nworkers is 4, maximum appears to be 8 (on Irix 4.0.2) - - -import sys -import getopt -import string -import time -import os -from stat import * -import thread - - -# Work queue class. Usage: -# wq = WorkQ() -# wq.addwork(func, (arg1, arg2, ...)) # one or more calls -# wq.run(nworkers) -# The work is done when wq.run() completes. -# The function calls executed by the workers may add more work. -# Don't use keyboard interrupts! - -class WorkQ: - - # Invariants: - - # - busy and work are only modified when mutex is locked - # - len(work) is the number of jobs ready to be taken - # - busy is the number of jobs being done - # - todo is locked iff there is no work and somebody is busy - - def __init__(self): - self.mutex = thread.allocate() - self.todo = thread.allocate() - self.todo.acquire() - self.work = [] - self.busy = 0 - - def addwork(self, job): - if not job: - raise TypeError, 'cannot add null job' - self.mutex.acquire() - self.work.append(job) - self.mutex.release() - if len(self.work) == 1: - self.todo.release() - - def _getwork(self): - self.todo.acquire() - self.mutex.acquire() - if self.busy == 0 and len(self.work) == 0: - self.mutex.release() - self.todo.release() - return None - job = self.work[0] - del self.work[0] - self.busy = self.busy + 1 - self.mutex.release() - if len(self.work) > 0: - self.todo.release() - return job - - def _donework(self): - self.mutex.acquire() - self.busy = self.busy - 1 - if self.busy == 0 and len(self.work) == 0: - self.todo.release() - self.mutex.release() - - def _worker(self): - while 1: - job = self._getwork() - if not job: - break - func, args = job - apply(func, args) - self._donework() - - def run(self, nworkers): - if not self.work: - return # Nothing to do - for i in range(nworkers-1): - thread.start_new(self._worker, ()) - self._worker() - self.todo.acquire() - - -# Main program - -def main(): - nworkers = 4 - opts, args = getopt.getopt(sys.argv[1:], '-w:') - for opt, arg in opts: - if opt == '-w': - nworkers = string.atoi(arg) - if not args: - args = [os.curdir] - - wq = WorkQ() - for dir in args: - wq.addwork(find, (dir, selector, wq)) - - t1 = time.millitimer() - wq.run(nworkers) - t2 = time.millitimer() - - sys.stderr.write('Total time ' + `t2-t1` + ' msec.\n') - - -# The predicate -- defines what files we look for. -# Feel free to change this to suit your purpose - -def selector(dir, name, fullname, stat): - # Look for group or world writable files - return (stat[ST_MODE] & 0022) != 0 - - -# The find procedure -- calls wq.addwork() for subdirectories - -def find(dir, pred, wq): - try: - names = os.listdir(dir) - except os.error, msg: - print `dir`, ':', msg - return - for name in names: - if name not in (os.curdir, os.pardir): - fullname = os.path.join(dir, name) - try: - stat = os.lstat(fullname) - except os.error, msg: - print `fullname`, ':', msg - continue - if pred(dir, name, fullname, stat): - print fullname - if S_ISDIR(stat[ST_MODE]): - if not os.path.ismount(fullname): - wq.addwork(find, (fullname, pred, wq)) - - -# Call the main program - -main() diff --git a/Demo/threads/telnet.py b/Demo/threads/telnet.py deleted file mode 100644 index 5d4ae76cad..0000000000 --- a/Demo/threads/telnet.py +++ /dev/null @@ -1,113 +0,0 @@ -# Minimal interface to the Internet telnet protocol. -# -# *** modified to use threads *** -# -# It refuses all telnet options and does not recognize any of the other -# telnet commands, but can still be used to connect in line-by-line mode. -# It's also useful to play with a number of other services, -# like time, finger, smtp and even ftp. -# -# Usage: telnet host [port] -# -# The port may be a service name or a decimal port number; -# it defaults to 'telnet'. - - -import sys, os, time -from socket import * -import thread - -BUFSIZE = 8*1024 - -# Telnet protocol characters - -IAC = chr(255) # Interpret as command -DONT = chr(254) -DO = chr(253) -WONT = chr(252) -WILL = chr(251) - -def main(): - if len(sys.argv) != 2: - sys.stderr.write('usage: telnet hostname\n') - sys.exit(2) - host = sys.argv[1] - try: - hostaddr = gethostbyname(host) - except error: - sys.stderr.write(sys.argv[1] + ': bad host name\n') - sys.exit(2) - # - if len(sys.argv) > 2: - servname = sys.argv[2] - else: - servname = 'telnet' - # - if '0' <= servname[:1] <= '9': - port = eval(servname) - else: - try: - port = getservbyname(servname, 'tcp') - except error: - sys.stderr.write(servname + ': bad tcp service name\n') - sys.exit(2) - # - s = socket(AF_INET, SOCK_STREAM) - # - try: - s.connect(host, port) - except error, msg: - sys.stderr.write('connect failed: ' + `msg` + '\n') - sys.exit(1) - # - thread.start_new(child, (s,)) - parent(s) - -def parent(s): - # read socket, write stdout - iac = 0 # Interpret next char as command - opt = '' # Interpret next char as option - while 1: - data, dummy = s.recvfrom(BUFSIZE) - if not data: - # EOF -- exit - sys.stderr.write( '(Closed by remote host)\n') - thread.exit_prog(1) - cleandata = '' - for c in data: - if opt: - print ord(c) -## print '(replying: ' + `opt+c` + ')' - s.send(opt + c) - opt = '' - elif iac: - iac = 0 - if c == IAC: - cleandata = cleandata + c - elif c in (DO, DONT): - if c == DO: print '(DO)', - else: print '(DONT)', - opt = IAC + WONT - elif c in (WILL, WONT): - if c == WILL: print '(WILL)', - else: print '(WONT)', - opt = IAC + DONT - else: - print '(command)', ord(c) - elif c == IAC: - iac = 1 - print '(IAC)', - else: - cleandata = cleandata + c - sys.stdout.write(cleandata) - sys.stdout.flush() -## print 'Out:', `cleandata` - -def child(s): - # read stdin, write socket - while 1: - line = sys.stdin.readline() -## print 'Got:', `line` - s.send(line) - -main() diff --git a/Demo/threads/wpi.py b/Demo/threads/wpi.py deleted file mode 100644 index e408d21da1..0000000000 --- a/Demo/threads/wpi.py +++ /dev/null @@ -1,74 +0,0 @@ -# Display digits of pi in a window, calculating in a separate thread. -# Compare ../scripts/pi.py. - -import time -import thread -import stdwin -from stdwinevents import * - -digits = [] - -def worker(): - k, a, b, a1, b1 = 2l, 4l, 1l, 12l, 4l - while 1: - # Next approximation - p, q, k = k*k, 2l*k+1l, k+1l - a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1 - # Print common digits - d, d1 = a/b, a1/b1 - #print a, b, a1, b1 - while d == d1: - digits.append(`int(d)`) - a, a1 = 10l*(a%b), 10l*(a1%b1) - d, d1 = a/b, a1/b1 - -def main(): - digits_seen = 0 - thread.start_new_thread(worker, ()) - tw = stdwin.textwidth('0 ') - lh = stdwin.lineheight() - stdwin.setdefwinsize(20 * tw, 20 * lh) - win = stdwin.open('digits of pi') - options = win.menucreate('Options') - options.additem('Auto scroll') - autoscroll = 1 - options.check(0, autoscroll) - while 1: - win.settimer(1) - type, w, detail = stdwin.getevent() - if type == WE_CLOSE: - thread.exit_prog(0) - elif type == WE_DRAW: - (left, top), (right, bottom) = detail - digits_seen = len(digits) - d = win.begindrawing() - for i in range(digits_seen): - h = (i % 20) * tw - v = (i / 20) * lh - if top-lh < v < bottom: - d.text((h, v), digits[i]) - d.close() - elif type == WE_TIMER: - n = len(digits) - if n > digits_seen: - win.settitle(`n` + ' digits of pi') - d = win.begindrawing() - for i in range(digits_seen, n): - h = (i % 20) * tw - v = (i / 20) * lh - d.text((h, v), digits[i]) - d.close() - digits_seen = n - height = (v + 20*lh) / (20*lh) * (20*lh) - win.setdocsize(0, height) - if autoscroll: - win.show((0, v), (h+tw, v+lh)) - elif type == WE_MENU: - menu, item = detail - if menu == options: - if item == 0: - autoscroll = (not autoscroll) - options.check(0, autoscroll) - - -main() diff --git a/Doc/.cvsignore b/Doc/.cvsignore deleted file mode 100755 index 3df983b746..0000000000 --- a/Doc/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -python-lib.info* diff --git a/Doc/Makefile b/Doc/Makefile deleted file mode 100644 index d13f59fa7c..0000000000 --- a/Doc/Makefile +++ /dev/null @@ -1,68 +0,0 @@ -DESTDIR=/usr/local -LIBDESTDIR=$DESTDIR/lib -LIBDEST=$LIBDESTDIR/python -DOCDESTDIR=$LIBDEST/doc - -all: tut lib ref ext qua - -tut: - latex tut - latex tut - dvips tut >tut.ps - -ref: - touch ref.ind - latex ref - ./fix_hack ref.idx - makeindex ref - latex ref - dvips ref >ref.ps - -lib: - touch lib.ind - latex lib - ./fix_hack lib.idx - makeindex lib - latex lib - dvips lib >lib.ps - -ext: - touch ext.ind - latex ext - ./fix_hack ext.idx - makeindex ext - latex ext - dvips ext >ext.ps - -qua: - latex qua - bibtex qua - latex qua - latex qua - dvips qua >qua.ps - -lib.texi: lib1.tex lib2.tex lib3.tex lib4.tex lib5.tex \ - texipre.dat texipost.dat partparse.py - python partparse.py -o @lib.texi lib[1-5].tex - mv @lib.texi lib.texi - -.PRECIOUS: lib.texi - -python-lib.info: lib.texi fix.el - emacs -batch -l fix.el -f save-buffer -kill - makeinfo +footnote-style end +fill-column 72 +paragraph-indent 0 \ - lib.texi - -lib.info: python-lib.info - -# This target is very local to CWI... -libwww: lib.texi - texi2html -d lib.texi /usr/local/ftp.cwi.nl/pub/www/texinfo/python - -clean: - rm -f @* *~ *.aux *.idx *.ilg *.ind *.log *.toc *.blg *.bbl *.pyc - # Sources: .tex, .bib, .sty - # Useful results: .dvi, .ps, .texi, .info - -clobber: clean - rm -f *.dvi *.ps *.texi *.info *.info-[0-9]* diff --git a/Doc/README b/Doc/README deleted file mode 100644 index aba5c6cbcb..0000000000 --- a/Doc/README +++ /dev/null @@ -1,87 +0,0 @@ -Python main documentation -- in LaTeX -------------------------------------- - -This directory contains the LaTeX sources to the Python documentation -and a published article about Python. - -The following are the LaTeX source files: - - tut.tex The tutorial - lib.tex, lib[1-5].tex The library reference - ref.tex, ref[1-8].tex The reference manual - qua.tex, quabib.bib Article published in CWI Quarterly - -All except qua.tex use the style option file "myformat.sty". This -contains some macro definitions and sets some style parameters. - -The style parameters are set up for European paper size (21 x 29.7 cm, -a.k.a. A4, or roughly 8.27 x 11.7 inch) by default. To use US paper, -comment out the line saying \input{a4wide.sty} in myformat.sty (you -may want to fiddle with lay-out parameters like \textwidth and -\textheight, since the default format uses rather wide margins). - -You need the makeindex utility to produce the index for ref.tex -lib.tex; you need bibtex to produce the references list for qua.tex. - -There's a Makefile to call latex and the other utilities in the right -order and the right number of times. This will produce dvi files for -each document made; to preview them, use xdvi. Printing depends on -local conventions; at my site, I use dvips and lpr. For example: - - make ref # creates ref.dvi - xdvi ref # preview it - dvips -Ppsc ref | lpr -Ppsc # print it on printer "psc". - -If you don't have latex, you can ftp the pre-formatted PosytScript -versions of the documents; see "../misc/FTP" for information about -ftp-ing Python files. - -Making the INFO version of the Library Reference ------------------------------------------------- - -The Library Reference can now also be read in hypertext form using the -Emacs INFO system. This uses Texinfo format as an intermediate step. -It requires texinfo version 2 (we have used 2.14). - -To build the info files (python-lib.info*), say "make libinfo". This -takes a while, even on machines with 33 MIPS and 16 Mbytes :-) You can -ignore the output. - -But first you'll have to change a site dependency in fix.el: if -texinfo 2.xx is installed by default at your site, comment out the two -lines starting with "(setq load-path"; if it isn't, change the path! -(I'm afraid that if you don't have texinfo 2.xx this won't work -- use -archie to locate a version and ftp to fetch it.) - -The files used by the conversion process are: - -partparse.py the dirty-written Python script that converts - LaTeX sources to texi files. Output is left in - `@out.texi' - -texi{pre,post}.dat these files will be put before and after the - result - -fix.sh calls emacs in order to update all the nodes and - menus. After this, makeinfo will convert the - texinfo-source to the info-file(s). Assumption: - the texi-source is called `@out.texi' - -fix.el the elisp-file executed by emacs. Two calls to - 'texinfo-all-menus-update are necessary in - some cases - -fix_hack executable shell script that fixes the results - of the underscore hack. {\ptt \char'137} is - back-translated to a simple underscore. This is - needed for the texindex program - -handy.el some handy Emacs-macro's that helped converting - ``old'' documentation to a format that could be - understood by the converter scipt (partparse.py). - (You don't really need this, but, as the name - says, these macros are "handy") - -A Million thanks for Jan-Hein B\"uhrman for writing and debugging the -convertor and related scripts, and for fixing the LaTeX sources and -writing new macros for myformat.sty! diff --git a/Doc/ext.tex b/Doc/ext.tex deleted file mode 100644 index 18c801527f..0000000000 --- a/Doc/ext.tex +++ /dev/null @@ -1,914 +0,0 @@ -\documentstyle[twoside,11pt,myformat,times]{report} - -\title{\bf Extending and Embedding the Python Interpreter} - -\author{ - Guido van Rossum \\ - Dept. CST, CWI, P.O. Box 94079 \\ - 1090 GB Amsterdam, The Netherlands \\ - E-mail: {\tt guido@cwi.nl} -} - -\date{19 November 1993 \\ Release 0.9.9.++} % XXX update before release! - -% Tell \index to actually write the .idx file -\makeindex - -\begin{document} - -\pagenumbering{roman} - -\maketitle - -\begin{abstract} - -\noindent -This document describes how to write modules in C or C++ to extend the -Python interpreter. It also describes how to use Python as an -`embedded' language, and how extension modules can be loaded -dynamically (at run time) into the interpreter, if the operating -system supports this feature. - -\end{abstract} - -\pagebreak - -{ -\parskip = 0mm -\tableofcontents -} - -\pagebreak - -\pagenumbering{arabic} - - -\chapter{Extending Python with C or C++ code} - - -\section{Introduction} - -It is quite easy to add non-standard built-in modules to Python, if -you know how to program in C. A built-in module known to the Python -programmer as \code{foo} is generally implemented by a file called -\file{foomodule.c}. All but the most essential standard built-in -modules also adhere to this convention, and in fact some of them form -excellent examples of how to create an extension. - -Extension modules can do two things that can't be done directly in -Python: they can implement new data types, and they can make system -calls or call C library functions. Since the latter is usually the -most important reason for adding an extension, I'll concentrate on -adding `wrappers' around C library functions; the concrete example -uses the wrapper for -\code{system()} in module \code{posix}, found in (of course) the file -\file{posixmodule.c}. - -It is important not to be impressed by the size and complexity of -the average extension module; much of this is straightforward -`boilerplate' code (starting right with the copyright notice)! - -Let's skip the boilerplate and have a look at an interesting function -in \file{posixmodule.c} first: - -\begin{verbatim} - static object * - posix_system(self, args) - object *self; - object *args; - { - char *command; - int sts; - if (!getargs(args, "s", &command)) - return NULL; - sts = system(command); - return mkvalue("i", sts); - } -\end{verbatim} - -This is the prototypical top-level function in an extension module. -It will be called (we'll see later how this is made possible) when the -Python program executes statements like - -\begin{verbatim} - >>> import posix - >>> sts = posix.system('ls -l') -\end{verbatim} - -There is a straightforward translation from the arguments to the call -in Python (here the single value \code{'ls -l'}) to the arguments that -are passed to the C function. The C function always has two -parameters, conventionally named \var{self} and \var{args}. In this -example, \var{self} will always be a \code{NULL} pointer, since this is a -function, not a method (this is done so that the interpreter doesn't -have to understand two different types of C functions). - -The \var{args} parameter will be a pointer to a Python object, or -\code{NULL} if the Python function/method was called without -arguments. It is necessary to do full argument type checking on each -call, since otherwise the Python user would be able to cause the -Python interpreter to `dump core' by passing the wrong arguments to a -function in an extension module (or no arguments at all). Because -argument checking and converting arguments to C is such a common task, -there's a general function in the Python interpreter which combines -these tasks: \code{getargs()}. It uses a template string to determine -both the types of the Python argument and the types of the C variables -into which it should store the converted values. (More about this -later.)\footnote{ -There are convenience macros \code{getstrarg()}, -\code{getintarg()}, etc., for many common forms of \code{getargs()} -templates. These are relics from the past; it's better to call -\code{getargs()} directly.} - -If \code{getargs()} returns nonzero, the argument list has the right -type and its components have been stored in the variables whose -addresses are passed. If it returns zero, an error has occurred. In -the latter case it has already raised an appropriate exception by -calling \code{err_setstr()}, so the calling function can just return -\code{NULL}. - - -\section{Intermezzo: errors and exceptions} - -An important convention throughout the Python interpreter is the -following: when a function fails, it should set an exception condition -and return an error value (often a NULL pointer). Exceptions are set -in a global variable in the file errors.c; if this variable is NULL no -exception has occurred. A second variable is the `associated value' -of the exception. - -The file errors.h declares a host of err_* functions to set various -types of exceptions. The most common one is \code{err_setstr()} --- its -arguments are an exception object (e.g. RuntimeError --- actually it -can be any string object) and a C string indicating the cause of the -error (this is converted to a string object and stored as the -`associated value' of the exception). Another useful function is -\code{err_errno()}, which only takes an exception argument and -constructs the associated value by inspection of the (UNIX) global -variable errno. - -You can test non-destructively whether an exception has been set with -\code{err_occurred()}. However, most code never calls -\code{err_occurred()} to see whether an error occurred or not, but -relies on error return values from the functions it calls instead: - -When a function that calls another function detects that the called -function fails, it should return an error value but not set an -condition --- one is already set. The caller is then supposed to also -return an error indication to *its* caller, again *without* calling -\code{err_setstr()}, and so on --- the most detailed cause of the error -was already reported by the function that detected it in the first -place. Once the error has reached Python's interpreter main loop, -this aborts the currently executing Python code and tries to find an -exception handler specified by the Python programmer. - -To ignore an exception set by a function call that failed, the -exception condition must be cleared explicitly by calling -\code{err_clear()}. The only time C code should call -\code{err_clear()} is if it doesn't want to pass the error on to the -interpreter but wants to handle it completely by itself (e.g. by -trying something else or pretending nothing happened). - -Finally, the function \code{err_get()} gives you both error variables -*and clears them*. Note that even if an error occurred the second one -may be NULL. I doubt you will need to use this function. - -Note that a failing \code{malloc()} call must also be turned into an -exception --- the direct caller of \code{malloc()} (or -\code{realloc()}) must call \code{err_nomem()} and return a failure -indicator itself. All the object-creating functions -(\code{newintobject()} etc.) already do this, so only if you call -\code{malloc()} directly this note is of importance. - -Also note that, with the important exception of \code{getargs()}, functions -that return an integer status usually use 0 for success and -1 for -failure. - -Finally, be careful about cleaning up garbage (making appropriate -[\code{X}]\code{DECREF()} calls) when you return an error! - - -\section{Back to the example} - -Going back to posix_system, you should now be able to understand this -bit: - -\begin{verbatim} - if (!getargs(args, "s", &command)) - return NULL; -\end{verbatim} - -It returns NULL (the error indicator for functions of this kind) if an -error is detected in the argument list, relying on the exception set -by \code{getargs()}. The string value of the argument is now copied to the -local variable 'command'. - -If a Python function is called with multiple arguments, the argument -list is turned into a tuple. Python programs can us this feature, for -instance, to explicitly create the tuple containing the arguments -first and make the call later. - -The next statement in posix_system is a call tothe C library function -\code{system()}, passing it the string we just got from \code{getargs()}: - -\begin{verbatim} - sts = system(command); -\end{verbatim} - -Python strings may contain internal null bytes; but if these occur in -this example the rest of the string will be ignored by \code{system()}. - -Finally, posix.\code{system()} must return a value: the integer status -returned by the C library \code{system()} function. This is done by the -function \code{newintobject()}, which takes a (long) integer as parameter. - -\begin{verbatim} - return newintobject((long)sts); -\end{verbatim} - -(Yes, even integers are represented as objects on the heap in Python!) -If you had a function that returned no useful argument, you would need -this idiom: - -\begin{verbatim} - INCREF(None); - return None; -\end{verbatim} - -'None' is a unique Python object representing 'no value'. It differs -from NULL, which means 'error' in most contexts (except when passed as -a function argument --- there it means 'no arguments'). - - -\section{The module's function table} - -I promised to show how I made the function \code{posix_system()} -available to Python programs. This is shown later in posixmodule.c: - -\begin{verbatim} - static struct methodlist posix_methods[] = { - ... - {"system", posix_system}, - ... - {NULL, NULL} /* Sentinel */ - }; - - void - initposix() - { - (void) initmodule("posix", posix_methods); - } -\end{verbatim} - -(The actual \code{initposix()} is somewhat more complicated, but most -extension modules are indeed as simple as that.) When the Python -program first imports module 'posix', \code{initposix()} is called, -which calls \code{initmodule()} with specific parameters. This -creates a module object (which is inserted in the table sys.modules -under the key 'posix'), and adds built-in-function objects to the -newly created module based upon the table (of type struct methodlist) -that was passed as its second parameter. The function -\code{initmodule()} returns a pointer to the module object that it -creates, but this is unused here. It aborts with a fatal error if the -module could not be initialized satisfactorily. - - -\section{Calling the module initialization function} - -There is one more thing to do: telling the Python module to call the -\code{initfoo()} function when it encounters an 'import foo' statement. -This is done in the file config.c. This file contains a table mapping -module names to parameterless void function pointers. You need to add -a declaration of \code{initfoo()} somewhere early in the file, and a -line saying - -\begin{verbatim} - {"foo", initfoo}, -\end{verbatim} - -to the initializer for inittab[]. It is conventional to include both -the declaration and the initializer line in preprocessor commands -\code{\#ifdef USE_FOO} / \code{\#endif}, to make it easy to turn the -foo extension on or off. Note that the Macintosh version uses a -different configuration file, distributed as configmac.c. This -strategy may be extended to other operating system versions, although -usually the standard config.c file gives a pretty useful starting -point for a new config*.c file. - -And, of course, I forgot the Makefile. This is actually not too hard, -just follow the examples for, say, AMOEBA. Just find all occurrences -of the string AMOEBA in the Makefile and do the same for FOO that's -done for AMOEBA... - -(Note: if you are using dynamic loading for your extension, you don't -need to edit config.c and the Makefile. See \file{./DYNLOAD} for more -info about this.) - - -\section{Calling Python functions from C} - -The above concentrates on making C functions accessible to the Python -programmer. The reverse is also often useful: calling Python -functions from C. This is especially the case for libraries that -support so-called `callback' functions. If a C interface makes heavy -use of callbacks, the equivalent Python often needs to provide a -callback mechanism to the Python programmer; the implementation may -require calling the Python callback functions from a C callback. -Other uses are also possible. - -Fortunately, the Python interpreter is easily called recursively, and -there is a standard interface to call a Python function. I won't -dwell on how to call the Python parser with a particular string as -input --- if you're interested, have a look at the implementation of -the \samp{-c} command line option in pythonmain.c. - -Calling a Python function is easy. First, the Python program must -somehow pass you the Python function object. You should provide a -function (or some other interface) to do this. When this function is -called, save a pointer to the Python function object (be careful to -INCREF it!) in a global variable --- or whereever you see fit. -For example, the following function might be part of a module -definition: - -\begin{verbatim} - static object *my_callback; - - static object * - my_set_callback(dummy, arg) - object *dummy, *arg; - { - XDECREF(my_callback); /* Dispose of previous callback */ - my_callback = arg; - XINCREF(my_callback); /* Remember new callback */ - /* Boilerplate for "void" return */ - INCREF(None); - return None; - } -\end{verbatim} - -Later, when it is time to call the function, you call the C function -\code{call_object()}. This function has two arguments, both pointers -to arbitrary Python objects: the Python function, and the argument. -The argument can be NULL to call the function without arguments. For -example: - -\begin{verbatim} - object *result; - ... - /* Time to call the callback */ - result = call_object(my_callback, (object *)NULL); -\end{verbatim} - -\code{call_object()} returns a Python object pointer: this is -the return value of the Python function. \code{call_object()} is -`reference-count-neutral' with respect to its arguments, but the -return value is `new': either it is a brand new object, or it is an -existing object whose reference count has been incremented. So, you -should somehow apply DECREF to the result, even (especially!) if you -are not interested in its value. - -Before you do this, however, it is important to check that the return -value isn't NULL. If it is, the Python function terminated by raising -an exception. If the C code that called \code{call_object()} is -called from Python, it should now return an error indication to its -Python caller, so the interpreter can print a stack trace, or the -calling Python code can handle the exception. If this is not possible -or desirable, the exception should be cleared by calling -\code{err_clear()}. For example: - -\begin{verbatim} - if (result == NULL) - return NULL; /* Pass error back */ - /* Here maybe use the result */ - DECREF(result); -\end{verbatim} - -Depending on the desired interface to the Python callback function, -you may also have to provide an argument to \code{call_object()}. In -some cases the argument is also provided by the Python program, -through the same interface that specified the callback function. It -can then be saved and used in the same manner as the function object. -In other cases, you may have to construct a new object to pass as -argument. In this case you must dispose of it as well. For example, -if you want to pass an integral event code, you might use the -following code: - -\begin{verbatim} - object *argument; - ... - argument = newintobject((long)eventcode); - result = call_object(my_callback, argument); - DECREF(argument); - if (result == NULL) - return NULL; /* Pass error back */ - /* Here maybe use the result */ - DECREF(result); -\end{verbatim} - -Note the placement of DECREF(argument) immediately after the call, -before the error check! Also note that strictly spoken this code is -not complete: \code{newintobject()} may run out of memory, and this -should be checked. - -In even more complicated cases you may want to pass the callback -function multiple arguments. To this end you have to construct (and -dispose of!) a tuple object. Details (mostly concerned with the -errror checks and reference count manipulation) are left as an -exercise for the reader; most of this is also needed when returning -multiple values from a function. - -XXX TO DO: explain objects. - -XXX TO DO: defining new object types. - - -\section{Format strings for {\tt getargs()}} - -The \code{getargs()} function is declared in \file{modsupport.h} as -follows: - -\begin{verbatim} - int getargs(object *arg, char *format, ...); -\end{verbatim} - -The remaining arguments must be addresses of variables whose type is -determined by the format string. For the conversion to succeed, the -`arg' object must match the format and the format must be exhausted. -Note that while \code{getargs()} checks that the Python object really -is of the specified type, it cannot check that the addresses provided -in the call match: if you make mistakes there, your code will probably -dump core. - -A format string consists of a single `format unit'. A format unit -describes one Python object; it is usually a single character or a -parenthesized string. The type of a format units is determined from -its first character, the `format letter': - -\begin{description} - -\item[\samp{s} (string)] -The Python object must be a string object. The C argument must be a -char** (i.e. the address of a character pointer), and a pointer to -the C string contained in the Python object is stored into it. If the -next character in the format string is \samp{\#}, another C argument -of type int* must be present, and the length of the Python string (not -counting the trailing zero byte) is stored into it. - -\item[\samp{z} (string or zero, i.e. \code{NULL})] -Like \samp{s}, but the object may also be None. In this case the -string pointer is set to NULL and if a \samp{\#} is present the size -it set to 0. - -\item[\samp{b} (byte, i.e. char interpreted as tiny int)] -The object must be a Python integer. The C argument must be a char*. - -\item[\samp{h} (half, i.e. short)] -The object must be a Python integer. The C argument must be a short*. - -\item[\samp{i} (int)] -The object must be a Python integer. The C argument must be an int*. - -\item[\samp{l} (long)] -The object must be a (plain!) Python integer. The C argument must be -a long*. - -\item[\samp{c} (char)] -The Python object must be a string of length 1. The C argument must -be a char*. (Don't pass an int*!) - -\item[\samp{f} (float)] -The object must be a Python int or float. The C argument must be a -float*. - -\item[\samp{d} (double)] -The object must be a Python int or float. The C argument must be a -double*. - -\item[\samp{S} (string object)] -The object must be a Python string. The C argument must be an -object** (i.e. the address of an object pointer). The C program thus -gets back the actual string object that was passed, not just a pointer -to its array of characters and its size as for format character -\samp{s}. - -\item[\samp{O} (object)] -The object can be any Python object, including None, but not NULL. -The C argument must be an object**. This can be used if an argument -list must contain objects of a type for which no format letter exist: -the caller must then check that it has the right type. - -\item[\samp{(} (tuple)] -The object must be a Python tuple. Following the \samp{(} character -in the format string must come a number of format units describing the -elements of the tuple, followed by a \samp{)} character. Tuple -format units may be nested. (There are no exceptions for empty and -singleton tuples; \samp{()} specifies an empty tuple and \samp{(i)} a -singleton of one integer. Normally you don't want to use the latter, -since it is hard for the user to specify. - -\end{description} - -More format characters will probably be added as the need arises. It -should be allowed to use Python long integers whereever integers are -expected, and perform a range check. (A range check is in fact always -necessary for the \samp{b}, \samp{h} and \samp{i} format -letters, but this is currently not implemented.) - -Some example calls: - -\begin{verbatim} - int ok; - int i, j; - long k, l; - char *s; - int size; - - ok = getargs(args, "(lls)", &k, &l, &s); /* Two longs and a string */ - /* Possible Python call: f(1, 2, 'three') */ - - ok = getargs(args, "s", &s); /* A string */ - /* Possible Python call: f('whoops!') */ - - ok = getargs(args, ""); /* No arguments */ - /* Python call: f() */ - - ok = getargs(args, "((ii)s#)", &i, &j, &s, &size); - /* A pair of ints and a string, whose size is also returned */ - /* Possible Python call: f(1, 2, 'three') */ - - { - int left, top, right, bottom, h, v; - ok = getargs(args, "(((ii)(ii))(ii))", - &left, &top, &right, &bottom, &h, &v); - /* A rectangle and a point */ - /* Possible Python call: - f( ((0, 0), (400, 300)), (10, 10)) */ - } -\end{verbatim} - -Note that a format string must consist of a single unit; strings like -\samp{is} and \samp{(ii)s\#} are not valid format strings. (But -\samp{s\#} is.) - -The \code{getargs()} function does not support variable-length -argument lists. In simple cases you can fake these by trying several -calls to -\code{getargs()} until one succeeds, but you must take care to call -\code{err_clear()} before each retry. For example: - -\begin{verbatim} - static object *my_method(self, args) object *self, *args; { - int i, j, k; - - if (getargs(args, "(ii)", &i, &j)) { - k = 0; /* Use default third argument */ - } - else { - err_clear(); - if (!getargs(args, "(iii)", &i, &j, &k)) - return NULL; - } - /* ... use i, j and k here ... */ - INCREF(None); - return None; - } -\end{verbatim} - -(It is possible to think of an extension to the definition of format -strings to accomodate this directly, e.g., placing a \samp{|} in a -tuple might specify that the remaining arguments are optional. -\code{getargs()} should then return one more than the number of -variables stored into.) - -Advanced users note: If you set the `varargs' flag in the method list -for a function, the argument will always be a tuple (the `raw argument -list'). In this case you must enclose single and empty argument lists -in parentheses, e.g., \samp{(s)} and \samp{()}. - - -\section{The {\tt mkvalue()} function} - -This function is the counterpart to \code{getargs()}. It is declared -in \file{modsupport.h} as follows: - -\begin{verbatim} - object *mkvalue(char *format, ...); -\end{verbatim} - -It supports exactly the same format letters as \code{getargs()}, but -the arguments (which are input to the function, not output) must not -be pointers, just values. If a byte, short or float is passed to a -varargs function, it is widened by the compiler to int or double, so -\samp{b} and \samp{h} are treated as \samp{i} and \samp{f} is -treated as \samp{d}. \samp{S} is treated as \samp{O}, \samp{s} is -treated as \samp{z}. \samp{z\#} and \samp{s\#} are supported: a -second argument specifies the length of the data (negative means use -\code{strlen()}). \samp{S} and \samp{O} add a reference to their -argument (so you should \code{DECREF()} it if you've just created it -and aren't going to use it again). - -If the argument for \samp{O} or \samp{S} is a NULL pointer, it is -assumed that this was caused because the call producing the argument -found an error and set an exception. Therefore, \code{mkvalue()} will -return \code{NULL} but won't set an exception if one is already set. -If no exception is set, \code{SystemError} is set. - -If there is an error in the format string, the \code{SystemError} -exception is set, since it is the calling C code's fault, not that of -the Python user who sees the exception. - -Example: - -\begin{verbatim} - return mkvalue("(ii)", 0, 0); -\end{verbatim} - -returns a tuple containing two zeros. (Outer parentheses in the -format string are actually superfluous, but you can use them for -compatibility with \code{getargs()}, which requires them if more than -one argument is expected.) - - -\section{Reference counts} - -Here's a useful explanation of \code{INCREF()} and \code{DECREF()} -(after an original by Sjoerd Mullender). - -Use \code{XINCREF()} or \code{XDECREF()} instead of \code{INCREF()} / -\code{DECREF()} when the argument may be \code{NULL}. - -The basic idea is, if you create an extra reference to an object, you -must \code{INCREF()} it, if you throw away a reference to an object, -you must \code{DECREF()} it. Functions such as -\code{newstringobject()}, \code{newsizedstringobject()}, -\code{newintobject()}, etc. create a reference to an object. If you -want to throw away the object thus created, you must use -\code{DECREF()}. - -If you put an object into a tuple or list using \code{settupleitem()} -or \code{setlistitem()}, the idea is that you usually don't want to -keep a reference of your own around, so Python does not -\code{INCREF()} the elements. It does \code{DECREF()} the old value. -This means that if you put something into such an object using the -functions Python provides for this, you must \code{INCREF()} the -object if you also want to keep a separate reference to the object around. -Also, if you replace an element, you should \code{INCREF()} the old -element first if you want to keep it. If you didn't \code{INCREF()} -it before you replaced it, you are not allowed to look at it anymore, -since it may have been freed. - -Returning an object to Python (i.e. when your C function returns) -creates a reference to an object, but it does not change the reference -count. When your code does not keep another reference to the object, -you should not \code{INCREF()} or \code{DECREF()} it (assuming it is a -newly created object). When you do keep a reference around, you -should \code{INCREF()} the object. Also, when you return a global -object such as \code{None}, you should \code{INCREF()} it. - -If you want to return a tuple, you should consider using -\code{mkvalue()}. This function creates a new tuple with a reference -count of 1 which you can return. If any of the elements you put into -the tuple are objects (format codes \samp{O} or \samp{S}), they -are \code{INCREF()}'ed by \code{mkvalue()}. If you don't want to keep -references to those elements around, you should \code{DECREF()} them -after having called \code{mkvalue()}. - -Usually you don't have to worry about arguments. They are -\code{INCREF()}'ed before your function is called and -\code{DECREF()}'ed after your function returns. When you keep a -reference to an argument, you should \code{INCREF()} it and -\code{DECREF()} when you throw it away. Also, when you return an -argument, you should \code{INCREF()} it, because returning the -argument creates an extra reference to it. - -If you use \code{getargs()} to parse the arguments, you can get a -reference to an object (by using \samp{O} in the format string). This -object was not \code{INCREF()}'ed, so you should not \code{DECREF()} -it. If you want to keep the object, you must \code{INCREF()} it -yourself. - -If you create your own type of objects, you should use \code{NEWOBJ()} -to create the object. This sets the reference count to 1. If you -want to throw away the object, you should use \code{DECREF()}. When -the reference count reaches zero, your type's \code{dealloc()} -function is called. In it, you should \code{DECREF()} all object to -which you keep references in your object, but you should not use -\code{DECREF()} on your object. You should use \code{DEL()} instead. - - -\section{Using C++} - -It is possible to write extension modules in C++. Some restrictions -apply: since the main program (the Python interpreter) is compiled and -linked by the C compiler, global or static objects with constructors -cannot be used. All functions that will be called directly or -indirectly (i.e. via function pointers) by the Python interpreter will -have to be declared using \code{extern "C"}; this applies to all -`methods' as well as to the module's initialization function. -It is unnecessary to enclose the Python header files in -\code{extern "C" \{...\}} --- they do this already. - - -\chapter{Embedding Python in another application} - -Embedding Python is similar to extending it, but not quite. The -difference is that when you extend Python, the main program of the -application is still the Python interpreter, while of you embed -Python, the main program may have nothing to do with Python --- -instead, some parts of the application occasionally call the Python -interpreter to run some Python code. - -So if you are embedding Python, you are providing your own main -program. One of the things this main program has to do is initialize -the Python interpreter. At the very least, you have to call the -function \code{initall()}. There are optional calls to pass command -line arguments to Python. Then later you can call the interpreter -from any part of the application. - -There are several different ways to call the interpreter: you can pass -a string containing Python statements to \code{run_command()}, or you -can pass a stdio file pointer and a file name (for identification in -error messages only) to \code{run_script()}. You can also call the -lower-level operations described in the previous chapters to construct -and use Python objects. - -A simple demo of embedding Python can be found in the directory -\file{/embed}. - - -\section{Using C++} - -It is also possible to embed Python in a C++ program; how this is done -exactly will depend on the details of the C++ system used; in general -you will need to write the main program in C++, and use the C++ -compiler to compile and link your program. There is no need to -recompile Python itself with C++. - - -\chapter{Dynamic Loading} - -On some systems (e.g., SunOS, SGI Irix) it is possible to configure -Python to support dynamic loading of modules implemented in C. Once -configured and installed it's trivial to use: if a Python program -executes \code{import foo}, the search for modules tries to find a -file \file{foomodule.o} in the module search path, and if one is -found, it is linked with the executing binary and executed. Once -linked, the module acts just like a built-in module. - -The advantages of dynamic loading are twofold: the `core' Python -binary gets smaller, and users can extend Python with their own -modules implemented in C without having to build and maintain their -own copy of the Python interpreter. There are also disadvantages: -dynamic loading isn't available on all systems (this just means that -on some systems you have to use static loading), and dynamically -loading a module that was compiled for a different version of Python -(e.g., with a different representation of objects) may dump core. - -{\bf NEW:} Under SunOS, dynamic loading now uses SunOS shared -libraries and is always configured. See at the end of this chapter -for how to create a dynamically loadable module. - - -\section{Configuring and building the interpreter for dynamic loading} - -(Ignore this section for SunOS --- on SunOS dynamic loading is always -configured.) - -Dynamic loading is a little complicated to configure, since its -implementation is extremely system dependent, and there are no -really standard libraries or interfaces for it. I'm using an -extremely simple interface, which basically needs only one function: - -\begin{verbatim} - funcptr = dl_loadmod(binary, object, function) -\end{verbatim} - -where \code{binary} is the pathname of the currently executing program -(not just \code{argv[0]}!), \code{object} is the name of the \samp{.o} -file to be dynamically loaded, and \code{function} is the name of a -function in the module. If the dynamic loading succeeds, -\code{dl_loadmod()} returns a pointer to the named function; if not, it -returns \code{NULL}. - -I provide two implementations of \code{dl_loadmod()}: one for SGI machines -running Irix 4.0 (written by my colleague Jack Jansen), and one that -is a thin interface layer for Wilson Ho's (GNU) dynamic loading -package \dfn{dld} (version 3.2.3). Dld implements a much more powerful -version of dynamic loading than needed (including unlinking), but it -does not support System V's COFF object file format. It currently -supports only VAX (Ultrix), Sun 3 (SunOS 3.4 and 4.0), SPARCstation -(SunOS 4.0), Sequent Symmetry (Dynix), and Atari ST (from the dld -3.2.3 README file). Dld is part of the standard Python distribution; -if you didn't get it,many ftp archive sites carry dld these days, so -it won't be hard to get hold of it if you need it (using archie). - -(If you don't know where to get dld, try anonymous ftp to -\file{wuarchive.wustl.edu:/mirrors2/gnu/dld-3.2.3.tar.Z}. Jack's dld -can be found at \file{ftp.cwi.nl:/pub/python/dl.tar.Z}.) - -To build a Python interpreter capable of dynamic loading, you need to -edit the Makefile. Basically you must uncomment the lines starting -with \samp{\#DL_}, but you must also edit some of the lines to choose -which version of dl_loadmod to use, and fill in the pathname of the dld -library if you use it. And, of course, you must first build -dl_loadmod and dld, if used. (This is now done through the Configure -script. For SunOS, everything is now automatic as long as the -architecture type is \code{sun4}.) - - -\section{Building a dynamically loadable module} - -Building an object file usable by dynamic loading is easy, if you -follow these rules (substitute your module name for \code{foo} -everywhere): - -\begin{itemize} - -\item -The source filename must be \file{foomodule.c}, so the object -name is \file{foomodule.o}. - -\item -The module must be written as a (statically linked) Python extension -module (described in an earlier chapter) except that no line for it -must be added to \file{config.c} and it mustn't be linked with the -main Python interpreter. - -\item -The module's initialization function must be called \code{initfoo}; it -must install the module in \code{sys.modules} (generally by calling -\code{initmodule()} as explained earlier. - -\item -The module must be compiled with \samp{-c}. The resulting .o file must -not be stripped. - -\item -Since the module must include many standard Python include files, it -must be compiled with a \samp{-I} option pointing to the Python source -directory (unless it resides there itself). - -\item -On SGI Irix, the compiler flag \samp{-G0} (or \samp{-G 0}) must be passed. -IF THIS IS NOT DONE THE RESULTING CODE WILL NOT WORK. - -\item -{\bf NEW:} On SunOS, you must create a shared library from your \samp{.o} -file using the following command (assuming your module is called -\code{foo}): - -\begin{verbatim} - ld -o foomodule.so foomodule.o -\end{verbatim} - -and place the resulting \samp{.so} file in the Python search path (not -the \samp{.o} file). Note: on Solaris, you need to pass \samp{-G} to -the loader. - -\end{itemize} - - -\section{Using libraries} - -If your dynamically loadable module needs to be linked with one or -more libraries that aren't linked with Python (or if it needs a -routine that isn't used by Python from one of the libraries with which -Python is linked), you must specify a list of libraries to search -after loading the module in a file with extension \samp{.libs} (and -otherwise the same as your \samp{.o} file). This file should contain -one or more lines containing whitespace-separated absolute library -pathnames. When using the dl interface, \samp{-l...} flags may also -be used (it is in fact passed as an option list to the system linker -ld(1)), but the dl-dld interface requires absolute pathnames. I -believe it is possible to specify shared libraries here. - -(On SunOS, any extra libraries must be specified on the \code{ld} -command that creates the \samp{.so} file.) - - -\section{Caveats} - -Dynamic loading requires that \code{main}'s \code{argv[0]} contains -the pathname or at least filename of the Python interpreter. -Unfortunately, when executing a directly executable Python script (an -executable file with \samp{\#!...} on the first line), the kernel -overwrites \code{argv[0]} with the name of the script. There is no -easy way around this, so executable Python scripts cannot use -dynamically loaded modules. (You can always write a simple shell -script that calls the Python interpreter with the script as its -input.) - -When using dl, the overlay is first converted into an `overlay' for -the current process by the system linker (\code{ld}). The overlay is -saved as a file with extension \samp{.ld}, either in the directory -where the \samp{.o} file lives or (if that can't be written) in a -temporary directory. An existing \samp{.ld} file resulting from a -previous run (not from a temporary directory) is used, bypassing the -(costly) linking phase, provided its version matches the \samp{.o} -file and the current binary. (See the \code{dl} man page for more -details.) - - -\input{ext.ind} - -\end{document} diff --git a/Doc/ext/ext.tex b/Doc/ext/ext.tex deleted file mode 100644 index 18c801527f..0000000000 --- a/Doc/ext/ext.tex +++ /dev/null @@ -1,914 +0,0 @@ -\documentstyle[twoside,11pt,myformat,times]{report} - -\title{\bf Extending and Embedding the Python Interpreter} - -\author{ - Guido van Rossum \\ - Dept. CST, CWI, P.O. Box 94079 \\ - 1090 GB Amsterdam, The Netherlands \\ - E-mail: {\tt guido@cwi.nl} -} - -\date{19 November 1993 \\ Release 0.9.9.++} % XXX update before release! - -% Tell \index to actually write the .idx file -\makeindex - -\begin{document} - -\pagenumbering{roman} - -\maketitle - -\begin{abstract} - -\noindent -This document describes how to write modules in C or C++ to extend the -Python interpreter. It also describes how to use Python as an -`embedded' language, and how extension modules can be loaded -dynamically (at run time) into the interpreter, if the operating -system supports this feature. - -\end{abstract} - -\pagebreak - -{ -\parskip = 0mm -\tableofcontents -} - -\pagebreak - -\pagenumbering{arabic} - - -\chapter{Extending Python with C or C++ code} - - -\section{Introduction} - -It is quite easy to add non-standard built-in modules to Python, if -you know how to program in C. A built-in module known to the Python -programmer as \code{foo} is generally implemented by a file called -\file{foomodule.c}. All but the most essential standard built-in -modules also adhere to this convention, and in fact some of them form -excellent examples of how to create an extension. - -Extension modules can do two things that can't be done directly in -Python: they can implement new data types, and they can make system -calls or call C library functions. Since the latter is usually the -most important reason for adding an extension, I'll concentrate on -adding `wrappers' around C library functions; the concrete example -uses the wrapper for -\code{system()} in module \code{posix}, found in (of course) the file -\file{posixmodule.c}. - -It is important not to be impressed by the size and complexity of -the average extension module; much of this is straightforward -`boilerplate' code (starting right with the copyright notice)! - -Let's skip the boilerplate and have a look at an interesting function -in \file{posixmodule.c} first: - -\begin{verbatim} - static object * - posix_system(self, args) - object *self; - object *args; - { - char *command; - int sts; - if (!getargs(args, "s", &command)) - return NULL; - sts = system(command); - return mkvalue("i", sts); - } -\end{verbatim} - -This is the prototypical top-level function in an extension module. -It will be called (we'll see later how this is made possible) when the -Python program executes statements like - -\begin{verbatim} - >>> import posix - >>> sts = posix.system('ls -l') -\end{verbatim} - -There is a straightforward translation from the arguments to the call -in Python (here the single value \code{'ls -l'}) to the arguments that -are passed to the C function. The C function always has two -parameters, conventionally named \var{self} and \var{args}. In this -example, \var{self} will always be a \code{NULL} pointer, since this is a -function, not a method (this is done so that the interpreter doesn't -have to understand two different types of C functions). - -The \var{args} parameter will be a pointer to a Python object, or -\code{NULL} if the Python function/method was called without -arguments. It is necessary to do full argument type checking on each -call, since otherwise the Python user would be able to cause the -Python interpreter to `dump core' by passing the wrong arguments to a -function in an extension module (or no arguments at all). Because -argument checking and converting arguments to C is such a common task, -there's a general function in the Python interpreter which combines -these tasks: \code{getargs()}. It uses a template string to determine -both the types of the Python argument and the types of the C variables -into which it should store the converted values. (More about this -later.)\footnote{ -There are convenience macros \code{getstrarg()}, -\code{getintarg()}, etc., for many common forms of \code{getargs()} -templates. These are relics from the past; it's better to call -\code{getargs()} directly.} - -If \code{getargs()} returns nonzero, the argument list has the right -type and its components have been stored in the variables whose -addresses are passed. If it returns zero, an error has occurred. In -the latter case it has already raised an appropriate exception by -calling \code{err_setstr()}, so the calling function can just return -\code{NULL}. - - -\section{Intermezzo: errors and exceptions} - -An important convention throughout the Python interpreter is the -following: when a function fails, it should set an exception condition -and return an error value (often a NULL pointer). Exceptions are set -in a global variable in the file errors.c; if this variable is NULL no -exception has occurred. A second variable is the `associated value' -of the exception. - -The file errors.h declares a host of err_* functions to set various -types of exceptions. The most common one is \code{err_setstr()} --- its -arguments are an exception object (e.g. RuntimeError --- actually it -can be any string object) and a C string indicating the cause of the -error (this is converted to a string object and stored as the -`associated value' of the exception). Another useful function is -\code{err_errno()}, which only takes an exception argument and -constructs the associated value by inspection of the (UNIX) global -variable errno. - -You can test non-destructively whether an exception has been set with -\code{err_occurred()}. However, most code never calls -\code{err_occurred()} to see whether an error occurred or not, but -relies on error return values from the functions it calls instead: - -When a function that calls another function detects that the called -function fails, it should return an error value but not set an -condition --- one is already set. The caller is then supposed to also -return an error indication to *its* caller, again *without* calling -\code{err_setstr()}, and so on --- the most detailed cause of the error -was already reported by the function that detected it in the first -place. Once the error has reached Python's interpreter main loop, -this aborts the currently executing Python code and tries to find an -exception handler specified by the Python programmer. - -To ignore an exception set by a function call that failed, the -exception condition must be cleared explicitly by calling -\code{err_clear()}. The only time C code should call -\code{err_clear()} is if it doesn't want to pass the error on to the -interpreter but wants to handle it completely by itself (e.g. by -trying something else or pretending nothing happened). - -Finally, the function \code{err_get()} gives you both error variables -*and clears them*. Note that even if an error occurred the second one -may be NULL. I doubt you will need to use this function. - -Note that a failing \code{malloc()} call must also be turned into an -exception --- the direct caller of \code{malloc()} (or -\code{realloc()}) must call \code{err_nomem()} and return a failure -indicator itself. All the object-creating functions -(\code{newintobject()} etc.) already do this, so only if you call -\code{malloc()} directly this note is of importance. - -Also note that, with the important exception of \code{getargs()}, functions -that return an integer status usually use 0 for success and -1 for -failure. - -Finally, be careful about cleaning up garbage (making appropriate -[\code{X}]\code{DECREF()} calls) when you return an error! - - -\section{Back to the example} - -Going back to posix_system, you should now be able to understand this -bit: - -\begin{verbatim} - if (!getargs(args, "s", &command)) - return NULL; -\end{verbatim} - -It returns NULL (the error indicator for functions of this kind) if an -error is detected in the argument list, relying on the exception set -by \code{getargs()}. The string value of the argument is now copied to the -local variable 'command'. - -If a Python function is called with multiple arguments, the argument -list is turned into a tuple. Python programs can us this feature, for -instance, to explicitly create the tuple containing the arguments -first and make the call later. - -The next statement in posix_system is a call tothe C library function -\code{system()}, passing it the string we just got from \code{getargs()}: - -\begin{verbatim} - sts = system(command); -\end{verbatim} - -Python strings may contain internal null bytes; but if these occur in -this example the rest of the string will be ignored by \code{system()}. - -Finally, posix.\code{system()} must return a value: the integer status -returned by the C library \code{system()} function. This is done by the -function \code{newintobject()}, which takes a (long) integer as parameter. - -\begin{verbatim} - return newintobject((long)sts); -\end{verbatim} - -(Yes, even integers are represented as objects on the heap in Python!) -If you had a function that returned no useful argument, you would need -this idiom: - -\begin{verbatim} - INCREF(None); - return None; -\end{verbatim} - -'None' is a unique Python object representing 'no value'. It differs -from NULL, which means 'error' in most contexts (except when passed as -a function argument --- there it means 'no arguments'). - - -\section{The module's function table} - -I promised to show how I made the function \code{posix_system()} -available to Python programs. This is shown later in posixmodule.c: - -\begin{verbatim} - static struct methodlist posix_methods[] = { - ... - {"system", posix_system}, - ... - {NULL, NULL} /* Sentinel */ - }; - - void - initposix() - { - (void) initmodule("posix", posix_methods); - } -\end{verbatim} - -(The actual \code{initposix()} is somewhat more complicated, but most -extension modules are indeed as simple as that.) When the Python -program first imports module 'posix', \code{initposix()} is called, -which calls \code{initmodule()} with specific parameters. This -creates a module object (which is inserted in the table sys.modules -under the key 'posix'), and adds built-in-function objects to the -newly created module based upon the table (of type struct methodlist) -that was passed as its second parameter. The function -\code{initmodule()} returns a pointer to the module object that it -creates, but this is unused here. It aborts with a fatal error if the -module could not be initialized satisfactorily. - - -\section{Calling the module initialization function} - -There is one more thing to do: telling the Python module to call the -\code{initfoo()} function when it encounters an 'import foo' statement. -This is done in the file config.c. This file contains a table mapping -module names to parameterless void function pointers. You need to add -a declaration of \code{initfoo()} somewhere early in the file, and a -line saying - -\begin{verbatim} - {"foo", initfoo}, -\end{verbatim} - -to the initializer for inittab[]. It is conventional to include both -the declaration and the initializer line in preprocessor commands -\code{\#ifdef USE_FOO} / \code{\#endif}, to make it easy to turn the -foo extension on or off. Note that the Macintosh version uses a -different configuration file, distributed as configmac.c. This -strategy may be extended to other operating system versions, although -usually the standard config.c file gives a pretty useful starting -point for a new config*.c file. - -And, of course, I forgot the Makefile. This is actually not too hard, -just follow the examples for, say, AMOEBA. Just find all occurrences -of the string AMOEBA in the Makefile and do the same for FOO that's -done for AMOEBA... - -(Note: if you are using dynamic loading for your extension, you don't -need to edit config.c and the Makefile. See \file{./DYNLOAD} for more -info about this.) - - -\section{Calling Python functions from C} - -The above concentrates on making C functions accessible to the Python -programmer. The reverse is also often useful: calling Python -functions from C. This is especially the case for libraries that -support so-called `callback' functions. If a C interface makes heavy -use of callbacks, the equivalent Python often needs to provide a -callback mechanism to the Python programmer; the implementation may -require calling the Python callback functions from a C callback. -Other uses are also possible. - -Fortunately, the Python interpreter is easily called recursively, and -there is a standard interface to call a Python function. I won't -dwell on how to call the Python parser with a particular string as -input --- if you're interested, have a look at the implementation of -the \samp{-c} command line option in pythonmain.c. - -Calling a Python function is easy. First, the Python program must -somehow pass you the Python function object. You should provide a -function (or some other interface) to do this. When this function is -called, save a pointer to the Python function object (be careful to -INCREF it!) in a global variable --- or whereever you see fit. -For example, the following function might be part of a module -definition: - -\begin{verbatim} - static object *my_callback; - - static object * - my_set_callback(dummy, arg) - object *dummy, *arg; - { - XDECREF(my_callback); /* Dispose of previous callback */ - my_callback = arg; - XINCREF(my_callback); /* Remember new callback */ - /* Boilerplate for "void" return */ - INCREF(None); - return None; - } -\end{verbatim} - -Later, when it is time to call the function, you call the C function -\code{call_object()}. This function has two arguments, both pointers -to arbitrary Python objects: the Python function, and the argument. -The argument can be NULL to call the function without arguments. For -example: - -\begin{verbatim} - object *result; - ... - /* Time to call the callback */ - result = call_object(my_callback, (object *)NULL); -\end{verbatim} - -\code{call_object()} returns a Python object pointer: this is -the return value of the Python function. \code{call_object()} is -`reference-count-neutral' with respect to its arguments, but the -return value is `new': either it is a brand new object, or it is an -existing object whose reference count has been incremented. So, you -should somehow apply DECREF to the result, even (especially!) if you -are not interested in its value. - -Before you do this, however, it is important to check that the return -value isn't NULL. If it is, the Python function terminated by raising -an exception. If the C code that called \code{call_object()} is -called from Python, it should now return an error indication to its -Python caller, so the interpreter can print a stack trace, or the -calling Python code can handle the exception. If this is not possible -or desirable, the exception should be cleared by calling -\code{err_clear()}. For example: - -\begin{verbatim} - if (result == NULL) - return NULL; /* Pass error back */ - /* Here maybe use the result */ - DECREF(result); -\end{verbatim} - -Depending on the desired interface to the Python callback function, -you may also have to provide an argument to \code{call_object()}. In -some cases the argument is also provided by the Python program, -through the same interface that specified the callback function. It -can then be saved and used in the same manner as the function object. -In other cases, you may have to construct a new object to pass as -argument. In this case you must dispose of it as well. For example, -if you want to pass an integral event code, you might use the -following code: - -\begin{verbatim} - object *argument; - ... - argument = newintobject((long)eventcode); - result = call_object(my_callback, argument); - DECREF(argument); - if (result == NULL) - return NULL; /* Pass error back */ - /* Here maybe use the result */ - DECREF(result); -\end{verbatim} - -Note the placement of DECREF(argument) immediately after the call, -before the error check! Also note that strictly spoken this code is -not complete: \code{newintobject()} may run out of memory, and this -should be checked. - -In even more complicated cases you may want to pass the callback -function multiple arguments. To this end you have to construct (and -dispose of!) a tuple object. Details (mostly concerned with the -errror checks and reference count manipulation) are left as an -exercise for the reader; most of this is also needed when returning -multiple values from a function. - -XXX TO DO: explain objects. - -XXX TO DO: defining new object types. - - -\section{Format strings for {\tt getargs()}} - -The \code{getargs()} function is declared in \file{modsupport.h} as -follows: - -\begin{verbatim} - int getargs(object *arg, char *format, ...); -\end{verbatim} - -The remaining arguments must be addresses of variables whose type is -determined by the format string. For the conversion to succeed, the -`arg' object must match the format and the format must be exhausted. -Note that while \code{getargs()} checks that the Python object really -is of the specified type, it cannot check that the addresses provided -in the call match: if you make mistakes there, your code will probably -dump core. - -A format string consists of a single `format unit'. A format unit -describes one Python object; it is usually a single character or a -parenthesized string. The type of a format units is determined from -its first character, the `format letter': - -\begin{description} - -\item[\samp{s} (string)] -The Python object must be a string object. The C argument must be a -char** (i.e. the address of a character pointer), and a pointer to -the C string contained in the Python object is stored into it. If the -next character in the format string is \samp{\#}, another C argument -of type int* must be present, and the length of the Python string (not -counting the trailing zero byte) is stored into it. - -\item[\samp{z} (string or zero, i.e. \code{NULL})] -Like \samp{s}, but the object may also be None. In this case the -string pointer is set to NULL and if a \samp{\#} is present the size -it set to 0. - -\item[\samp{b} (byte, i.e. char interpreted as tiny int)] -The object must be a Python integer. The C argument must be a char*. - -\item[\samp{h} (half, i.e. short)] -The object must be a Python integer. The C argument must be a short*. - -\item[\samp{i} (int)] -The object must be a Python integer. The C argument must be an int*. - -\item[\samp{l} (long)] -The object must be a (plain!) Python integer. The C argument must be -a long*. - -\item[\samp{c} (char)] -The Python object must be a string of length 1. The C argument must -be a char*. (Don't pass an int*!) - -\item[\samp{f} (float)] -The object must be a Python int or float. The C argument must be a -float*. - -\item[\samp{d} (double)] -The object must be a Python int or float. The C argument must be a -double*. - -\item[\samp{S} (string object)] -The object must be a Python string. The C argument must be an -object** (i.e. the address of an object pointer). The C program thus -gets back the actual string object that was passed, not just a pointer -to its array of characters and its size as for format character -\samp{s}. - -\item[\samp{O} (object)] -The object can be any Python object, including None, but not NULL. -The C argument must be an object**. This can be used if an argument -list must contain objects of a type for which no format letter exist: -the caller must then check that it has the right type. - -\item[\samp{(} (tuple)] -The object must be a Python tuple. Following the \samp{(} character -in the format string must come a number of format units describing the -elements of the tuple, followed by a \samp{)} character. Tuple -format units may be nested. (There are no exceptions for empty and -singleton tuples; \samp{()} specifies an empty tuple and \samp{(i)} a -singleton of one integer. Normally you don't want to use the latter, -since it is hard for the user to specify. - -\end{description} - -More format characters will probably be added as the need arises. It -should be allowed to use Python long integers whereever integers are -expected, and perform a range check. (A range check is in fact always -necessary for the \samp{b}, \samp{h} and \samp{i} format -letters, but this is currently not implemented.) - -Some example calls: - -\begin{verbatim} - int ok; - int i, j; - long k, l; - char *s; - int size; - - ok = getargs(args, "(lls)", &k, &l, &s); /* Two longs and a string */ - /* Possible Python call: f(1, 2, 'three') */ - - ok = getargs(args, "s", &s); /* A string */ - /* Possible Python call: f('whoops!') */ - - ok = getargs(args, ""); /* No arguments */ - /* Python call: f() */ - - ok = getargs(args, "((ii)s#)", &i, &j, &s, &size); - /* A pair of ints and a string, whose size is also returned */ - /* Possible Python call: f(1, 2, 'three') */ - - { - int left, top, right, bottom, h, v; - ok = getargs(args, "(((ii)(ii))(ii))", - &left, &top, &right, &bottom, &h, &v); - /* A rectangle and a point */ - /* Possible Python call: - f( ((0, 0), (400, 300)), (10, 10)) */ - } -\end{verbatim} - -Note that a format string must consist of a single unit; strings like -\samp{is} and \samp{(ii)s\#} are not valid format strings. (But -\samp{s\#} is.) - -The \code{getargs()} function does not support variable-length -argument lists. In simple cases you can fake these by trying several -calls to -\code{getargs()} until one succeeds, but you must take care to call -\code{err_clear()} before each retry. For example: - -\begin{verbatim} - static object *my_method(self, args) object *self, *args; { - int i, j, k; - - if (getargs(args, "(ii)", &i, &j)) { - k = 0; /* Use default third argument */ - } - else { - err_clear(); - if (!getargs(args, "(iii)", &i, &j, &k)) - return NULL; - } - /* ... use i, j and k here ... */ - INCREF(None); - return None; - } -\end{verbatim} - -(It is possible to think of an extension to the definition of format -strings to accomodate this directly, e.g., placing a \samp{|} in a -tuple might specify that the remaining arguments are optional. -\code{getargs()} should then return one more than the number of -variables stored into.) - -Advanced users note: If you set the `varargs' flag in the method list -for a function, the argument will always be a tuple (the `raw argument -list'). In this case you must enclose single and empty argument lists -in parentheses, e.g., \samp{(s)} and \samp{()}. - - -\section{The {\tt mkvalue()} function} - -This function is the counterpart to \code{getargs()}. It is declared -in \file{modsupport.h} as follows: - -\begin{verbatim} - object *mkvalue(char *format, ...); -\end{verbatim} - -It supports exactly the same format letters as \code{getargs()}, but -the arguments (which are input to the function, not output) must not -be pointers, just values. If a byte, short or float is passed to a -varargs function, it is widened by the compiler to int or double, so -\samp{b} and \samp{h} are treated as \samp{i} and \samp{f} is -treated as \samp{d}. \samp{S} is treated as \samp{O}, \samp{s} is -treated as \samp{z}. \samp{z\#} and \samp{s\#} are supported: a -second argument specifies the length of the data (negative means use -\code{strlen()}). \samp{S} and \samp{O} add a reference to their -argument (so you should \code{DECREF()} it if you've just created it -and aren't going to use it again). - -If the argument for \samp{O} or \samp{S} is a NULL pointer, it is -assumed that this was caused because the call producing the argument -found an error and set an exception. Therefore, \code{mkvalue()} will -return \code{NULL} but won't set an exception if one is already set. -If no exception is set, \code{SystemError} is set. - -If there is an error in the format string, the \code{SystemError} -exception is set, since it is the calling C code's fault, not that of -the Python user who sees the exception. - -Example: - -\begin{verbatim} - return mkvalue("(ii)", 0, 0); -\end{verbatim} - -returns a tuple containing two zeros. (Outer parentheses in the -format string are actually superfluous, but you can use them for -compatibility with \code{getargs()}, which requires them if more than -one argument is expected.) - - -\section{Reference counts} - -Here's a useful explanation of \code{INCREF()} and \code{DECREF()} -(after an original by Sjoerd Mullender). - -Use \code{XINCREF()} or \code{XDECREF()} instead of \code{INCREF()} / -\code{DECREF()} when the argument may be \code{NULL}. - -The basic idea is, if you create an extra reference to an object, you -must \code{INCREF()} it, if you throw away a reference to an object, -you must \code{DECREF()} it. Functions such as -\code{newstringobject()}, \code{newsizedstringobject()}, -\code{newintobject()}, etc. create a reference to an object. If you -want to throw away the object thus created, you must use -\code{DECREF()}. - -If you put an object into a tuple or list using \code{settupleitem()} -or \code{setlistitem()}, the idea is that you usually don't want to -keep a reference of your own around, so Python does not -\code{INCREF()} the elements. It does \code{DECREF()} the old value. -This means that if you put something into such an object using the -functions Python provides for this, you must \code{INCREF()} the -object if you also want to keep a separate reference to the object around. -Also, if you replace an element, you should \code{INCREF()} the old -element first if you want to keep it. If you didn't \code{INCREF()} -it before you replaced it, you are not allowed to look at it anymore, -since it may have been freed. - -Returning an object to Python (i.e. when your C function returns) -creates a reference to an object, but it does not change the reference -count. When your code does not keep another reference to the object, -you should not \code{INCREF()} or \code{DECREF()} it (assuming it is a -newly created object). When you do keep a reference around, you -should \code{INCREF()} the object. Also, when you return a global -object such as \code{None}, you should \code{INCREF()} it. - -If you want to return a tuple, you should consider using -\code{mkvalue()}. This function creates a new tuple with a reference -count of 1 which you can return. If any of the elements you put into -the tuple are objects (format codes \samp{O} or \samp{S}), they -are \code{INCREF()}'ed by \code{mkvalue()}. If you don't want to keep -references to those elements around, you should \code{DECREF()} them -after having called \code{mkvalue()}. - -Usually you don't have to worry about arguments. They are -\code{INCREF()}'ed before your function is called and -\code{DECREF()}'ed after your function returns. When you keep a -reference to an argument, you should \code{INCREF()} it and -\code{DECREF()} when you throw it away. Also, when you return an -argument, you should \code{INCREF()} it, because returning the -argument creates an extra reference to it. - -If you use \code{getargs()} to parse the arguments, you can get a -reference to an object (by using \samp{O} in the format string). This -object was not \code{INCREF()}'ed, so you should not \code{DECREF()} -it. If you want to keep the object, you must \code{INCREF()} it -yourself. - -If you create your own type of objects, you should use \code{NEWOBJ()} -to create the object. This sets the reference count to 1. If you -want to throw away the object, you should use \code{DECREF()}. When -the reference count reaches zero, your type's \code{dealloc()} -function is called. In it, you should \code{DECREF()} all object to -which you keep references in your object, but you should not use -\code{DECREF()} on your object. You should use \code{DEL()} instead. - - -\section{Using C++} - -It is possible to write extension modules in C++. Some restrictions -apply: since the main program (the Python interpreter) is compiled and -linked by the C compiler, global or static objects with constructors -cannot be used. All functions that will be called directly or -indirectly (i.e. via function pointers) by the Python interpreter will -have to be declared using \code{extern "C"}; this applies to all -`methods' as well as to the module's initialization function. -It is unnecessary to enclose the Python header files in -\code{extern "C" \{...\}} --- they do this already. - - -\chapter{Embedding Python in another application} - -Embedding Python is similar to extending it, but not quite. The -difference is that when you extend Python, the main program of the -application is still the Python interpreter, while of you embed -Python, the main program may have nothing to do with Python --- -instead, some parts of the application occasionally call the Python -interpreter to run some Python code. - -So if you are embedding Python, you are providing your own main -program. One of the things this main program has to do is initialize -the Python interpreter. At the very least, you have to call the -function \code{initall()}. There are optional calls to pass command -line arguments to Python. Then later you can call the interpreter -from any part of the application. - -There are several different ways to call the interpreter: you can pass -a string containing Python statements to \code{run_command()}, or you -can pass a stdio file pointer and a file name (for identification in -error messages only) to \code{run_script()}. You can also call the -lower-level operations described in the previous chapters to construct -and use Python objects. - -A simple demo of embedding Python can be found in the directory -\file{/embed}. - - -\section{Using C++} - -It is also possible to embed Python in a C++ program; how this is done -exactly will depend on the details of the C++ system used; in general -you will need to write the main program in C++, and use the C++ -compiler to compile and link your program. There is no need to -recompile Python itself with C++. - - -\chapter{Dynamic Loading} - -On some systems (e.g., SunOS, SGI Irix) it is possible to configure -Python to support dynamic loading of modules implemented in C. Once -configured and installed it's trivial to use: if a Python program -executes \code{import foo}, the search for modules tries to find a -file \file{foomodule.o} in the module search path, and if one is -found, it is linked with the executing binary and executed. Once -linked, the module acts just like a built-in module. - -The advantages of dynamic loading are twofold: the `core' Python -binary gets smaller, and users can extend Python with their own -modules implemented in C without having to build and maintain their -own copy of the Python interpreter. There are also disadvantages: -dynamic loading isn't available on all systems (this just means that -on some systems you have to use static loading), and dynamically -loading a module that was compiled for a different version of Python -(e.g., with a different representation of objects) may dump core. - -{\bf NEW:} Under SunOS, dynamic loading now uses SunOS shared -libraries and is always configured. See at the end of this chapter -for how to create a dynamically loadable module. - - -\section{Configuring and building the interpreter for dynamic loading} - -(Ignore this section for SunOS --- on SunOS dynamic loading is always -configured.) - -Dynamic loading is a little complicated to configure, since its -implementation is extremely system dependent, and there are no -really standard libraries or interfaces for it. I'm using an -extremely simple interface, which basically needs only one function: - -\begin{verbatim} - funcptr = dl_loadmod(binary, object, function) -\end{verbatim} - -where \code{binary} is the pathname of the currently executing program -(not just \code{argv[0]}!), \code{object} is the name of the \samp{.o} -file to be dynamically loaded, and \code{function} is the name of a -function in the module. If the dynamic loading succeeds, -\code{dl_loadmod()} returns a pointer to the named function; if not, it -returns \code{NULL}. - -I provide two implementations of \code{dl_loadmod()}: one for SGI machines -running Irix 4.0 (written by my colleague Jack Jansen), and one that -is a thin interface layer for Wilson Ho's (GNU) dynamic loading -package \dfn{dld} (version 3.2.3). Dld implements a much more powerful -version of dynamic loading than needed (including unlinking), but it -does not support System V's COFF object file format. It currently -supports only VAX (Ultrix), Sun 3 (SunOS 3.4 and 4.0), SPARCstation -(SunOS 4.0), Sequent Symmetry (Dynix), and Atari ST (from the dld -3.2.3 README file). Dld is part of the standard Python distribution; -if you didn't get it,many ftp archive sites carry dld these days, so -it won't be hard to get hold of it if you need it (using archie). - -(If you don't know where to get dld, try anonymous ftp to -\file{wuarchive.wustl.edu:/mirrors2/gnu/dld-3.2.3.tar.Z}. Jack's dld -can be found at \file{ftp.cwi.nl:/pub/python/dl.tar.Z}.) - -To build a Python interpreter capable of dynamic loading, you need to -edit the Makefile. Basically you must uncomment the lines starting -with \samp{\#DL_}, but you must also edit some of the lines to choose -which version of dl_loadmod to use, and fill in the pathname of the dld -library if you use it. And, of course, you must first build -dl_loadmod and dld, if used. (This is now done through the Configure -script. For SunOS, everything is now automatic as long as the -architecture type is \code{sun4}.) - - -\section{Building a dynamically loadable module} - -Building an object file usable by dynamic loading is easy, if you -follow these rules (substitute your module name for \code{foo} -everywhere): - -\begin{itemize} - -\item -The source filename must be \file{foomodule.c}, so the object -name is \file{foomodule.o}. - -\item -The module must be written as a (statically linked) Python extension -module (described in an earlier chapter) except that no line for it -must be added to \file{config.c} and it mustn't be linked with the -main Python interpreter. - -\item -The module's initialization function must be called \code{initfoo}; it -must install the module in \code{sys.modules} (generally by calling -\code{initmodule()} as explained earlier. - -\item -The module must be compiled with \samp{-c}. The resulting .o file must -not be stripped. - -\item -Since the module must include many standard Python include files, it -must be compiled with a \samp{-I} option pointing to the Python source -directory (unless it resides there itself). - -\item -On SGI Irix, the compiler flag \samp{-G0} (or \samp{-G 0}) must be passed. -IF THIS IS NOT DONE THE RESULTING CODE WILL NOT WORK. - -\item -{\bf NEW:} On SunOS, you must create a shared library from your \samp{.o} -file using the following command (assuming your module is called -\code{foo}): - -\begin{verbatim} - ld -o foomodule.so foomodule.o -\end{verbatim} - -and place the resulting \samp{.so} file in the Python search path (not -the \samp{.o} file). Note: on Solaris, you need to pass \samp{-G} to -the loader. - -\end{itemize} - - -\section{Using libraries} - -If your dynamically loadable module needs to be linked with one or -more libraries that aren't linked with Python (or if it needs a -routine that isn't used by Python from one of the libraries with which -Python is linked), you must specify a list of libraries to search -after loading the module in a file with extension \samp{.libs} (and -otherwise the same as your \samp{.o} file). This file should contain -one or more lines containing whitespace-separated absolute library -pathnames. When using the dl interface, \samp{-l...} flags may also -be used (it is in fact passed as an option list to the system linker -ld(1)), but the dl-dld interface requires absolute pathnames. I -believe it is possible to specify shared libraries here. - -(On SunOS, any extra libraries must be specified on the \code{ld} -command that creates the \samp{.so} file.) - - -\section{Caveats} - -Dynamic loading requires that \code{main}'s \code{argv[0]} contains -the pathname or at least filename of the Python interpreter. -Unfortunately, when executing a directly executable Python script (an -executable file with \samp{\#!...} on the first line), the kernel -overwrites \code{argv[0]} with the name of the script. There is no -easy way around this, so executable Python scripts cannot use -dynamically loaded modules. (You can always write a simple shell -script that calls the Python interpreter with the script as its -input.) - -When using dl, the overlay is first converted into an `overlay' for -the current process by the system linker (\code{ld}). The overlay is -saved as a file with extension \samp{.ld}, either in the directory -where the \samp{.o} file lives or (if that can't be written) in a -temporary directory. An existing \samp{.ld} file resulting from a -previous run (not from a temporary directory) is used, bypassing the -(costly) linking phase, provided its version matches the \samp{.o} -file and the current binary. (See the \code{dl} man page for more -details.) - - -\input{ext.ind} - -\end{document} diff --git a/Doc/fix.el b/Doc/fix.el deleted file mode 100644 index 25086e4359..0000000000 --- a/Doc/fix.el +++ /dev/null @@ -1,6 +0,0 @@ -; load the new texinfo package (2.xx) if not installed by default -; (setq load-path -; (cons "/ufs/jh/lib/emacs/texinfo-2.14" load-path)) -(find-file "lib.texi") -(texinfo-all-menus-update t) -(texinfo-all-menus-update t) diff --git a/Doc/fix_hack b/Doc/fix_hack deleted file mode 100755 index 8c977291bb..0000000000 --- a/Doc/fix_hack +++ /dev/null @@ -1 +0,0 @@ -sed -e 's/{\\ptt[ ]*\\char[ ]*'"'"'137}/_/g' <"$1" > "@$1" && mv "@$1" $1 diff --git a/Doc/info/texipost.dat b/Doc/info/texipost.dat deleted file mode 100644 index 7897e44b09..0000000000 --- a/Doc/info/texipost.dat +++ /dev/null @@ -1,23 +0,0 @@ -@node Function Index, , , -@unnumbered Function Index - -@printindex fn - -@node Variable Index, , , -@unnumbered Variable Index - -@printindex vr - -@node Module Index, , , -@unnumbered Module Index - -@printindex pg - -@node Concept Index, , , -@unnumbered Concept Index - -@printindex cp - -@summarycontents -@contents -@bye diff --git a/Doc/info/texipre.dat b/Doc/info/texipre.dat deleted file mode 100644 index c531077e45..0000000000 --- a/Doc/info/texipre.dat +++ /dev/null @@ -1,86 +0,0 @@ -\input texinfo @c -*-texinfo-*- -@c %**start of header -@setfilename python-lib.info -@settitle Python library reference -@setchapternewpage odd -@footnotestyle end -@c %**end of header - -@ifinfo -This file describes the built-in types, exceptions and functions and the -standard modules that come with the Python system. It assumes basic -knowledge about the Python language. For an informal introduction to -the language, see the Python Tutorial. The Python Reference Manual -gives a more formal definition of the language. (These manuals are not -yet available in INFO or Texinfo format.) - -Copyright (C) 1991, 1992, 1993 by Stichting Mathematisch Centrum, -Amsterdam, The Netherlands. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the names of Stichting Mathematisch -Centrum or CWI not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior permission. - -STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO -THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE -FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -@end ifinfo - -@titlepage -@title Python library reference -@author Guido van Rossum - -@c The following two commands start the copyright page. -@page -@vskip 0pt plus 1filll -Copyright @copyright{} 1991, 1992, 1993 by Stichting Mathematisch Centrum, -Amsterdam, The Netherlands. - -@center All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the names of Stichting Mathematisch -Centrum or CWI not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior permission. - -STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO -THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE -FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -@end titlepage - - -@node Top, Overview, (dir), (dir) -@top The Python library - -@ifinfo -This file describes the built-in types, exceptions and functions and the -standard modules that come with the Python system. It assumes basic -knowledge about the Python language. For an informal introduction to -the language, see the @cite{Python Tutorial}. The @cite{Python -Reference Manual} gives a more formal definition of the language. -(These manuals are not yet available in INFO or Texinfo format.) - -This version corresponds roughly to Python version 1.0 (yet to be released). - -@end ifinfo - -@c placeholder for the master menu -- patched by texinfo-all-menus-update -@menu -@end menu diff --git a/Doc/lib.tex b/Doc/lib.tex deleted file mode 100644 index e7ef71ea4a..0000000000 --- a/Doc/lib.tex +++ /dev/null @@ -1,57 +0,0 @@ -\documentstyle[twoside,11pt,myformat]{report} -%\includeonly{lib5} - -\title{\bf - Python Library Reference -} - -\author{ - Guido van Rossum \\ - Dept. CST, CWI, P.O. Box 94079 \\ - 1090 GB Amsterdam, The Netherlands \\ - E-mail: {\tt guido@cwi.nl} -} - -\date{19 November 1993 \\ Release 0.9.9.++} % XXX update before release! - -% Tell \index to actually write the .idx file -\makeindex - -\begin{document} -%\showthe\fam -%\showthe\ttfam -\pagenumbering{roman} - -\maketitle - -\begin{abstract} - -\noindent -This document describes the built-in types, exceptions and functions -and the standard modules that come with the Python system. It assumes -basic knowledge about the Python language. For an informal -introduction to the language, see the {\em Python Tutorial}. The {\em -Python Reference Manual} gives a more formal definition of the -language. - -\end{abstract} - -\pagebreak - -{ -\parskip = 0mm -\tableofcontents -} - -\pagebreak - -\pagenumbering{arabic} -\include{lib1} % intro; built-in types, functions and exceptions -\include{lib2} % built-in modules -\include{lib3} % standard modules -\include{lib4} % Most OS'es; UNIX only; Amoeba only -\include{lib5} % STDWIN only; SGI machines only; SUNs only; AUDIO TOOLS - -\input{lib.ind} % The index - -\end{document} diff --git a/Doc/lib/lib.tex b/Doc/lib/lib.tex deleted file mode 100644 index e7ef71ea4a..0000000000 --- a/Doc/lib/lib.tex +++ /dev/null @@ -1,57 +0,0 @@ -\documentstyle[twoside,11pt,myformat]{report} -%\includeonly{lib5} - -\title{\bf - Python Library Reference -} - -\author{ - Guido van Rossum \\ - Dept. CST, CWI, P.O. Box 94079 \\ - 1090 GB Amsterdam, The Netherlands \\ - E-mail: {\tt guido@cwi.nl} -} - -\date{19 November 1993 \\ Release 0.9.9.++} % XXX update before release! - -% Tell \index to actually write the .idx file -\makeindex - -\begin{document} -%\showthe\fam -%\showthe\ttfam -\pagenumbering{roman} - -\maketitle - -\begin{abstract} - -\noindent -This document describes the built-in types, exceptions and functions -and the standard modules that come with the Python system. It assumes -basic knowledge about the Python language. For an informal -introduction to the language, see the {\em Python Tutorial}. The {\em -Python Reference Manual} gives a more formal definition of the -language. - -\end{abstract} - -\pagebreak - -{ -\parskip = 0mm -\tableofcontents -} - -\pagebreak - -\pagenumbering{arabic} -\include{lib1} % intro; built-in types, functions and exceptions -\include{lib2} % built-in modules -\include{lib3} % standard modules -\include{lib4} % Most OS'es; UNIX only; Amoeba only -\include{lib5} % STDWIN only; SGI machines only; SUNs only; AUDIO TOOLS - -\input{lib.ind} % The index - -\end{document} diff --git a/Doc/lib/libtemplate.tex b/Doc/lib/libtemplate.tex deleted file mode 100644 index 7465af8720..0000000000 --- a/Doc/lib/libtemplate.tex +++ /dev/null @@ -1,40 +0,0 @@ -% Template for library sections. -% Replace text in ALL CAPS by your own text. -% Comments starting with %** give additional directions. - -%** Choose one of the following two section headings: -\section{Built-in module {\tt YOUR-MODULE-NAME}} % If written in C -\section{Standard module {\tt YOUR-MODULE-NAME}} % If written in Python - -PUT A SHORT INTRODUCTION AND DESCRIPTION OF THE MODULE HERE. - -%** change this sentence to taste: -The module defines the following variables and functions: - -\begin{description} - -\renewcommand{\indexsubitem}{(in module YOUR-MODULE-NAME)} - - -%** You can mix exceptions, variables and functions below; often it is a -%** good idea to alphabetize them all. - - -%** repeat the following for each exception: -\excitem{NAME} -DESCRIPTION OF THE EXCEPTION GOES HERE. - - -%** repeat the following for each variable (or constant): -\dataitem{NAME} -DESCRIPTION OF THE VARIABLE/CONSTANT GOES HERE. - - -%** repeat the following for each function: -\funcitem{NAME}{PARAMETERS} % Don't include the parentheses -DESCRIPTION OF THE FUNCTION GOES HERE. - - -\end{description} - -ADDITIONAL HINTS FOR USING THE MODULE MAY GO HERE. diff --git a/Doc/libtemplate.tex b/Doc/libtemplate.tex deleted file mode 100644 index 7465af8720..0000000000 --- a/Doc/libtemplate.tex +++ /dev/null @@ -1,40 +0,0 @@ -% Template for library sections. -% Replace text in ALL CAPS by your own text. -% Comments starting with %** give additional directions. - -%** Choose one of the following two section headings: -\section{Built-in module {\tt YOUR-MODULE-NAME}} % If written in C -\section{Standard module {\tt YOUR-MODULE-NAME}} % If written in Python - -PUT A SHORT INTRODUCTION AND DESCRIPTION OF THE MODULE HERE. - -%** change this sentence to taste: -The module defines the following variables and functions: - -\begin{description} - -\renewcommand{\indexsubitem}{(in module YOUR-MODULE-NAME)} - - -%** You can mix exceptions, variables and functions below; often it is a -%** good idea to alphabetize them all. - - -%** repeat the following for each exception: -\excitem{NAME} -DESCRIPTION OF THE EXCEPTION GOES HERE. - - -%** repeat the following for each variable (or constant): -\dataitem{NAME} -DESCRIPTION OF THE VARIABLE/CONSTANT GOES HERE. - - -%** repeat the following for each function: -\funcitem{NAME}{PARAMETERS} % Don't include the parentheses -DESCRIPTION OF THE FUNCTION GOES HERE. - - -\end{description} - -ADDITIONAL HINTS FOR USING THE MODULE MAY GO HERE. diff --git a/Doc/myformat.sty b/Doc/myformat.sty deleted file mode 100644 index 398c2f33b1..0000000000 --- a/Doc/myformat.sty +++ /dev/null @@ -1,199 +0,0 @@ -% Style parameters and macros used by most documents here - -\input{a4wide.sty} % Take this out if it doesn't exist or doesn't work - -% This has to be tuned each time the repair person takes the printer apart: -\addtolength{\oddsidemargin}{-2.5mm} -\addtolength{\evensidemargin}{-2.5mm} - -% Style parameters -\raggedbottom -\sloppy -\parindent = 0mm -\parskip = 2mm - -% Frequently used system name -%\newcommand{\UNIX}{U{\sc nix}} - -% Variable used by begin code command -\newlength{\codewidth} - -% Command to start a code block (follow this by \begin{verbatim}) -\newcommand{\bcode}{ - % Calculate the text width for the minipage: - \setlength{\codewidth}{\linewidth} - \addtolength{\codewidth}{-\parindent} - % - \par - \vspace{3mm} - \indent - \begin{minipage}[t]{\codewidth} -} - -% Command to end a code block (precede this by \end{verbatim}) -\newcommand{\ecode}{ - \end{minipage} - \vspace{3mm} - \par - \noindent -} - -% Underscores are not magic throughout the Python documentation. -% This still only gives the right effect in the tt font!!! -\def\_{\ifnum\fam=\ttfam \char'137\else{\tt\char'137}\fi} -\catcode`\_=12 -\catcode`\_=\active\def_{\ifnum\fam=\ttfam \char'137 \else{\tt\char'137}\fi} - -% Define \itembreak: force the text after an item to start on a new line -\newcommand{\itembreak}{ -\mbox{} -\\*[0mm] -} - -% Command to generate two index entries (using subentries) -\newcommand{\indexii}[2]{ -\index{#1!#2} -\index{#2!#1} -} - -% And three entries (using only one level of subentries) -\newcommand{\indexiii}[3]{ -\index{#1!#2 #3} -\index{#2!#3, #1} -\index{#3!#1 #2} -} - -% And four (again, using only one level of subentries) -\newcommand{\indexiv}[4]{ -\index{#1!#2 #3 #4} -\index{#2!#3 #4, #1} -\index{#3!#4, #1 #2} -\index{#4!#1 #2 #3} -} - -% Command to generate a reference to a function, statement, keyword, operator -\newcommand{\stindex}[1]{\indexii{statement}{#1@{\tt#1}}} -\newcommand{\kwindex}[1]{\indexii{keyword}{#1@{\tt#1}}} -\newcommand{\opindex}[1]{\indexii{operator}{#1@{\tt#1}}} -\newcommand{\exindex}[1]{\indexii{exception}{#1@{\tt#1}}} -\newcommand{\obindex}[1]{\indexii{object}{#1}} -\newcommand{\bifuncindex}[1]{\index{#1@{\tt#1} (built-in function)}} - -% Add an index entry for a module -\newcommand{\modindex}[2]{\index{#1@{\tt#1} (#2module)}} -\newcommand{\bimodindex}[1]{\modindex{#1}{built-in }} -\newcommand{\stmodindex}[1]{\modindex{#1}{standard }} - -% Additional string for an index entry -\newcommand{\indexsubitem}{} -\newcommand{\ttindex}[1]{\index{#1@{\tt#1} \indexsubitem}} - -% Define \itemjoin: some negative vspace to join two items together -\newcommand{\itemjoin}{ -\mbox{} -\vspace{-\itemsep} -\vspace{-\parsep} -} - -% Define \funcitem{func}{args}: define a function item -\newcommand{\funcitem}[2]{% -\ttindex{#1}% -%\item[{\tt #1(#2)}] -\item[\code{#1(\varvars{#2})}] -\ -} - - -% from user-level, fulllineitems should be called as an environment -\def\fulllineitems{\list{}{\labelwidth \leftmargin \labelsep 0pt -\rightmargin 0pt \topsep -\parskip \partopsep \parskip -\itemsep -\parsep -\let\makelabel\itemnewline}} -\let\endfulllineitems\endlist - - -% funcdesc should be called as an \begin{funcdesc} ... \end{funcdesc} -\newcommand{\funcline}[2]{\item[\code{#1(\varvars{#2})}]\ttindex{#1}} -\newcommand{\funcdesc}[2]{\fulllineitems\funcline{#1}{#2}} -\let\endfuncdesc\endfulllineitems - -% same for excdesc -\newcommand{\excline}[1]{\item[\code{#1}]\ttindex{#1}} -\newcommand{\excdesc}[1]{\fulllineitems\excline{#1}} -\let\endexcdesc\endfulllineitems - -% same for datadesc -\newcommand{\dataline}[1]{\item[\code{#1}]\ttindex{#1}} -\newcommand{\datadesc}[1]{\fulllineitems\dataline{#1}} -\let\enddatadesc\endfulllineitems - - -% Define \dataitem{name}: define a data item -\newcommand{\dataitem}[1]{% -\ttindex{#1}% -\item[{\tt #1}] -\ -} - -% Define \excitem{name}: define an exception item -\newcommand{\excitem}[1]{% -\ttindex{#1}% -\item[{\tt #1}] -\itembreak -} - -\let\nodename=\label - -\newcommand{\ABC}{{\sc abc}} -\newcommand{\UNIX}{{\sc Unix}} -\newcommand{\ASCII}{{\sc ascii}} -%\newcommand{\C}{{\bf C}} -\newcommand{\C}{C} -\newcommand{\EOF}{{\sc eof}} - -% code is the most difficult one... -%\frenchspacing removed, because \section, etc., can't handle it -\newcommand{\code}[1]{{\@vobeyspaces\@noligs\def\{{\char`\{}\def\}{\char`\}}\def\~{\char`\~}\def\^{\char`\^}\def\e{\char`\\}\def\${\char`\$}\def\#{\char`\#}\def\&{\char`\&}\def\%{\char`\%}% -\mbox{\tt #1}}} -%This one does not work -%%%% myspecials, same as dospecials, but without {, } and \ -%%%\def\myspecials{\do\ \do\$\do\&% -%%% \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~} -%%%\newcommand{\code}[1]{\begingroup \catcode``=13 \@noligs -%%%\tt \let\do\@makeother \myspecials -%%%#1\endgroup} -\newcommand{\kbd}[1]{\mbox{\tt #1}} -\newcommand{\key}[1]{\mbox{\tt #1}} -\newcommand{\samp}[1]{\mbox{`\code{#1}'}} -\newcommand{\var}[1]{\mbox{\it#1\/}} -\let\file=\samp -\newcommand{\dfn}[1]{{\sl #1\/}} -\newcommand{\emph}[1]{{\em #1\/}} -\newcommand{\strong}[1]{{\bf #1}} - -%\newcommand{\varvars}[1]{{\catcode`\,=\active\def,{\tt\char`\,\/tt}\var{#1}}} -%\newcommand{\varvars}[1]{{\def\,{\/{\tt\char`\,}}\var{#1}}} -\newcommand{\varvars}[1]{{\def\,{\/{\tt\char`\,}}\def\({\/{\tt\char`\(}}\def\){\/{\tt\char`\)}}\var{#1}}} - -\newif\iftexi\texifalse -%not supported yet%\newif\iflatex\latextrue - -\newenvironment{tableiii}[5]{\begin{center}\def\lineiii##1##2##3{\csname#2\endcsname{##1}&##2&##3\\}\begin{tabular}{#1}\hline#3\\ -\hline}{\hline\end{tabular}\end{center}} - -\newcommand{\itemnewline}[1]{\@tempdima\linewidth -\advance\@tempdima \leftmargin\makebox[\@tempdima][l]{#1}} - -\newcommand{\sectcode}[1]{{\tt #1}} -%%% -%%%\let\orgchapter\chapter -%%%\def\chapter#1{{\let\code\sectcode\orgchapter{#1}}} -%%%\let\orgsection\section -%%%\def\section#1{{\let\code\sectcode\orgsection{#1}}} -%%%\let\orgsubsection\subsection -%%%\def\subsection#1{{\let\code\sectcode\orgsubsection{#1}}} -%%%\let\orgsubsubsection\subsubsection -%%%\def\subsubsection#1{{\let\code\sectcode\orgsubsubsection{#1}}} -%%%\let\orgsubsubsubsection\subsubsubsection -%%%\def\subsubsubsection#1{{\let\code\sectcode\orgsubsubsubsection{#1}}} - diff --git a/Doc/partparse.py b/Doc/partparse.py deleted file mode 100644 index 757fc02bc7..0000000000 --- a/Doc/partparse.py +++ /dev/null @@ -1,2129 +0,0 @@ -# -# partparse.py: parse a by-Guido-written-and-by-Jan-Hein-edited LaTeX file, -# and generate texinfo source. -# -# This is *not* a good example of good programming practices. In fact, this -# file could use a complete rewrite, in order to become faster, more -# easy extensible and maintainable. -# -# However, I added some comments on a few places for the pityful person who -# would ever need to take a look into this file. -# -# Have I been clear enough?? -# -# -jh - - -import sys, string, regex, getopt, os - -# Different parse modes for phase 1 -MODE_REGULAR = 0 -MODE_VERBATIM = 1 -MODE_CS_SCAN = 2 -MODE_COMMENT = 3 -MODE_MATH = 4 -MODE_DMATH = 5 -MODE_GOBBLEWHITE = 6 - -the_modes = MODE_REGULAR, MODE_VERBATIM, MODE_CS_SCAN, MODE_COMMENT, \ - MODE_MATH, MODE_DMATH, MODE_GOBBLEWHITE - -# Show the neighbourhood of the scanned buffer -def epsilon(buf, where): - wmt, wpt = where - 10, where + 10 - if wmt < 0: - wmt = 0 - if wpt > len(buf): - wpt = len(buf) - return ' Context ' + `buf[wmt:where]` + '.' + `buf[where:wpt]` + '.' - -# Should return the line number. never worked -def lin(): - global lineno - return ' Line ' + `lineno` + '.' - -# Displays the recursion level. -def lv(lvl): - return ' Level ' + `lvl` + '.' - -# Combine the three previous functions. Used often. -def lle(lvl, buf, where): - return lv(lvl) + lin() + epsilon(buf, where) - - -# This class is only needed for _symbolic_ representation of the parse mode. -class Mode: - def init(self, arg): - if arg not in the_modes: - raise ValueError, 'mode not in the_modes' - self.mode = arg - return self - - def __cmp__(self, other): - if type(self) != type(other): - other = mode(other) - return cmp(self.mode, other.mode) - - def __repr__(self): - if self.mode == MODE_REGULAR: - return 'MODE_REGULAR' - elif self.mode == MODE_VERBATIM: - return 'MODE_VERBATIM' - elif self.mode == MODE_CS_SCAN: - return 'MODE_CS_SCAN' - elif self.mode == MODE_COMMENT: - return 'MODE_COMMENT' - elif self.mode == MODE_MATH: - return 'MODE_MATH' - elif self.mode == MODE_DMATH: - return 'MODE_DMATH' - elif self.mode == MODE_GOBBLEWHITE: - return 'MODE_GOBBLEWHITE' - else: - raise ValueError, 'mode not in the_modes' - -# just a wrapper around a class initialisation -def mode(arg): - return Mode().init(arg) - - -# After phase 1, the text consists of chunks, with a certain type -# this type will be assigned to the chtype member of the chunk -# the where-field contains the file position where this is found -# and the data field contains (1): a tuple describing start- end end -# positions of the substring (can be used as slice for the buf-variable), -# (2) just a string, mostly generated by the changeit routine, -# or (3) a list, describing a (recursive) subgroup of chunks -PLAIN = 0 # ASSUME PLAINTEXT, data = the text -GROUP = 1 # GROUP ({}), data = [chunk, chunk,..] -CSNAME = 2 # CONTROL SEQ TOKEN, data = the command -COMMENT = 3 # data is the actual comment -DMATH = 4 # DISPLAYMATH, data = [chunk, chunk,..] -MATH = 5 # MATH, see DISPLAYMATH -OTHER = 6 # CHAR WITH CATCODE OTHER, data = char -ACTIVE = 7 # ACTIVE CHAR -GOBBLEDWHITE = 8 # Gobbled LWSP, after CSNAME -ENDLINE = 9 # END-OF-LINE, data = '\n' -DENDLINE = 10 # DOUBLE EOL, data='\n', indicates \par -ENV = 11 # LaTeX-environment - # data =(envname,[ch,ch,ch,.]) -CSLINE = 12 # for texi: next chunk will be one group - # of args. Will be set all on 1 line -IGNORE = 13 # IGNORE this data -ENDENV = 14 # TEMP END OF GROUP INDICATOR -IF = 15 # IF-directive - # data = (flag,negate,[ch, ch, ch,...]) -the_types = PLAIN, GROUP, CSNAME, COMMENT, DMATH, MATH, OTHER, ACTIVE, \ - GOBBLEDWHITE, ENDLINE, DENDLINE, ENV, CSLINE, IGNORE, ENDENV, IF - -# class, just to display symbolic name -class ChunkType: - def init(self, chunk_type): - if chunk_type not in the_types: - raise 'ValueError', 'chunk_type not in the_types' - self.chunk_type = chunk_type - return self - - def __cmp__(self, other): - if type(self) != type(other): - other = chunk_type(other) - return cmp(self.chunk_type, other.chunk_type) - - def __repr__(self): - if self.chunk_type == PLAIN: - return 'PLAIN' - elif self.chunk_type == GROUP: - return 'GROUP' - elif self.chunk_type == CSNAME: - return 'CSNAME' - elif self.chunk_type == COMMENT: - return 'COMMENT' - elif self.chunk_type == DMATH: - return 'DMATH' - elif self.chunk_type == MATH: - return 'MATH' - elif self.chunk_type == OTHER: - return 'OTHER' - elif self.chunk_type == ACTIVE: - return 'ACTIVE' - elif self.chunk_type == GOBBLEDWHITE: - return 'GOBBLEDWHITE' - elif self.chunk_type == DENDLINE: - return 'DENDLINE' - elif self.chunk_type == ENDLINE: - return 'ENDLINE' - elif self.chunk_type == ENV: - return 'ENV' - elif self.chunk_type == CSLINE: - return 'CSLINE' - elif self.chunk_type == IGNORE: - return 'IGNORE' - elif self.chunk_type == ENDENV: - return 'ENDENV' - elif self.chunk_type == IF: - return 'IF' - else: - raise ValueError, 'chunk_type not in the_types' - -# ...and the wrapper -def chunk_type(type): - return ChunkType().init(type) - -# store a type object of the ChunkType-class-instance... -chunk_type_type = type(chunk_type(0)) - -# this class contains a part of the parsed buffer -class Chunk: - def init(self, chtype, where, data): - if type(chtype) != chunk_type_type: - chtype = chunk_type(chtype) - self.chtype = chtype - if type(where) != type(0): - raise TypeError, '\'where\' is not a number' - self.where = where - self.data = data - ##print 'CHUNK', self - return self - - def __repr__(self): - return 'chunk' + `self.chtype, self.where, self.data` - -# and the wrapper -def chunk(chtype, where, data): - return Chunk().init(chtype, where, data) - - - -error = 'partparse.error' - -# -# TeX's catcodes... -# -CC_ESCAPE = 0 -CC_LBRACE = 1 -CC_RBRACE = 2 -CC_MATHSHIFT = 3 -CC_ALIGNMENT = 4 -CC_ENDLINE = 5 -CC_PARAMETER = 6 -CC_SUPERSCRIPT = 7 -CC_SUBSCRIPT = 8 -CC_IGNORE = 9 -CC_WHITE = 10 -CC_LETTER = 11 -CC_OTHER = 12 -CC_ACTIVE = 13 -CC_COMMENT = 14 -CC_INVALID = 15 - -# and the names -cc_names = [\ - 'CC_ESCAPE', \ - 'CC_LBRACE', \ - 'CC_RBRACE', \ - 'CC_MATHSHIFT', \ - 'CC_ALIGNMENT', \ - 'CC_ENDLINE', \ - 'CC_PARAMETER', \ - 'CC_SUPERSCRIPT', \ - 'CC_SUBSCRIPT', \ - 'CC_IGNORE', \ - 'CC_WHITE', \ - 'CC_LETTER', \ - 'CC_OTHER', \ - 'CC_ACTIVE', \ - 'CC_COMMENT', \ - 'CC_INVALID', \ - ] - -# Show a list of catcode-name-symbols -def pcl(codelist): - result = '' - for i in codelist: - result = result + cc_names[i] + ', ' - return '[' + result[:-2] + ']' - -# the name of the catcode (ACTIVE, OTHER, etc.) -def pc(code): - return cc_names[code] - - -# Which catcodes make the parser stop parsing regular plaintext -regular_stopcodes = [CC_ESCAPE, CC_LBRACE, CC_RBRACE, CC_MATHSHIFT, \ - CC_ALIGNMENT, CC_PARAMETER, CC_SUPERSCRIPT, CC_SUBSCRIPT, \ - CC_IGNORE, CC_ACTIVE, CC_COMMENT, CC_INVALID, CC_ENDLINE] - -# same for scanning a control sequence name -csname_scancodes = [CC_LETTER] - -# same for gobbling LWSP -white_scancodes = [CC_WHITE] -##white_scancodes = [CC_WHITE, CC_ENDLINE] - -# make a list of all catcode id's, except for catcode ``other'' -all_but_other_codes = range(16) -del all_but_other_codes[CC_OTHER] -##print all_but_other_codes - -# when does a comment end -comment_stopcodes = [CC_ENDLINE] - -# gather all characters together, specified by a list of catcodes -def code2string(cc, codelist): - ##print 'code2string: codelist = ' + pcl(codelist), - result = '' - for category in codelist: - if cc[category]: - result = result + cc[category] - ##print 'result = ' + `result` - return result - -# automatically generate all characters of catcode other, being the -# complement set in the ASCII range (128 characters) -def make_other_codes(cc): - otherchars = range(256) # could be made 256, no problem - for category in all_but_other_codes: - if cc[category]: - for c in cc[category]: - otherchars[ord(c)] = None - result = '' - for i in otherchars: - if i != None: - result = result + chr(i) - return result - -# catcode dump (which characters have which catcodes). -def dump_cc(name, cc): - ##print '\t' + name - ##print '=' * (8+len(name)) - if len(cc) != 16: - raise TypeError, 'cc not good cat class' -## for i in range(16): -## print pc(i) + '\t' + `cc[i]` - - -# In the beginning,.... -epoch_cc = [None] * 16 -##dump_cc('epoch_cc', epoch_cc) - - -# INITEX -initex_cc = epoch_cc[:] -initex_cc[CC_ESCAPE] = '\\' -initex_cc[CC_ENDLINE], initex_cc[CC_IGNORE], initex_cc[CC_WHITE] = \ - '\n', '\0', ' ' -initex_cc[CC_LETTER] = string.uppercase + string.lowercase -initex_cc[CC_COMMENT], initex_cc[CC_INVALID] = '%', '\x7F' -#initex_cc[CC_OTHER] = make_other_codes(initex_cc) I don't need them, anyway -##dump_cc('initex_cc', initex_cc) - - -# LPLAIN: LaTeX catcode setting (see lplain.tex) -lplain_cc = initex_cc[:] -lplain_cc[CC_LBRACE], lplain_cc[CC_RBRACE] = '{', '}' -lplain_cc[CC_MATHSHIFT] = '$' -lplain_cc[CC_ALIGNMENT] = '&' -lplain_cc[CC_PARAMETER] = '#' -lplain_cc[CC_SUPERSCRIPT] = '^\x0B' # '^' and C-k -lplain_cc[CC_SUBSCRIPT] = '_\x01' # '_' and C-a -lplain_cc[CC_WHITE] = lplain_cc[CC_WHITE] + '\t' -lplain_cc[CC_ACTIVE] = '~\x0C' # '~' and C-l -lplain_cc[CC_OTHER] = make_other_codes(lplain_cc) -##dump_cc('lplain_cc', lplain_cc) - - -# Guido's LaTeX environment catcoded '_' as ``other'' -# my own purpose catlist -my_cc = lplain_cc[:] -my_cc[CC_SUBSCRIPT] = my_cc[CC_SUBSCRIPT][1:] # remove '_' here -my_cc[CC_OTHER] = my_cc[CC_OTHER] + '_' # add it to OTHER list -dump_cc('my_cc', my_cc) - - - -# needed for un_re, my equivalent for regexp-quote in Emacs -re_meaning = '\\[]^$' - -def un_re(str): - result = '' - for i in str: - if i in re_meaning: - result = result + '\\' - result = result + i - return result - -# NOTE the negate ('^') operator in *some* of the regexps below -def make_rc_regular(cc): - # problems here if '[]' are included!! - return regex.compile('[' + code2string(cc, regular_stopcodes) + ']') - -def make_rc_cs_scan(cc): - return regex.compile('[^' + code2string(cc, csname_scancodes) + ']') - -def make_rc_comment(cc): - return regex.compile('[' + code2string(cc, comment_stopcodes) + ']') - -def make_rc_endwhite(cc): - return regex.compile('[^' + code2string(cc, white_scancodes) + ']') - - - -# regular: normal mode: -rc_regular = make_rc_regular(my_cc) - -# scan: scan a command sequence e.g. `newlength' or `mbox' or `;', `,' or `$' -rc_cs_scan = make_rc_cs_scan(my_cc) -rc_comment = make_rc_comment(my_cc) -rc_endwhite = make_rc_endwhite(my_cc) - - -# parseit (BUF, PARSEMODE=mode(MODE_REGULAR), START=0, RECURSION-LEVEL=0) -# RECURSION-LEVEL will is incremented on entry. -# result contains the list of chunks returned -# together with this list, the buffer position is returned - -# RECURSION-LEVEL will be set to zero *again*, when recursively a -# {,D}MATH-mode scan has been enetered. -# This has been done in order to better check for environment-mismatches - -def parseit(buf, *rest): - global lineno - - if len(rest) == 3: - parsemode, start, lvl = rest - elif len(rest) == 2: - parsemode, start, lvl = rest + (0, ) - elif len(rest) == 1: - parsemode, start, lvl = rest + (0, 0) - elif len(rest) == 0: - parsemode, start, lvl = mode(MODE_REGULAR), 0, 0 - else: - raise TypeError, 'usage: parseit(buf[, parsemode[, start[, level]]])' - result = [] - end = len(buf) - if lvl == 0 and parsemode == mode(MODE_REGULAR): - lineno = 1 - lvl = lvl + 1 - - ##print 'parseit(' + epsilon(buf, start) + ', ' + `parsemode` + ', ' + `start` + ', ' + `lvl` + ')' - - # - # some of the more regular modes... - # - - if parsemode in (mode(MODE_REGULAR), mode(MODE_DMATH), mode(MODE_MATH)): - cstate = [] - newpos = start - curpmode = parsemode - while 1: - where = newpos - #print '\tnew round: ' + epsilon(buf, where) - if where == end: - if lvl > 1 or curpmode != mode(MODE_REGULAR): - # not the way we started... - raise EOFError, 'premature end of file.' + lle(lvl, buf, where) - # the real ending of lvl-1 parse - return end, result - - pos = rc_regular.search(buf, where) - - if pos < 0: - pos = end - - if pos != where: - newpos, c = pos, chunk(PLAIN, where, (where, pos)) - result.append(c) - continue - - - # - # ok, pos == where and pos != end - # - foundchar = buf[where] - if foundchar in my_cc[CC_LBRACE]: - # recursive subgroup parse... - newpos, data = parseit(buf, curpmode, where+1, lvl) - result.append(chunk(GROUP, where, data)) - - elif foundchar in my_cc[CC_RBRACE]: - if lvl <= 1: - raise error, 'ENDGROUP while in base level.' + lle(lvl, buf, where) - if lvl == 1 and mode != mode(MODE_REGULAR): - raise error, 'endgroup while in math mode. +lin() + epsilon(buf, where)' - return where + 1, result - - elif foundchar in my_cc[CC_ESCAPE]: - # - # call the routine that actually deals with - # this problem. If do_ret is None, than - # return the value of do_ret - # - # Note that handle_cs might call this routine - # recursively again... - # - do_ret, newpos = handlecs(buf, where, \ - curpmode, lvl, result, end) - if do_ret != None: - return do_ret - - elif foundchar in my_cc[CC_COMMENT]: - newpos, data = parseit(buf, \ - mode(MODE_COMMENT), where+1, lvl) - result.append(chunk(COMMENT, where, data)) - - elif foundchar in my_cc[CC_MATHSHIFT]: - # note that recursive calls to math-mode - # scanning are called with recursion-level 0 - # again, in order to check for bad mathend - # - if where + 1 != end and \ - buf[where + 1] in \ - my_cc[CC_MATHSHIFT]: - # - # double mathshift, e.g. '$$' - # - if curpmode == mode(MODE_REGULAR): - newpos, data = parseit(buf, \ - mode(MODE_DMATH), \ - where+2, 0) - result.append(chunk(DMATH, \ - where, data)) - elif curpmode == mode(MODE_MATH): - raise error, 'wrong math delimiiter' + lin() + epsilon(buf, where) - elif lvl != 1: - raise error, 'bad mathend.' + \ - lle(lvl, buf, where) - else: - return where + 2, result - else: - # - # single math shift, e.g. '$' - # - if curpmode == mode(MODE_REGULAR): - newpos, data = parseit(buf, \ - mode(MODE_MATH), \ - where+1, 0) - result.append(chunk(MATH, \ - where, data)) - elif curpmode == mode(MODE_DMATH): - raise error, 'wrong math delimiiter' + lin() + epsilon(buf, where) - elif lvl != 1: - raise error, 'bad mathend.' + \ - lv(lvl, buf, where) - else: - return where + 1, result - - elif foundchar in my_cc[CC_IGNORE]: - print 'warning: ignored char', `foundchar` - newpos = where + 1 - - elif foundchar in my_cc[CC_ACTIVE]: - result.append(chunk(ACTIVE, where, foundchar)) - newpos = where + 1 - - elif foundchar in my_cc[CC_INVALID]: - raise error, 'invalid char ' + `foundchar` - newpos = where + 1 - - elif foundchar in my_cc[CC_ENDLINE]: - # - # after an end of line, eat the rest of - # whitespace on the beginning of the next line - # this is what LaTeX more or less does - # - # also, try to indicate double newlines (\par) - # - lineno = lineno + 1 - savedwhere = where - newpos, dummy = parseit(buf, mode(MODE_GOBBLEWHITE), where + 1, lvl) - if newpos != end and buf[newpos] in \ - my_cc[CC_ENDLINE]: - result.append(chunk(DENDLINE, \ - savedwhere, foundchar)) - else: - result.append(chunk(ENDLINE, \ - savedwhere, foundchar)) - else: - result.append(chunk(OTHER, where, foundchar)) - newpos = where + 1 - - elif parsemode == mode(MODE_CS_SCAN): - # - # scan for a control sequence token. `\ape', `\nut' or `\%' - # - if start == end: - raise EOFError, 'can\'t find end of csname' - pos = rc_cs_scan.search(buf, start) - if pos < 0: - pos = end - if pos == start: - # first non-letter right where we started the search - # ---> the control sequence name consists of one single - # character. Also: don't eat white space... - if buf[pos] in my_cc[CC_ENDLINE]: - lineno = lineno + 1 - pos = pos + 1 - return pos, (start, pos) - else: - spos = pos - if buf[pos] == '\n': - lineno = lineno + 1 - spos = pos + 1 - pos2, dummy = parseit(buf, \ - mode(MODE_GOBBLEWHITE), spos, lvl) - return pos2, (start, pos) - - elif parsemode == mode(MODE_GOBBLEWHITE): - if start == end: - return start, '' - pos = rc_endwhite.search(buf, start) - if pos < 0: - pos = start - return pos, (start, pos) - - elif parsemode == mode(MODE_COMMENT): - pos = rc_comment.search(buf, start) - lineno = lineno + 1 - if pos < 0: - print 'no newline perhaps?' - raise EOFError, 'can\'t find end of comment' - pos = pos + 1 - pos2, dummy = parseit(buf, mode(MODE_GOBBLEWHITE), pos, lvl) - return pos2, (start, pos) - - - else: - raise error, 'Unknown mode (' + `parsemode` + ')' - - -#moreresult = cswitch(buf[x1:x2], buf, newpos, parsemode, lvl) - -#boxcommands = 'mbox', 'fbox' -#defcommands = 'def', 'newcommand' - -endverbstr = '\\end{verbatim}' - -re_endverb = regex.compile(un_re(endverbstr)) - -# -# handlecs: helper function for parseit, for the special thing we might -# wanna do after certain command control sequences -# returns: None or return_data, newpos -# -# in the latter case, the calling function is instructed to immediately -# return with the data in return_data -# -def handlecs(buf, where, curpmode, lvl, result, end): - global lineno - - # get the control sequence name... - newpos, data = parseit(buf, mode(MODE_CS_SCAN), where+1, lvl) - saveddata = data - - if s(buf, data) in ('begin', 'end'): - # skip the expected '{' and get the LaTeX-envname '}' - newpos, data = parseit(buf, mode(MODE_REGULAR), newpos+1, lvl) - if len(data) != 1: - raise error, 'expected 1 chunk of data.' + \ - lle(lvl, buf, where) - - # yucky, we've got an environment - envname = s(buf, data[0].data) - ##print 'FOUND ' + s(buf, saveddata) + '. Name ' + `envname` + '.' + lv(lvl) - if s(buf, saveddata) == 'begin' and envname == 'verbatim': - # verbatim deserves special treatment - pos = re_endverb.search(buf, newpos) - if pos < 0: - raise error, `endverbstr` + ' not found.' + lle(lvl, buf, where) - result.append(chunk(ENV, where, (envname, [chunk(PLAIN, newpos, (newpos, pos))]))) - newpos = pos + len(endverbstr) - - elif s(buf, saveddata) == 'begin': - # start parsing recursively... If that parse returns - # from an '\end{...}', then should the last item of - # the returned data be a string containing the ended - # environment - newpos, data = parseit(buf, curpmode, newpos, lvl) - if not data or type(data[-1]) != type(''): - raise error, 'missing \'end\'' + lle(lvl, buf, where) + epsilon(buf, newpos) - retenv = data[-1] - del data[-1] - if retenv != envname: - #[`retenv`, `envname`] - raise error, 'environments do not match.' + \ - lle(lvl, buf, where) + \ - epsilon(buf, newpos) - result.append(chunk(ENV, where, (retenv, data))) - else: - # 'end'... append the environment name, as just - # pointed out, and order parsit to return... - result.append(envname) - ##print 'POINT of return: ' + epsilon(buf, newpos) - # the tuple will be returned by parseit - return (newpos, result), newpos - - # end of \begin ... \end handling - - elif s(buf, data)[0:2] == 'if': - # another scary monster: the 'if' directive - flag = s(buf, data)[2:] - - # recursively call parseit, just like environment above.. - # the last item of data should contain the if-termination - # e.g., 'else' of 'fi' - newpos, data = parseit(buf, curpmode, newpos, lvl) - if not data or data[-1] not in ('else', 'fi'): - raise error, 'wrong if... termination' + \ - lle(lvl, buf, where) + epsilon(buf, newpos) - - ifterm = data[-1] - del data[-1] - # 0 means dont_negate flag - result.append(chunk(IF, where, (flag, 0, data))) - if ifterm == 'else': - # do the whole thing again, there is only one way - # to end this one, by 'fi' - newpos, data = parseit(buf, curpmode, newpos, lvl) - if not data or data[-1] not in ('fi', ): - raise error, 'wrong if...else... termination' \ - + lle(lvl, buf, where) \ - + epsilon(buf, newpos) - - ifterm = data[-1] - del data[-1] - result.append(chunk(IF, where, (flag, 1, data))) - #done implicitely: return None, newpos - - elif s(buf, data) in ('else', 'fi'): - result.append(s(buf, data)) - # order calling party to return tuple - return (newpos, result), newpos - - # end of \if, \else, ... \fi handling - - elif s(buf, saveddata) == 'verb': - x2 = saveddata[1] - result.append(chunk(CSNAME, where, data)) - if x2 == end: - raise error, 'premature end of command.' + lle(lvl, buf, where) - delimchar = buf[x2] - ##print 'VERB: delimchar ' + `delimchar` - pos = regex.compile(un_re(delimchar)).search(buf, x2 + 1) - if pos < 0: - raise error, 'end of \'verb\' argument (' + \ - `delimchar` + ') not found.' + \ - lle(lvl, buf, where) - result.append(chunk(GROUP, x2, [chunk(PLAIN, x2+1, (x2+1, pos))])) - newpos = pos + 1 - else: - result.append(chunk(CSNAME, where, data)) - return None, newpos - -# this is just a function to get the string value if the possible data-tuple -def s(buf, data): - if type(data) == type(''): - return data - if len(data) != 2 or not (type(data[0]) == type(data[1]) == type(0)): - raise TypeError, 'expected tuple of 2 integers' - x1, x2 = data - return buf[x1:x2] - - -##length, data1, i = getnextarg(length, buf, pp, i + 1) - -# make a deep-copy of some chunks -def crcopy(r): - result = [] - for x in r: - result.append(chunkcopy(x)) - return result - - - -# copy a chunk, would better be a method of class Chunk... -def chunkcopy(ch): - if ch.chtype == chunk_type(GROUP): - listc = ch.data[:] - for i in range(len(listc)): - listc[i] = chunkcopy(listc[i]) - return chunk(GROUP, ch.where, listc) - else: - return chunk(ch.chtype, ch.where, ch.data) - - -# get next argument for TeX-macro, flatten a group (insert between) -# or return Command Sequence token, or give back one character -def getnextarg(length, buf, pp, item): - - ##wobj = Wobj().init() - ##dumpit(buf, wobj.write, pp[item:min(length, item + 5)]) - ##print 'GETNEXTARG, (len, item) =', `length, item` + ' ---> ' + wobj.data + ' <---' - - while item < length and pp[item].chtype == chunk_type(ENDLINE): - del pp[item] - length = length - 1 - if item >= length: - raise error, 'no next arg.' + epsilon(buf, pp[-1].where) - if pp[item].chtype == chunk_type(GROUP): - newpp = pp[item].data - del pp[item] - length = length - 1 - changeit(buf, newpp) - length = length + len(newpp) - pp[item:item] = newpp - item = item + len(newpp) - if len(newpp) < 10: - wobj = Wobj().init() - dumpit(buf, wobj.write, newpp) - ##print 'GETNEXTARG: inserted ' + `wobj.data` - return length, item - elif pp[item].chtype == chunk_type(PLAIN): - #grab one char - print 'WARNING: grabbing one char' - if len(s(buf, pp[item].data)) > 1: - pp.insert(item, chunk(PLAIN, pp[item].where, s(buf, pp[item].data)[:1])) - item, length = item+1, length+1 - pp[item].data = s(buf, pp[item].data)[1:] - else: - item = item+1 - return length, item - else: - try: - str = `s(buf, ch.data)` - except TypeError: - str = `ch.data` - if len(str) > 400: - str = str[:400] + '...' - print 'GETNEXTARG:', ch.chtype, 'not handled, data ' + str - return length, item - - -# this one is needed to find the end of LaTeX's optional argument, like -# item[...] -re_endopt = regex.compile(']') - -# get a LaTeX-optional argument, you know, the square braces '[' and ']' -def getoptarg(length, buf, pp, item): - - wobj = Wobj().init() - dumpit(buf, wobj.write, pp[item:min(length, item + 5)]) - ##print 'GETOPTARG, (len, item) =', `length, item` + ' ---> ' + wobj.data + ' <---' - - if item >= length or \ - pp[item].chtype != chunk_type(PLAIN) or \ - s(buf, pp[item].data)[0] != '[': - return length, item - - pp[item].data = s(buf, pp[item].data)[1:] - if len(pp[item].data) == 0: - del pp[item] - length = length-1 - - while 1: - if item == length: - raise error, 'No end of optional arg found' - if pp[item].chtype == chunk_type(PLAIN): - text = s(buf, pp[item].data) - pos = re_endopt.search(text) - if pos >= 0: - pp[item].data = text[:pos] - if pos == 0: - del pp[item] - length = length-1 - else: - item=item+1 - text = text[pos+1:] - - while text and text[0] in ' \t': - text = text[1:] - - if text: - pp.insert(item, chunk(PLAIN, 0, text)) - length = length + 1 - return length, item - - item = item+1 - - -# Wobj just add write-requests to the ``data'' attribute -class Wobj: - def init(self): - self.data = '' - return self - def write(self, data): - self.data = self.data + data - -# ignore these commands -ignoredcommands = ('bcode', 'ecode') -# map commands like these to themselves as plaintext -wordsselves = ('UNIX', 'ABC', 'C', 'ASCII', 'EOF') -# \{ --> {, \} --> }, etc -themselves = ('{', '}', '.', '@') + wordsselves -# these ones also themselves (see argargs macro in myformat.sty) -inargsselves = (',', '[', ']', '(', ')') -# this is how *I* would show the difference between emph and strong -# code 1 means: fold to uppercase -markcmds = {'code': ('', ''), 'var': 1, 'emph': ('_', '_'), \ - 'strong': ('*', '*')} - -# recognise patter {\FONTCHANGE-CMD TEXT} to \MAPPED-FC-CMD{TEXT} -fontchanges = {'rm': 'r', 'it': 'i', 'em': 'emph', 'bf': 'b', 'tt': 't'} - -# transparent for these commands -for_texi = ('emph', 'var', 'strong', 'code', 'kbd', 'key', 'dfn', 'samp', \ - 'r', 'i', 't') - - -# try to remove macros and return flat text -def flattext(buf, pp): - pp = crcopy(pp) - ##print '---> FLATTEXT ' + `pp` - wobj = Wobj().init() - - i, length = 0, len(pp) - while 1: - if len(pp) != length: - raise 'FATAL', 'inconsistent length' - if i >= length: - break - ch = pp[i] - i = i+1 - if ch.chtype == chunk_type(PLAIN): - pass - elif ch.chtype == chunk_type(CSNAME): - if s(buf, ch.data) in themselves or hist.inargs and s(buf, ch.data) in inargsselves: - ch.chtype = chunk_type(PLAIN) - elif s(buf, ch.data) == 'e': - ch.chtype = chunk_type(PLAIN) - ch.data = '\\' - elif len(s(buf, ch.data)) == 1 \ - and s(buf, ch.data) in onlylatexspecial: - ch.chtype = chunk_type(PLAIN) - # if it is followed by an empty group, - # remove that group, it was needed for - # a true space - if i < length \ - and pp[i].chtype==chunk_type(GROUP) \ - and len(pp[i].data) == 0: - del pp[i] - length = length-1 - - elif s(buf, ch.data) in markcmds.keys(): - length, newi = getnextarg(length, buf, pp, i) - str = flattext(buf, pp[i:newi]) - del pp[i:newi] - length = length - (newi - i) - ch.chtype = chunk_type(PLAIN) - markcmd = s(buf, ch.data) - x = markcmds[markcmd] - if type(x) == type(()): - pre, after = x - str = pre+str+after - elif x == 1: - str = string.upper(str) - else: - raise 'FATAL', 'corrupt markcmds' - ch.data = str - else: - if s(buf, ch.data) not in ignoredcommands: - print 'WARNING: deleting command ' + `s(buf, ch.data)` - print 'PP' + `pp[i-1]` - del pp[i-1] - i, length = i-1, length-1 - elif ch.chtype == chunk_type(GROUP): - length, newi = getnextarg(length, buf, pp, i-1) - i = i-1 -## str = flattext(buf, crcopy(pp[i-1:newi])) -## del pp[i:newi] -## length = length - (newi - i) -## ch.chtype = chunk_type(PLAIN) -## ch.data = str - else: - pass - - dumpit(buf, wobj.write, pp) - ##print 'FLATTEXT: RETURNING ' + `wobj.data` - return wobj.data - -# try to generate node names (a bit shorter than the chapter title) -# note that the \nodename command (see elsewhere) overules these efforts -def invent_node_names(text): - words = string.split(text) - - ##print 'WORDS ' + `words` - - if len(words) == 2 \ - and string.lower(words[0]) == 'built-in' \ - and string.lower(words[1]) not in ('modules', 'functions'): - return words[1] - if len(words) == 3 and string.lower(words[1]) == 'module': - return words[2] - if len(words) == 3 and string.lower(words[1]) == 'object': - return string.join(words[0:2]) - if len(words) > 4 and string.lower(string.join(words[-4:])) == \ - 'methods and data attributes': - return string.join(words[:2]) - return text - -re_commas_etc = regex.compile('[,`\'@{}]') - -re_whitespace = regex.compile('[ \t]*') - - -##nodenamecmd = next_command_p(length, buf, pp, newi, 'nodename') - -# look if the next non-white stuff is also a command, resulting in skipping -# double endlines (DENDLINE) too, and thus omitting \par's -# Sometimes this is too much, maybe consider DENDLINE's as stop -def next_command_p(length, buf, pp, i, cmdname): - - while 1: - if i >= len(pp): - break - ch = pp[i] - i = i+1 - if ch.chtype == chunk_type(ENDLINE): - continue - if ch.chtype == chunk_type(DENDLINE): - continue - if ch.chtype == chunk_type(PLAIN): - if re_whitespace.search(s(buf, ch.data)) == 0 and \ - re_whitespace.match(s(buf, ch.data)) == len(s(buf, ch.data)): - continue - return -1 - if ch.chtype == chunk_type(CSNAME): - if s(buf, ch.data) == cmdname: - return i # _after_ the command - return -1 - return -1 - - -# things that are special to LaTeX, but not to texi.. -onlylatexspecial = '_~^$#&%' - -class Struct: pass - -hist = Struct() -out = Struct() - -def startchange(): - global hist, out - - hist.inenv = [] - hist.nodenames = [] - hist.cindex = [] - hist.inargs = 0 - hist.enumeratenesting, hist.itemizenesting = 0, 0 - - out.doublenodes = [] - out.doublecindeces = [] - - -spacech = [chunk(PLAIN, 0, ' ')] -commach = [chunk(PLAIN, 0, ', ')] -cindexch = [chunk(CSLINE, 0, 'cindex')] - -# the standard variation in symbols for itemize -itemizesymbols = ['bullet', 'minus', 'dots'] - -# same for enumerate -enumeratesymbols = ['1', 'A', 'a'] - -## -## \begin{ {func,data,exc}desc }{name}... -## the resulting texi-code is dependent on the contents of indexsubitem -## - -# indexsubitem: `['XXX', 'function'] -# funcdesc: -# deffn {`idxsi`} NAME (FUNCARGS) - -# indexsubitem: `['XXX', 'method']` -# funcdesc: -# defmethod {`idxsi[0]`} NAME (FUNCARGS) - -# indexsubitem: `['in', 'module', 'MODNAME']' -# datadesc: -# defcv data {`idxsi[1:]`} NAME -# excdesc: -# defcv exception {`idxsi[1:]`} NAME -# funcdesc: -# deffn {function of `idxsi[1:]`} NAME (FUNCARGS) - -# indexsubitem: `['OBJECT', 'attribute']' -# datadesc -# defcv attribute {`OBJECT`} NAME - - -## this routine will be called on \begin{funcdesc}{NAME}{ARGS} -## or \funcline{NAME}{ARGS} -## -def do_funcdesc(length, buf, pp, i): - startpoint = i-1 - ch = pp[startpoint] - wh = ch.where - length, newi = getnextarg(length, buf, pp, i) - funcname = chunk(GROUP, wh, pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - save = hist.inargs - hist.inargs = 1 - length, newi = getnextarg(length, buf, pp, i) - hist.inargs = save - del save - the_args = [chunk(PLAIN, wh, '()'[0])] + \ - pp[i:newi] + \ - [chunk(PLAIN, wh, '()'[1])] - del pp[i:newi] - length = length - (newi-i) - - idxsi = hist.indexsubitem # words - command = '' - cat_class = '' - if idxsi and idxsi[-1] == 'method': - command = 'defmethod' - cat_class = string.join(idxsi[:-1]) - elif len(idxsi) == 2 and idxsi[1] == 'function': - command = 'deffn' - cat_class = string.join(idxsi) - elif len(idxsi) == 3 and idxsi[:2] == ['in', 'module']: - command = 'deffn' - cat_class = 'function of ' + string.join(idxsi[1:]) - - if not command: - raise error, 'don\'t know what to do with indexsubitem ' + `idxsi` - - ch.chtype = chunk_type(CSLINE) - ch.data = command - - cslinearg = [chunk(GROUP, wh, [chunk(PLAIN, wh, cat_class)])] - cslinearg.append(chunk(PLAIN, wh, ' ')) - cslinearg.append(funcname) - cslinearg.append(chunk(PLAIN, wh, ' ')) - l = len(cslinearg) - cslinearg[l:l] = the_args - - pp.insert(i, chunk(GROUP, wh, cslinearg)) - i, length = i+1, length+1 - hist.command = command - return length, i - - -## this routine will be called on \begin{excdesc}{NAME} -## or \excline{NAME} -## -def do_excdesc(length, buf, pp, i): - startpoint = i-1 - ch = pp[startpoint] - wh = ch.where - length, newi = getnextarg(length, buf, pp, i) - excname = chunk(GROUP, wh, pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - - idxsi = hist.indexsubitem # words - command = '' - cat_class = '' - class_class = '' - if len(idxsi) == 2 and idxsi[1] == 'exception': - command = 'defvr' - cat_class = string.join(idxsi) - elif len(idxsi) == 3 and idxsi[:2] == ['in', 'module']: - command = 'defcv' - cat_class = 'exception' - class_class = string.join(idxsi[1:]) - elif len(idxsi) == 4 and idxsi[:3] == ['exception', 'in', 'module']: - command = 'defcv' - cat_class = 'exception' - class_class = string.join(idxsi[2:]) - - - if not command: - raise error, 'don\'t know what to do with indexsubitem ' + `idxsi` - - ch.chtype = chunk_type(CSLINE) - ch.data = command - - cslinearg = [chunk(GROUP, wh, [chunk(PLAIN, wh, cat_class)])] - cslinearg.append(chunk(PLAIN, wh, ' ')) - if class_class: - cslinearg.append(chunk(GROUP, wh, [chunk(PLAIN, wh, class_class)])) - cslinearg.append(chunk(PLAIN, wh, ' ')) - cslinearg.append(excname) - - pp.insert(i, chunk(GROUP, wh, cslinearg)) - i, length = i+1, length+1 - hist.command = command - return length, i - -## same for datadesc or dataline... -def do_datadesc(length, buf, pp, i): - startpoint = i-1 - ch = pp[startpoint] - wh = ch.where - length, newi = getnextarg(length, buf, pp, i) - dataname = chunk(GROUP, wh, pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - - idxsi = hist.indexsubitem # words - command = '' - cat_class = '' - class_class = '' - if len(idxsi) == 2 and idxsi[1] == 'attribute': - command = 'defcv' - cat_class = 'attribute' - class_class = idxsi[0] - elif len(idxsi) == 3 and idxsi[:2] == ['in', 'module']: - command = 'defcv' - cat_class = 'data' - class_class = string.join(idxsi[1:]) - elif len(idxsi) == 4 and idxsi[:3] == ['data', 'in', 'module']: - command = 'defcv' - cat_class = 'data' - class_class = string.join(idxsi[2:]) - - - if not command: - raise error, 'don\'t know what to do with indexsubitem ' + `idxsi` - - ch.chtype = chunk_type(CSLINE) - ch.data = command - - cslinearg = [chunk(GROUP, wh, [chunk(PLAIN, wh, cat_class)])] - cslinearg.append(chunk(PLAIN, wh, ' ')) - if class_class: - cslinearg.append(chunk(GROUP, wh, [chunk(PLAIN, wh, class_class)])) - cslinearg.append(chunk(PLAIN, wh, ' ')) - cslinearg.append(dataname) - - pp.insert(i, chunk(GROUP, wh, cslinearg)) - i, length = i+1, length+1 - hist.command = command - return length, i - - -# regular indices: those that are not set in tt font by default.... -regindices = ('cindex', ) - -# remove illegal characters from node names -def rm_commas_etc(text): - result = '' - changed = 0 - while 1: - pos = re_commas_etc.search(text) - if pos >= 0: - changed = 1 - result = result + text[:pos] - text = text[pos+1:] - else: - result = result + text - break - if changed: - print 'Warning: nodename changhed to ' + `result` - - return result - -# boolean flags -flags = {'texi': 1} - - -## -## changeit: the actual routine, that changes the contents of the parsed -## chunks -## - -def changeit(buf, pp): - global onlylatexspecial, hist, out - - i, length = 0, len(pp) - while 1: - # sanity check: length should always equal len(pp) - if len(pp) != length: - raise 'FATAL', 'inconsistent length. thought ' + `length` + ', but should really be ' + `len(pp)` - if i >= length: - break - ch = pp[i] - i = i + 1 - - if type(ch) == type(''): - #normally, only chunks are present in pp, - # but in some cases, some extra info - # has been inserted, e.g., the \end{...} clauses - raise 'FATAL', 'got string, probably too many ' + `end` - - if ch.chtype == chunk_type(GROUP): - # check for {\em ...} constructs - if ch.data and \ - ch.data[0].chtype == chunk_type(CSNAME) and \ - s(buf, ch.data[0].data) in fontchanges.keys(): - k = s(buf, ch.data[0].data) - del ch.data[0] - pp.insert(i-1, chunk(CSNAME, ch.where, fontchanges[k])) - length, i = length+1, i+1 - - # recursively parse the contents of the group - changeit(buf, ch.data) - - elif ch.chtype == chunk_type(IF): - # \if... - flag, negate, data = ch.data - ##print 'IF: flag, negate = ' + `flag, negate` - if flag not in flags.keys(): - raise error, 'unknown flag ' + `flag` - - value = flags[flag] - if negate: - value = (not value) - del pp[i-1] - length, i = length-1, i-1 - if value: - pp[i:i] = data - length = length + len(data) - - - elif ch.chtype == chunk_type(ENV): - # \begin{...} .... - envname, data = ch.data - - #push this environment name on stack - hist.inenv.insert(0, envname) - - #append an endenv chunk after grouped data - data.append(chunk(ENDENV, ch.where, envname)) - ##[`data`] - - #delete this object - del pp[i-1] - i, length = i-1, length-1 - - #insert found data - pp[i:i] = data - length = length + len(data) - - if envname == 'verbatim': - pp[i:i] = [chunk(CSLINE, ch.where, 'example'), \ - chunk(GROUP, ch.where, [])] - length, i = length+2, i+2 - - elif envname == 'itemize': - if hist.itemizenesting > len(itemizesymbols): - raise error, 'too deep itemize nesting' - ingroupch = [chunk(CSNAME, ch.where,\ - itemizesymbols[hist.itemizenesting])] - hist.itemizenesting = hist.itemizenesting + 1 - pp[i:i] = [chunk(CSLINE, ch.where, 'itemize'),\ - chunk(GROUP, ch.where, ingroupch)] - length, i = length+2, i+2 - - elif envname == 'enumerate': - if hist.enumeratenesting > len(enumeratesymbols): - raise error, 'too deep enumerate nesting' - ingroupch = [chunk(PLAIN, ch.where,\ - enumeratesymbols[hist.enumeratenesting])] - hist.enumeratenesting = hist.enumeratenesting + 1 - pp[i:i] = [chunk(CSLINE, ch.where, 'enumerate'),\ - chunk(GROUP, ch.where, ingroupch)] - length, i = length+2, i+2 - - elif envname == 'description': - ingroupch = [chunk(CSNAME, ch.where, 'b')] - pp[i:i] = [chunk(CSLINE, ch.where, 'table'), \ - chunk(GROUP, ch.where, ingroupch)] - length, i = length+2, i+2 - - elif envname == 'tableiii': - wh = ch.where - newcode = [] - - #delete tabular format description - # e.g., {|l|c|l|} - length, newi = getnextarg(length, buf, pp, i) - del pp[i:newi] - length = length - (newi-i) - - newcode.append(chunk(CSLINE, wh, 'table')) - ingroupch = [chunk(CSNAME, wh, 'asis')] - newcode.append(chunk(GROUP, wh, ingroupch)) - newcode.append(chunk(CSLINE, wh, 'item')) - - #get the name of macro for @item - # e.g., {code} - length, newi = getnextarg(length, buf, pp, i) - - if newi-i != 1: - raise error, 'Sorry, expected 1 chunk argument' - if pp[i].chtype != chunk_type(PLAIN): - raise error, 'Sorry, expected plain text argument' - hist.itemargmacro = s(buf, pp[i].data) - del pp[i:newi] - length = length - (newi-i) - - for count in range(3): - length, newi = getnextarg(length, buf, pp, i) - emphgroup = [\ - chunk(CSNAME, wh, 'emph'), \ - chunk(GROUP, 0, pp[i:newi])] - del pp[i:newi] - length = length - (newi-i) - if count == 0: - itemarg = emphgroup - elif count == 2: - itembody = itembody + \ - [chunk(PLAIN, wh, ' --- ')] + \ - emphgroup - else: - itembody = emphgroup - newcode.append(chunk(GROUP, wh, itemarg)) - newcode = newcode + itembody + [chunk(DENDLINE, wh, '\n')] - pp[i:i] = newcode - l = len(newcode) - length, i = length+l, i+l - del newcode, l - - if length != len(pp): - raise 'STILL, SOMETHING wrong', `i` - - - elif envname == 'funcdesc': - pp.insert(i, chunk(PLAIN, ch.where, '')) - i, length = i+1, length+1 - length, i = do_funcdesc(length, buf, pp, i) - - elif envname == 'excdesc': - pp.insert(i, chunk(PLAIN, ch.where, '')) - i, length = i+1, length+1 - length, i = do_excdesc(length, buf, pp, i) - - elif envname == 'datadesc': - pp.insert(i, chunk(PLAIN, ch.where, '')) - i, length = i+1, length+1 - length, i = do_datadesc(length, buf, pp, i) - - else: - print 'WARNING: don\'t know what to do with env ' + `envname` - - elif ch.chtype == chunk_type(ENDENV): - envname = ch.data - if envname != hist.inenv[0]: - raise error, '\'end\' does not match. Name ' + `envname` + ', expected ' + `hist.inenv[0]` - del hist.inenv[0] - del pp[i-1] - i, length = i-1, length-1 - - if envname == 'verbatim': - pp[i:i] = [\ - chunk(CSLINE, ch.where, 'end'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, 'example')])] - i, length = i+2, length+2 - elif envname == 'itemize': - hist.itemizenesting = hist.itemizenesting - 1 - pp[i:i] = [\ - chunk(CSLINE, ch.where, 'end'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, 'itemize')])] - i, length = i+2, length+2 - elif envname == 'enumerate': - hist.enumeratenesting = hist.enumeratenesting-1 - pp[i:i] = [\ - chunk(CSLINE, ch.where, 'end'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, 'enumerate')])] - i, length = i+2, length+2 - elif envname == 'description': - pp[i:i] = [\ - chunk(CSLINE, ch.where, 'end'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, 'table')])] - i, length = i+2, length+2 - elif envname == 'tableiii': - pp[i:i] = [\ - chunk(CSLINE, ch.where, 'end'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, 'table')])] - i, length = i+2, length + 2 - pp.insert(i, chunk(DENDLINE, ch.where, '\n')) - i, length = i+1, length+1 - - elif envname in ('funcdesc', 'excdesc', 'datadesc'): - pp[i:i] = [\ - chunk(CSLINE, ch.where, 'end'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, hist.command)])] - i, length = i+2, length+2 - else: - print 'WARNING: ending env ' + `envname` + 'has no actions' - - elif ch.chtype == chunk_type(CSNAME): - # control name transformations - if s(buf, ch.data) in ignoredcommands: - del pp[i-1] - i, length = i-1, length-1 - elif s(buf, ch.data) == '@' and \ - i != length and \ - pp[i].chtype == chunk_type(PLAIN) and \ - s(buf, pp[i].data)[0] == '.': - # \@. --> \. --> @. - ch.data = '.' - del pp[i] - length = length-1 - elif s(buf, ch.data) == '\\': - # \\ --> \* --> @* - ch.data = '*' - elif len(s(buf, ch.data)) == 1 and \ - s(buf, ch.data) in onlylatexspecial: - ch.chtype = chunk_type(PLAIN) - # check if such a command is followed by - # an empty group: e.g., `\%{}'. If so, remove - # this empty group too - if i < length and \ - pp[i].chtype == chunk_type(GROUP) \ - and len(pp[i].data) == 0: - del pp[i] - length = length-1 - - elif hist.inargs and s(buf, ch.data) in inargsselves: - # This is the special processing of the - # arguments of the \begin{funcdesc}... or - # \funcline... arguments - # \, --> , \[ --> [, \] --> ] - ch.chtype = chunk_type(PLAIN) - - elif s(buf, ch.data) == 'renewcommand': - # \renewcommand{\indexsubitem}.... - i, length = i-1, length-1 - del pp[i] - length, newi = getnextarg(length, buf, pp, i) - if newi-i == 1 \ - and i < length \ - and pp[i].chtype == chunk_type(CSNAME) \ - and s(buf, pp[i].data) == 'indexsubitem': - del pp[i:newi] - length = length - (newi-i) - length, newi = getnextarg(length, buf, pp, i) - text = flattext(buf, pp[i:newi]) - if text[0] != '(' or text[-1] != ')': - raise error, 'expected indexsubitme enclosed in braces' - words = string.split(text[1:-1]) - hist.indexsubitem = words - del text, words - else: - print 'WARNING: renewcommand with unsupported arg removed' - del pp[i:newi] - length = length - (newi-i) - - elif s(buf, ch.data) == 'item': - ch.chtype = chunk_type(CSLINE) - length, newi = getoptarg(length, buf, pp, i) - ingroupch = pp[i:newi] - del pp[i:newi] - length = length - (newi-i) - pp.insert(i, chunk(GROUP, ch.where, ingroupch)) - i, length = i+1, length+1 - - elif s(buf, ch.data) == 'ttindex': - idxsi = hist.indexsubitem - - cat_class = '' - if len(idxsi) >= 2 and idxsi[1] in \ - ('method', 'function'): - command = 'findex' - elif len(idxsi) >= 2 and idxsi[1] in \ - ('exception', 'object'): - command = 'vindex' - else: - print 'WARNING: can\'t categorize ' + `idxsi` + ' for \'ttindex\' command' - command = 'cindex' - - if not cat_class: - cat_class = '('+string.join(idxsi)+')' - - ch.chtype = chunk_type(CSLINE) - ch.data = command - - length, newi = getnextarg(length, buf, pp, i) - arg = pp[i:newi] - del pp[i:newi] - length = length - (newi-i) - - cat_arg = [chunk(PLAIN, ch.where, cat_class)] - - # determine what should be set in roman, and - # what in tt-font - if command in regindices: - - arg = [chunk(CSNAME, ch.where, 't'), \ - chunk(GROUP, ch.where, arg)] - else: - cat_arg = [chunk(CSNAME, ch.where, 'r'), \ - chunk(GROUP, ch.where, cat_arg)] - - ingroupch = arg + \ - [chunk(PLAIN, ch.where, ' ')] + \ - cat_arg - - pp.insert(i, chunk(GROUP, ch.where, ingroupch)) - length, i = length+1, i+1 - - - elif s(buf, ch.data) == 'ldots': - # \ldots --> \dots{} --> @dots{} - ch.data = 'dots' - if i == length \ - or pp[i].chtype != chunk_type(GROUP) \ - or pp[i].data != []: - pp.insert(i, chunk(GROUP, ch.where, [])) - i, length = i+1, length+1 - elif s(buf, ch.data) in wordsselves: - # \UNIX --> UNIX - ch.chtype = chunk_type(PLAIN) - if i != length \ - and pp[i].chtype == chunk_type(GROUP) \ - and pp[i].data == []: - del pp[i] - length = length-1 - elif s(buf, ch.data) in for_texi: - pass - - elif s(buf, ch.data) == 'e': - # \e --> \ - ch.data = '\\' - ch.chtype = chunk_type(PLAIN) - elif s(buf, ch.data) == 'lineiii': - # This is the most tricky one - # \lineiii{a1}{a2}[{a3}] --> - # @item @{a1} - # a2 [ -- a3] - # - ##print 'LINEIIIIII!!!!!!!' -## wobj = Wobj().init() -## dumpit(buf, wobj.write, pp[i-1:i+5]) -## print '--->' + wobj.data + '<----' - if not hist.inenv: - raise error, \ - 'no environment for lineiii' - if hist.inenv[0] != 'tableiii': - raise error, \ - 'wrong command (' + \ - `'lineiii'` + \ - ') in wrong environment (' \ - + `hist.inenv[0]` + ')' - ch.chtype = chunk_type(CSLINE) - ch.data = 'item' - length, newi = getnextarg(length, buf, pp, i) - ingroupch = [chunk(CSNAME, 0, \ - hist.itemargmacro), \ - chunk(GROUP, 0, pp[i:newi])] - del pp[i:newi] - length = length - (newi-i) -## print 'ITEM ARG: --->', -## wobj = Wobj().init() -## dumpit(buf, wobj.write, ingroupch) -## print wobj.data, '<---' - pp.insert(i, chunk(GROUP, ch.where, ingroupch)) - grouppos = i - i, length = i+1, length+1 - length, i = getnextarg(length, buf, pp, i) - length, newi = getnextarg(length, buf, pp, i) - if newi > i: - # we have a 3rd arg - pp.insert(i, chunk(PLAIN, ch.where, ' --- ')) - i = newi + 1 - length = length + 1 -## pp[grouppos].data = pp[grouppos].data \ -## + [chunk(PLAIN, ch.where, ' ')] \ -## + pp[i:newi] -## del pp[i:newi] -## length = length - (newi-i) - if length != len(pp): - raise 'IN LINEIII IS THE ERR', `i` - - elif s(buf, ch.data) in ('chapter', 'section', 'subsection', 'subsubsection'): - #\xxxsection{A} ----> - # @node A, , , - # @xxxsection A - ## also: remove commas and quotes - ch.chtype = chunk_type(CSLINE) - length, newi = getnextarg(length, buf, pp, i) - afternodenamecmd = next_command_p(length, buf, pp, newi, 'nodename') - if afternodenamecmd < 0: - cp1 = crcopy(pp[i:newi]) - pp[i:newi] = [\ - chunk(GROUP, ch.where, \ - pp[i:newi])] - length, newi = length - (newi-i) + 1, \ - i+1 - text = flattext(buf, cp1) - text = invent_node_names(text) - else: - length, endarg = getnextarg(length, buf, pp, afternodenamecmd) - cp1 = crcopy(pp[afternodenamecmd:endarg]) - del pp[newi:endarg] - length = length - (endarg-newi) - - pp[i:newi] = [\ - chunk(GROUP, ch.where, \ - pp[i:newi])] - length, newi = length - (newi-i) + 1, \ - i + 1 - text = flattext(buf, cp1) - if text[-1] == '.': - text = text[:-1] -## print 'FLATTEXT:', `text` - if text in hist.nodenames: - print 'WARNING: node name ' + `text` + ' already used' - out.doublenodes.append(text) - else: - hist.nodenames.append(text) - text = rm_commas_etc(text) - pp[i-1:i-1] = [\ - chunk(CSLINE, ch.where, 'node'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, text+', , ,')\ - ])] - i, length = newi+2, length+2 - - elif s(buf,ch.data) == 'funcline': - # fold it to a very short environment - pp[i-1:i-1] = [\ - chunk(CSLINE, ch.where, 'end'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, hist.command)])] - i, length = i+2, length+2 - length, i = do_funcdesc(length, buf, pp, i) - - elif s(buf,ch.data) == 'dataline': - pp[i-1:i-1] = [\ - chunk(CSLINE, ch.where, 'end'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, hist.command)])] - i, length = i+2, length+2 - length, i = do_datadesc(length, buf, pp, i) - - elif s(buf,ch.data) == 'excline': - pp[i-1:i-1] = [\ - chunk(CSLINE, ch.where, 'end'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, hist.command)])] - i, length = i+2, length+2 - length, i = do_excdesc(length, buf, pp, i) - - - elif s(buf, ch.data) == 'index': - #\index{A} ---> - # @cindex A - ch.chtype = chunk_type(CSLINE) - ch.data = 'cindex' - length, newi = getnextarg(length, buf, pp, i) - - ingroupch = pp[i:newi] - del pp[i:newi] - length = length - (newi-i) - pp.insert(i, chunk(GROUP, ch.where, ingroupch)) - length, i = length+1, i+1 - - elif s(buf, ch.data) == 'bifuncindex': - ch.chtype = chunk_type(CSLINE) - ch.data = 'findex' - length, newi = getnextarg(length, buf, pp, i) - ingroupch = pp[i:newi] - del pp[i:newi] - length = length - (newi-i) - - ingroupch.append(chunk(PLAIN, ch.where, ' ')) - ingroupch.append(chunk(CSNAME, ch.where, 'r')) - ingroupch.append(chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, \ - '(built-in function)')])) - - pp.insert(i, chunk(GROUP, ch.where, ingroupch)) - length, i = length+1, i+1 - - - elif s(buf, ch.data) == 'opindex': - ch.chtype = chunk_type(CSLINE) - ch.data = 'findex' - length, newi = getnextarg(length, buf, pp, i) - ingroupch = pp[i:newi] - del pp[i:newi] - length = length - (newi-i) - - ingroupch.append(chunk(PLAIN, ch.where, ' ')) - ingroupch.append(chunk(CSNAME, ch.where, 'r')) - ingroupch.append(chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, \ - '(operator)')])) - - pp.insert(i, chunk(GROUP, ch.where, ingroupch)) - length, i = length+1, i+1 - - - elif s(buf, ch.data) == 'bimodindex': - ch.chtype = chunk_type(CSLINE) - ch.data = 'pindex' - length, newi = getnextarg(length, buf, pp, i) - ingroupch = pp[i:newi] - del pp[i:newi] - length = length - (newi-i) - - ingroupch.append(chunk(PLAIN, ch.where, ' ')) - ingroupch.append(chunk(CSNAME, ch.where, 'r')) - ingroupch.append(chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, \ - '(built-in)')])) - - pp.insert(i, chunk(GROUP, ch.where, ingroupch)) - length, i = length+1, i+1 - - elif s(buf, ch.data) == 'sectcode': - ch.data = 'code' - - - elif s(buf, ch.data) == 'stmodindex': - ch.chtype = chunk_type(CSLINE) - # use the program index as module index - ch.data = 'pindex' - length, newi = getnextarg(length, buf, pp, i) - ingroupch = pp[i:newi] - del pp[i:newi] - length = length - (newi-i) - - ingroupch.append(chunk(PLAIN, ch.where, ' ')) - ingroupch.append(chunk(CSNAME, ch.where, 'r')) - ingroupch.append(chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, \ - '(standard)')])) - - pp.insert(i, chunk(GROUP, ch.where, ingroupch)) - length, i = length+1, i+1 - - - elif s(buf, ch.data) == 'stindex': - # XXX must actually go to newindex st - wh = ch.where - ch.chtype = chunk_type(CSLINE) - ch.data = 'cindex' - length, newi = getnextarg(length, buf, pp, i) - ingroupch = [chunk(CSNAME, wh, 'code'), \ - chunk(GROUP, wh, pp[i:newi])] - - del pp[i:newi] - length = length - (newi-i) - - t = ingroupch[:] - t.append(chunk(PLAIN, wh, ' statement')) - - pp.insert(i, chunk(GROUP, wh, t)) - i, length = i+1, length+1 - - pp.insert(i, chunk(CSLINE, wh, 'cindex')) - i, length = i+1, length+1 - - t = ingroupch[:] - t.insert(0, chunk(PLAIN, wh, 'statement, ')) - - pp.insert(i, chunk(GROUP, wh, t)) - i, length = i+1, length+1 - - - elif s(buf, ch.data) == 'indexii': - #\indexii{A}{B} ---> - # @cindex A B - # @cindex B, A - length, newi = getnextarg(length, buf, pp, i) - cp11 = pp[i:newi] - cp21 = crcopy(pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - length, newi = getnextarg(length, buf, pp, i) - cp12 = pp[i:newi] - cp22 = crcopy(pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - - ch.chtype = chunk_type(CSLINE) - ch.data = 'cindex' - pp.insert(i, chunk(GROUP, ch.where, cp11 + [\ - chunk(PLAIN, ch.where, ' ')] + cp12)) - i, length = i+1, length+1 - pp[i:i] = [chunk(CSLINE, ch.where, 'cindex'), \ - chunk(GROUP, ch.where, cp22 + [\ - chunk(PLAIN, ch.where, ', ')]+ cp21)] - i, length = i+2, length+2 - - elif s(buf, ch.data) == 'indexiii': - length, newi = getnextarg(length, buf, pp, i) - cp11 = pp[i:newi] - cp21 = crcopy(pp[i:newi]) - cp31 = crcopy(pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - length, newi = getnextarg(length, buf, pp, i) - cp12 = pp[i:newi] - cp22 = crcopy(pp[i:newi]) - cp32 = crcopy(pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - length, newi = getnextarg(length, buf, pp, i) - cp13 = pp[i:newi] - cp23 = crcopy(pp[i:newi]) - cp33 = crcopy(pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - - ch.chtype = chunk_type(CSLINE) - ch.data = 'cindex' - pp.insert(i, chunk(GROUP, ch.where, cp11 + [\ - chunk(PLAIN, ch.where, ' ')] + cp12 \ - + [chunk(PLAIN, ch.where, ' ')] \ - + cp13)) - i, length = i+1, length+1 - pp[i:i] = [chunk(CSLINE, ch.where, 'cindex'), \ - chunk(GROUP, ch.where, cp22 + [\ - chunk(PLAIN, ch.where, ' ')]+ cp23\ - + [chunk(PLAIN, ch.where, ', ')] +\ - cp21)] - i, length = i+2, length+2 - pp[i:i] = [chunk(CSLINE, ch.where, 'cindex'), \ - chunk(GROUP, ch.where, cp33 + [\ - chunk(PLAIN, ch.where, ', ')]+ cp31\ - + [chunk(PLAIN, ch.where, ' ')] +\ - cp32)] - i, length = i+2, length+2 - - - elif s(buf, ch.data) == 'indexiv': - length, newi = getnextarg(length, buf, pp, i) - cp11 = pp[i:newi] - cp21 = crcopy(pp[i:newi]) - cp31 = crcopy(pp[i:newi]) - cp41 = crcopy(pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - length, newi = getnextarg(length, buf, pp, i) - cp12 = pp[i:newi] - cp22 = crcopy(pp[i:newi]) - cp32 = crcopy(pp[i:newi]) - cp42 = crcopy(pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - length, newi = getnextarg(length, buf, pp, i) - cp13 = pp[i:newi] - cp23 = crcopy(pp[i:newi]) - cp33 = crcopy(pp[i:newi]) - cp43 = crcopy(pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - length, newi = getnextarg(length, buf, pp, i) - cp14 = pp[i:newi] - cp24 = crcopy(pp[i:newi]) - cp34 = crcopy(pp[i:newi]) - cp44 = crcopy(pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - - ch.chtype = chunk_type(CSLINE) - ch.data = 'cindex' - ingroupch = cp11 + \ - spacech + cp12 + \ - spacech + cp13 + \ - spacech + cp14 - pp.insert(i, chunk(GROUP, ch.where, ingroupch)) - i, length = i+1, length+1 - ingroupch = cp22 + \ - spacech + cp23 + \ - spacech + cp24 + \ - commach + cp21 - pp[i:i] = cindexch + [\ - chunk(GROUP, ch.where, ingroupch)] - i, length = i+2, length+2 - ingroupch = cp33 + \ - spacech + cp34 + \ - commach + cp31 + \ - spacech + cp32 - pp[i:i] = cindexch + [\ - chunk(GROUP, ch.where, ingroupch)] - i, length = i+2, length+2 - ingroupch = cp44 + \ - commach + cp41 + \ - spacech + cp42 + \ - spacech + cp43 - pp[i:i] = cindexch + [\ - chunk(GROUP, ch.where, ingroupch)] - i, length = i+2, length+2 - - - - else: - print 'don\'t know what to do with keyword ' + `s(buf, ch.data)` - - - -re_atsign = regex.compile('[@{}]') -re_newline = regex.compile('\n') - -def dumpit(buf, wm, pp): - - global out - - i, length = 0, len(pp) - - addspace = 0 - - while 1: - if len(pp) != length: - raise 'FATAL', 'inconsistent length' - if i == length: - break - ch = pp[i] - i = i + 1 - - if addspace: - dospace = 1 - addspace = 0 - else: - dospace = 0 - - if ch.chtype == chunk_type(CSNAME): - wm('@' + s(buf, ch.data)) - if s(buf, ch.data) == 'node' and \ - pp[i].chtype == chunk_type(PLAIN) and \ - s(buf, pp[i].data) in out.doublenodes: - ##XXX doesnt work yet?? - wm(' ZZZ-' + zfill(`i`, 4)) - if s(buf, ch.data)[0] in string.letters: - addspace = 1 - elif ch.chtype == chunk_type(PLAIN): - if dospace and s(buf, ch.data) not in (' ', '\t'): - wm(' ') - text = s(buf, ch.data) - while 1: - pos = re_atsign.search(text) - if pos < 0: - break - wm(text[:pos] + '@' + text[pos]) - text = text[pos+1:] - wm(text) - elif ch.chtype == chunk_type(GROUP): - wm('{') - dumpit(buf, wm, ch.data) - wm('}') - elif ch.chtype == chunk_type(DENDLINE): - wm('\n\n') - while i != length and pp[i].chtype in \ - (chunk_type(DENDLINE), chunk_type(ENDLINE)): - i = i + 1 - elif ch.chtype == chunk_type(OTHER): - wm(s(buf, ch.data)) - elif ch.chtype == chunk_type(ACTIVE): - wm(s(buf, ch.data)) - elif ch.chtype == chunk_type(ENDLINE): - wm('\n') - elif ch.chtype == chunk_type(CSLINE): - if i >= 2 and pp[i-2].chtype not in \ - (chunk_type(ENDLINE), chunk_type(DENDLINE)) \ - and (pp[i-2].chtype != chunk_type(PLAIN) \ - or s(buf, pp[i-2].data)[-1] != '\n'): - - wm('\n') - wm('@' + s(buf, ch.data)) - if i == length: - raise error, 'CSLINE expected another chunk' - if pp[i].chtype != chunk_type(GROUP): - raise error, 'CSLINE expected GROUP' - if type(pp[i].data) != type([]): - raise error, 'GROUP chould contain []-data' - - wobj = Wobj().init() - dumpit(buf, wobj.write, pp[i].data) - i = i + 1 - text = wobj.data - del wobj - if text: - wm(' ') - while 1: - pos = re_newline.search(text) - if pos < 0: - break - print 'WARNING: found newline in csline arg' - wm(text[:pos] + ' ') - text = text[pos+1:] - wm(text) - if i >= length or \ - pp[i].chtype not in (chunk_type(CSLINE), \ - chunk_type(ENDLINE), chunk_type(DENDLINE)) \ - and (pp[i].chtype != chunk_type(PLAIN) \ - or s(buf, pp[i].data)[0] != '\n'): - wm('\n') - - elif ch.chtype == chunk_type(COMMENT): -## print 'COMMENT: previous chunk =', pp[i-2] - if pp[i-2].chtype == chunk_type(PLAIN): - print 'PLAINTEXT =', `s(buf, pp[i-2].data)` - if s(buf, ch.data) and \ - regex.match('^[ \t]*$', s(buf, ch.data)) < 0: - if i >= 2 and pp[i-2].chtype not in \ - (chunk_type(ENDLINE), chunk_type(DENDLINE)) \ - and not (pp[i-2].chtype == chunk_type(PLAIN) \ - and regex.match('\\(.\\|\n\\)*[ \t]*\n$', s(buf, pp[i-2].data)) >= 0): - print 'ADDING NEWLINE' - wm('\n') - wm('@c ' + s(buf, ch.data)) - elif ch.chtype == chunk_type(IGNORE): - pass - else: - try: - str = `s(buf, ch.data)` - except TypeError: - str = `ch.data` - if len(str) > 400: - str = str[:400] + '...' - print 'warning:', ch.chtype, 'not handled, data ' + str - - - -def main(): - outfile = None - headerfile = 'texipre.dat' - trailerfile = 'texipost.dat' - - try: - opts, args = getopt.getopt(sys.argv[1:], 'o:h:t:') - except getopt.error: - args = [] - - if not args: - print 'usage: partparse [-o outfile] [-h headerfile]', - print '[-t trailerfile] file ...' - sys.exit(2) - - for opt, arg in opts: - if opt == '-o': outfile = arg - if opt == '-h': headerfile = arg - if opt == '-t': trailerfile = arg - - if not outfile: - root, ext = os.path.splitext(args[0]) - outfile = root + '.texi' - - if outfile in args: - print 'will not overwrite input file', outfile - sys.exit(2) - - outf = open(outfile, 'w') - outf.write(open(headerfile, 'r').read()) - - for file in args: - if len(args) > 1: print '='*20, file, '='*20 - buf = open(file, 'r').read() - w, pp = parseit(buf) - startchange() - changeit(buf, pp) - dumpit(buf, outf.write, pp) - - outf.write(open(trailerfile, 'r').read()) - - outf.close() - -main() diff --git a/Doc/qua.tex b/Doc/qua.tex deleted file mode 100644 index 7cca09d3c0..0000000000 --- a/Doc/qua.tex +++ /dev/null @@ -1,1235 +0,0 @@ -\documentstyle[11pt]{article} - -\title{ -Interactively Testing Remote Servers Using the Python Programming Language -} - -\author{ - Guido van Rossum \\ - Dept. CST, CWI, P.O. Box 94079 \\ - 1090 GB Amsterdam, The Netherlands \\ - E-mail: {\tt guido@cwi.nl} -\and - Jelke de Boer \\ - HIO Enschede; P.O.Box 1326 \\ - 7500 BH Enschede, The Netherlands -} - -\begin{document} - -\maketitle - -\begin{abstract} -This paper describes how two tools that were developed quite -independently gained in power by a well-designed connection between -them. The tools are Python, an interpreted prototyping language, and -AIL, a Remote Procedure Call stub generator. The context is Amoeba, a -well-known distributed operating system developed jointly by the Free -University and CWI in Amsterdam. - -As a consequence of their integration, both tools have profited: -Python gained usability when used with Amoeba --- for which it was not -specifically developed --- and AIL users now have a powerful -interactive tool to test servers and to experiment with new -client/server interfaces.% -\footnote{ -An earlier version of this paper was presented at the Spring 1991 -EurOpen Conference in Troms{\o} under the title ``Linking a Stub -Generator (AIL) to a Prototyping Language (Python).'' -} -\end{abstract} - -\section{Introduction} - -Remote Procedure Call (RPC) interfaces, used in distributed systems -like Amoeba -\cite{Amoeba:IEEE,Amoeba:CACM}, -have a much more concrete character than local procedure call -interfaces in traditional systems. Because clients and servers may -run on different machines, with possibly different word size, byte -order, etc., much care is needed to describe interfaces exactly and to -implement them in such a way that they continue to work when a client -or server is moved to a different machine. Since machines may fail -independently, error handling must also be treated more carefully. - -A common approach to such problems is to use a {\em stub generator}. -This is a program that takes an interface description and transforms -it into functions that must be compiled and linked with client and -server applications. These functions are called by the application -code to take care of details of interfacing to the system's RPC layer, -to implement transformations between data representations of different -machines, to check for errors, etc. They are called `stubs' because -they don't actually perform the action that they are called for but -only relay the parameters to the server -\cite{RPC}. - -Amoeba's stub generator is called AIL, which stands for Amoeba -Interface Language -\cite{AIL}. -The first version of AIL generated only C functions, but an explicit -goal of AIL's design was {\em retargetability}: it should be possible -to add back-ends that generate stubs for different languages from the -same interface descriptions. Moreover, the stubs generated by -different back-ends must be {\em interoperable}: a client written in -Modula-3, say, should be able to use a server written in C, and vice -versa. - -This interoperability is the key to the success of the marriage -between AIL and Python. Python is a versatile interpreted language -developed by the first author. Originally intended as an alternative -for the kind of odd jobs that are traditionally solved by a mixture of -shell scripts, manually given shell commands, and an occasional ad hoc -C program, Python has evolved into a general interactive prototyping -language. It has been applied to a wide range of problems, from -replacements for large shell scripts to fancy graphics demos and -multimedia applications. - -One of Python's strengths is the ability for the user to type in some -code and immediately run it: no compilation or linking is necessary. -Interactive performance is further enhanced by Python's concise, clear -syntax, its very-high-level data types, and its lack of declarations -(which is compensated by run-time type checking). All this makes -programming in Python feel like a leisure trip compared to the hard -work involved in writing and debugging even a smallish C program. - -It should be clear by now that Python will be the ideal tool to test -servers and their interfaces. Especially during the development of a -complex server, one often needs to generate test requests on an ad hoc -basis, to answer questions like ``what happens if request X arrives -when the server is in state Y,'' to test the behavior of the server -with requests that touch its limitations, to check server responses to -all sorts of wrong requests, etc. Python's ability to immediately -execute `improvised' code makes it a much better tool for this -situation than C. - -The link to AIL extends Python with the necessary functionality to -connect to arbitrary servers, making the server testbed sketched above -a reality. Python's high-level data types, general programming -features, and system interface ensure that it has all the power and -flexibility needed for the job. - -One could go even further than this. Current distributed operating -systems, based on client-server interaction, all lack a good command -language or `shell' to give adequate access to available services. -Python has considerable potential for becoming such a shell. - -\subsection{Overview of this Paper} - -The rest of this paper contains three major sections and a conclusion. -First an overview of the Python programming language is given. Next -comes a short description of AIL, together with some relevant details -about Amoeba. Finally, the design and construction of the link -between Python and AIL is described in much detail. The conclusion -looks back at the work and points out weaknesses and strengths of -Python and AIL that were discovered in the process. - -\section{An Overview of Python} - -Python% -\footnote{ -Named after the funny TV show, not the nasty reptile. -} -owes much to ABC -\cite{ABC}, -a language developed at CWI as a programming language for non-expert -computer users. Python borrows freely from ABC's syntax and data -types, but adds modules, exceptions and classes, extensibility, and -the ability to call system functions. The concepts of modules, -exceptions and (to some extent) classes are influenced strongly by -their occurrence in Modula-3 -\cite{Modula-3}. - -Although Python resembles ABC in many ways, there is a a clear -difference in application domain. ABC is intended to be the only -programming language for those who use a computer as a tool, but -occasionally need to write a program. For this reason, ABC is not -just a programming language but also a programming environment, which -comes with an integrated syntax-directed editor and some source -manipulation commands. Python, on the other hand, aims to be a tool -for professional (system) programmers, for whom having a choice of -languages with different feature sets makes it possible to choose `the -right tool for the job.' The features added to Python make it more -useful than ABC in an environment where access to system functions -(such as file and directory manipulations) are common. They also -support the building of larger systems and libraries. The Python -implementation offers little in the way of a programming environment, -but is designed to integrate seamlessly with existing programming -environments (e.g. UNIX and Emacs). - -Perhaps the best introduction to Python is a short example. The -following is a complete Python program to list the contents of a UNIX -directory. -\begin{verbatim} -import sys, posix - -def ls(dirname): # Print sorted directory contents - names = posix.listdir(dirname) - names.sort() - for name in names: - if name[0] != '.': print name - -ls(sys.argv[1]) -\end{verbatim} -The largest part of this program, in the middle starting with {\tt -def}, is a function definition. It defines a function named {\tt ls} -with a single parameter called {\tt dirname}. (Comments in Python -start with `\#' and extend to the end of the line.) The function body -is indented: Python uses indentation for statement grouping instead of -braces or begin/end keywords. This is shorter to type and avoids -frustrating mismatches between the perception of grouping by the user -and the parser. Python accepts one statement per line; long -statements may be broken in pieces using the standard backslash -convention. If the body of a compound statement is a single, simple -statement, it may be placed on the same line as the head. - -The first statement of the function body calls the function {\tt -listdir} defined in the module {\tt posix}. This function returns a -list of strings representing the contents of the directory name passed -as a string argument, here the argument {\tt dirname}. If {\tt -dirname} were not a valid directory name, or perhaps not even a -string, {\tt listdir} would raise an exception and the next statement -would never be reached. (Exceptions can be caught in Python; see -later.) Assuming {\tt listdir} returns normally, its result is -assigned to the local variable {\tt names}. - -The second statement calls the method {\tt sort} of the variable {\tt -names}. This method is defined for all lists in Python and does the -obvious thing: the elements of the list are reordered according to -their natural ordering relationship. Since in our example the list -contains strings, they are sorted in ascending ASCII order. - -The last two lines of the function contain a loop that prints all -elements of the list whose first character isn't a period. In each -iteration, the {\tt for} statement assigns an element of the list to -the local variable {\tt name}. The {\tt print} statement is intended -for simple-minded output; more elaborate formatting is possible with -Python's string handling functions. - -The other two parts of the program are easily explained. The first -line is an {\tt import} statement that tells the interpreter to import -the modules {\tt sys} and {\tt posix}. As it happens these are both -built into the interpreter. Importing a module (built-in or -otherwise) only makes the module name available in the current scope; -functions and data defined in the module are accessed through the dot -notation as in {\tt posix.listdir}. The scope rules of Python are -such that the imported module name {\tt posix} is also available in -the function {\tt ls} (this will be discussed in more detail later). - -Finally, the last line of the program calls the {\tt ls} function with -a definite argument. It must be last since Python objects must be -defined before they can be used; in particular, the function {\tt ls} -must be defined before it can be called. The argument to {\tt ls} is -{\tt sys.argv[1]}, which happens to be the Python equivalent of {\tt -\$1} in a shell script or {\tt argv[1]} in a C program's {\tt main} -function. - -\subsection{Python Data Types} - -(This and the following subsections describe Python in quite a lot of -detail. If you are more interested in AIL, Amoeba and how they are -linked with Python, you can skip to section 3 now.) - -Python's syntax may not have big surprises (which is exactly as it -should be), but its data types are quite different from what is found -in languages like C, Ada or Modula-3. All data types in Python, even -integers, are `objects'. All objects participate in a common garbage -collection scheme (currently implemented using reference counting). -Assignment is cheap, independent of object size and type: only a -pointer to the assigned object is stored in the assigned-to variable. -No type checking is performed on assignment; only specific operations -like addition test for particular operand types. - -The basic object types in Python are numbers, strings, tuples, lists -and dictionaries. Some other object types are open files, functions, -modules, classes, and class instances; even types themselves are -represented as objects. Extension modules written in C can define -additional object types; examples are objects representing windows and -Amoeba capabilities. Finally, the implementation itself makes heavy -use of objects, and defines some private object types that aren't -normally visible to the user. There is no explicit pointer type in -Python. - -{\em Numbers}, both integers and floating point, are pretty -straightforward. The notation for numeric literals is the same as in -C, including octal and hexadecimal integers; precision is the same as -{\tt long} or {\tt double} in C\@. A third numeric type, `long -integer', written with an `L' suffix, can be used for arbitrary -precision calculations. All arithmetic, shifting and masking -operations from C are supported. - -{\em Strings} are `primitive' objects just like numbers. String -literals are written between single quotes, using similar escape -sequences as in C\@. Operations are built into the language to -concatenate and to replicate strings, to extract substrings, etc. -There is no limit to the length of the strings created by a program. -There is no separate character data type; strings of length one do -nicely. - -{\em Tuples} are a way to `pack' small amounts of heterogeneous data -together and carry them around as a unit. Unlike structure members in -C, tuple items are nameless. Packing and unpacking assignments allow -access to the items, for example: -\begin{verbatim} -x = 'Hi', (1, 2), 'World' # x is a 3-item tuple, - # its middle item is (1, 2) -p, q, r = x # unpack x into p, q and r -a, b = q # unpack q into a and b -\end{verbatim} -A combination of packing and unpacking assignment can be used as -parallel assignment, and is idiom for permutations, e.g.: -\begin{verbatim} -p, q = q, p # swap without temporary -a, b, c = b, c, a # cyclic permutation -\end{verbatim} -Tuples are also used for function argument lists if there is more than -one argument. A tuple object, once created, cannot be modified; but -it is easy enough to unpack it and create a new, modified tuple from -the unpacked items and assign this to the variable that held the -original tuple object (which will then be garbage-collected). - -{\em Lists} are array-like objects. List items may be arbitrary -objects and can be accessed and changed using standard subscription -notation. Lists support item insertion and deletion, and can -therefore be used as queues, stacks etc.; there is no limit to their -size. - -Strings, tuples and lists together are {\em sequence} types. These -share a common notation for generic operations on sequences such as -subscription, concatenation, slicing (taking subsequences) and -membership tests. As in C, subscripts start at 0. - -{\em Dictionaries} are `mappings' from one domain to another. The -basic operations on dictionaries are item insertion, extraction and -deletion, using subscript notation with the key as subscript. (The -current implementation allows only strings in the key domain, but a -future version of the language may remove this restriction.) - -\subsection{Statements} - -Python has various kinds of simple statements, such as assignments -and {\tt print} statements, and several kinds of compound statements, -like {\tt if} and {\tt for} statements. Formally, function -definitions and {\tt import} statements are also statements, and there -are no restrictions on the ordering of statements or their nesting: -{\tt import} may be used inside a function, functions may be defined -conditionally using an {\tt if} statement, etc. The effect of a -declaration-like statement takes place only when it is executed. - -All statements except assignments and expression statements begin with -a keyword: this makes the language easy to parse. An overview of the -most common statement forms in Python follows. - -An {\em assignment} has the general form -\vspace{\itemsep} - -\noindent -{\em variable $=$ variable $= ... =$ variable $=$ expression} -\vspace{\itemsep} - -It assigns the value of the expression to all listed variables. (As -shown in the section on tuples, variables and expressions can in fact -be comma-separated lists.) The assignment operator is not an -expression operator; there are no horrible things in Python like -\begin{verbatim} -while (p = p->next) { ... } -\end{verbatim} -Expression syntax is mostly straightforward and will not be explained -in detail here. - -An {\em expression statement} is just an expression on a line by -itself. This writes the value of the expression to standard output, -in a suitably unambiguous way, unless it is a `procedure call' (a -function call that returns no value). Writing the value is useful -when Python is used in `calculator mode', and reminds the programmer -not to ignore function results. - -The {\tt if} statement allows conditional execution. It has optional -{\tt elif} and {\tt else} parts; a construct like {\tt -if...elif...elif...elif...else} can be used to compensate for the -absence of a {\em switch} or {\em case} statement. - -Looping is done with {\tt while} and {\tt for} statements. The latter -(demonstrated in the `ls' example earlier) iterates over the elements -of a `sequence' (see the discussion of data types below). It is -possible to terminate a loop with a {\tt break} statement or to start -the next iteration with {\tt continue}. Both looping statements have -an optional {\tt else} clause which is executed after the loop is -terminated normally, but skipped when it is terminated by {\tt break}. -This can be handy for searches, to handle the case that the item is -not found. - -Python's {\em exception} mechanism is modelled after that of Modula-3. -Exceptions are raised by the interpreter when an illegal operation is -tried. It is also possible to explicitly raise an exception with the -{\tt raise} statement: -\vspace{\itemsep} - -\noindent -{\tt raise {\em expression}, {\em expression}} -\vspace{\itemsep} - -The first expression identifies which exception should be raised; -there are several built-in exceptions and the user may define -additional ones. The second, optional expression is passed to the -handler, e.g. as a detailed error message. - -Exceptions may be handled (caught) with the {\tt try} statement, which -has the following general form: -\vspace{\itemsep} - -\noindent -{\tt -\begin{tabular}{l} -try: {\em block} \\ -except {\em expression}, {\em variable}: {\em block} \\ -except {\em expression}, {\em variable}: {\em block} \\ -... \\ -except: {\em block} -\end{tabular} -} -\vspace{\itemsep} - -When an exception is raised during execution of the first block, a -search for an exception handler starts. The first {\tt except} clause -whose {\em expression} matches the exception is executed. The -expression may specify a list of exceptions to match against. A -handler without an expression serves as a `catch-all'. If there is no -match, the search for a handler continues with outer {\tt try} -statements; if no match is found on the entire invocation stack, an -error message and stack trace are printed, and the program is -terminated (interactively, the interpreter returns to its main loop). - -Note that the form of the {\tt except} clauses encourages a style of -programming whereby only selected exceptions are caught, passing -unanticipated exceptions on to the caller and ultimately to the user. -This is preferable over a simpler `catch-all' error handling -mechanism, where a simplistic handler intended to catch a single type -of error like `file not found' can easily mask genuine programming -errors --- especially in a language like Python which relies strongly -on run-time checking and allows the catching of almost any type of -error. - -Other common statement forms, which we have already encountered, are -function definitions, {\tt import} statements and {\tt print} -statements. There is also a {\tt del} statement to delete one or more -variables, a {\tt return} statement to return from a function, and a -{\tt global} statement to allow assignments to global variables. -Finally, the {\tt pass} statement is a no-op. - -\subsection{Execution Model} - -A Python program is executed by a stack-based interpreter. - -When a function is called, a new `execution environment' for it is -pushed onto the stack. An execution environment contains (among other -data) pointers to two `symbol tables' that are used to hold variables: -the local and the global symbol table. The local symbol table -contains local variables of the current function invocation (including -the function arguments); the global symbol table contains variables -defined in the module containing the current function. - -The `global' symbol table is thus only global with respect to the -current function. There are no system-wide global variables; using -the {\tt import} statement it is easy enough to reference variables -that are defined in other modules. A system-wide read-only symbol -table is used for built-in functions and constants though. - -On assignment to a variable, by default an entry for it is made in the -local symbol table of the current execution environment. The {\tt -global} command can override this (it is not enough that a global -variable by the same name already exists). When a variable's value is -needed, it is searched first in the local symbol table, then in the -global one, and finally in the symbol table containing built-in -functions and constants. - -The term `variable' in this context refers to any name: functions and -imported modules are searched in exactly the same way. - -Names defined in a module's symbol table survive until the end of the -program. This approximates the semantics of file-static global -variables in C or module variables in Modula-3. A module is -initialized the first time it is imported, by executing the text of -the module as a parameterless function whose local and global symbol -tables are the same, so names are defined in module's symbol table. -(Modules implemented in C have another way to define symbols.) - -A Python main program is read from standard input or from a script -file passed as an argument to the interpreter. It is executed as if -an anonymous module was imported. Since {\tt import} statements are -executed like all other statements, the initialization order of the -modules used in a program is defined by the flow of control through -the program. - -The `attribute' notation {\em m.name}, where {\em m} is a module, -accesses the symbol {\em name} in that module's symbol table. It can -be assigned to as well. This is in fact a special case of the -construct {\em x.name} where {\em x} denotes an arbitrary object; the -type of {\em x} determines how this is to be interpreted, and what -assignment to it means. - -For instance, when {\tt a} is a list object, {\tt a.append} yields a -built-in `method' object which, when called, appends an item to {\tt a}. -(If {\tt a} and {\tt b} are distinct list objects, {\tt a.append} and -{\tt b.append} are distinguishable method objects.) Normally, in -statements like {\tt a.append(x)}, the method object {\tt a.append} is -called and then discarded, but this is a matter of convention. - -List attributes are read-only --- the user cannot define new list -methods. Some objects, like numbers and strings, have no attributes -at all. Like all type checking in Python, the meaning of an attribute -is determined at run-time --- when the parser sees {\em x.name}, it -has no idea of the type of {\em x}. Note that {\em x} here does not -have to be a variable --- it can be an arbitrary (perhaps -parenthesized) expression. - -Given the flexibility of the attribute notation, one is tempted to use -methods to replace all standard operations. Yet, Python has kept a -small repertoire of built-in functions like {\tt len()} and {\tt -abs()}. The reason is that in some cases the function notation is -more familiar than the method notation; just like programs would -become less readable if all infix operators were replaced by function -calls, they would become less readable if all function calls had to be -replaced by method calls (and vice versa!). - -The choice whether to make something a built-in function or a method -is a matter of taste. For arithmetic and string operations, function -notation is preferred, since frequently the argument to such an -operation is an expression using infix notation, as in {\tt abs(a+b)}; -this definitely looks better than {\tt (a+b).abs()}. The choice -between make something a built-in function or a function defined in a -built-in method (requiring {\tt import}) is similarly guided by -intuition; all in all, only functions needed by `general' programming -techniques are built-in functions. - -\subsection{Classes} - -Python has a class mechanism distinct from the object-orientation -already explained. A class in Python is not much more than a -collection of methods and a way to create class instances. Class -methods are ordinary functions whose first parameter is the class -instance; they are called using the method notation. - -For instance, a class can be defined as follows: -\begin{verbatim} -class Foo: - def meth1(self, arg): ... - def meth2(self): ... -\end{verbatim} -A class instance is created by -{\tt x = Foo()} -and its methods can be called thus: -\begin{verbatim} -x.meth1('Hi There!') -x.meth2() -\end{verbatim} -The functions used as methods are also available as attributes of the -class object, and the above method calls could also have been written -as follows: -\begin{verbatim} -Foo.meth1(x, 'Hi There!') -Foo.meth2(x) -\end{verbatim} -Class methods can store instance data by assigning to instance data -attributes, e.g.: -\begin{verbatim} -self.size = 100 -self.title = 'Dear John' -\end{verbatim} -Data attributes do not have to be declared; as with local variables, -they spring into existence when assigned to. It is a matter of -discretion to avoid name conflicts with method names. This facility -is also available to class users; instances of a method-less class can -be used as records with named fields. - -There is no built-in mechanism for instance initialization. Classes -by convention provide an {\tt init()} method which initializes the -instance and then returns it, so the user can write -\begin{verbatim} -x = Foo().init('Dr. Strangelove') -\end{verbatim} - -Any user-defined class can be used as a base class to derive other -classes. However, built-in types like lists cannot be used as base -classes. (Incidentally, the same is true in C++ and Modula-3.) A -class may override any method of its base classes. Instance methods -are first searched in the method list of their class, and then, -recursively, in the method lists of their base class. Initialization -methods of derived classes should explicitly call the initialization -methods of their base class. - -A simple form of multiple inheritance is also supported: a class can -have multiple base classes, but the language rules for resolving name -conflicts are somewhat simplistic, and consequently the feature has so -far found little usage. - -\subsection{The Python Library} - -Python comes with an extensive library, structured as a collection of -modules. A few modules are built into the interpreter: these -generally provide access to system libraries implemented in C such as -mathematical functions or operating system calls. Two built-in -modules provide access to internals of the interpreter and its -environment. Even abusing these internals will at most cause an -exception in the Python program; the interpreter will not dump core -because of errors in Python code. - -Most modules however are written in Python and distributed with the -interpreter; they provide general programming tools like string -operations and random number generators, provide more convenient -interfaces to some built-in modules, or provide specialized services -like a {\em getopt}-style command line option processor for -stand-alone scripts. - -There are also some modules written in Python that dig deep in the -internals of the interpreter; there is a module to browse the stack -backtrace when an unhandled exception has occurred, one to disassemble -the internal representation of Python code, and even an interactive -source code debugger which can trace Python code, set breakpoints, -etc. - -\subsection{Extensibility} - -It is easy to add new built-in modules written in C to the Python -interpreter. Extensions appear to the Python user as built-in -modules. Using a built-in module is no different from using a module -written in Python, but obviously the author of a built-in module can -do things that cannot be implemented purely in Python. - -In particular, built-in modules can contain Python-callable functions -that call functions from particular system libraries (`wrapper -functions'), and they can define new object types. In general, if a -built-in module defines a new object type, it should also provide at -least one function that creates such objects. Attributes of such -object types are also implemented in C; they can return data -associated with the object or methods, implemented as C functions. - -For instance, an extension was created for Amoeba: it provides wrapper -functions for the basic Amoeba name server functions, and defines a -`capability' object type, whose methods are file server operations. -Another extension is a built-in module called {\tt posix}; it provides -wrappers around post UNIX system calls. Extension modules also -provide access to two different windowing/graphics interfaces: STDWIN -\cite{STDWIN} -(which connects to X11 on UNIX and to the Mac Toolbox on the -Macintosh), and the Graphics Library (GL) for Silicon Graphics -machines. - -Any function in an extension module is supposed to type-check its -arguments; the interpreter contains a convenience function to -facilitate extracting C values from arguments and type-checking them -at the same time. Returning values is also painless, using standard -functions to create Python objects from C values. - -On some systems extension modules may be dynamically loaded, thus -avoiding the need to maintain a private copy of the Python interpreter -in order to use a private extension. - -\section{A Short Description of AIL and Amoeba} - -An RPC stub generator takes an interface description as input. The -designer of a stub generator has at least two choices for the input -language: use a suitably restricted version of the target language, or -design a new language. The first solution was chosen, for instance, -by the designers of Flume, the stub generator for the Topaz -distributed operating system built at DEC SRC -\cite{Flume,Evolving}. - -Flume's one and only target language is Modula-2+ (the predecessor of -Modula-3). Modula-2+, like Modula-N for any N, has an interface -syntax that is well suited as a stub generator input language: an -interface module declares the functions that are `exported' by a -module implementation, with their parameter and return types, plus the -types and constants used for the parameters. Therefore, the input to -Flume is simply a Modula-2+ interface module. But even in this ideal -situation, an RPC stub generator needs to know things about functions -that are not stated explicitly in the interface module: for instance, -the transfer direction of VAR parameters (IN, OUT or both) is not -given. Flume solves this and other problems by a mixture of -directives hidden in comments and a convention for the names of -objects. Thus, one could say that the designers of Flume really -created a new language, even though it looks remarkably like their -target language. - -\subsection{The AIL Input Language} - -Amoeba uses C as its primary programming language. C function -declarations (at least in `Classic' C) don't specify the types of -the parameters, let alone their transfer direction. Using this as -input for a stub generator would require almost all information for -the stub generator to be hidden inside comments, which would require a -rather contorted scanner. Therefore we decided to design the input -syntax for Amoeba's stub generator `from scratch'. This gave us the -liberty to invent proper syntax not only for the transfer direction of -parameters, but also for variable-length arrays. - -On the other hand we decided not to abuse our freedom, and borrowed as -much from C as we could. For instance, AIL runs its input through the -C preprocessor, so we get macros, include files and conditional -compilation for free. AIL's type declaration syntax is a superset of -C's, so the user can include C header files to use the types declared -there as function parameter types --- which are declared using -function prototypes as in C++ or Standard C\@. It should be clear by -now that AIL's lexical conventions are also identical to C's. The -same is true for its expression syntax. - -Where does AIL differ from C, then? Function declarations in AIL are -grouped in {\em classes}. Classes in AIL are mostly intended as a -grouping mechanism: all functions implemented by a server are grouped -together in a class. Inheritance is used to form new groups by adding -elements to existing groups; multiple inheritance is supported to join -groups together. Classes can also contain constant and type -definitions, and one form of output that AIL can generate is a header -file for use by C programmers who wish to use functions from a -particular AIL class. - -Let's have a look at some (unrealistically simple) class definitions: -\begin{verbatim} -#include /* Defines `capability', etc. */ - -class standard_ops [1000 .. 1999] { - /* Operations supported by most interfaces */ - std_info(*, out char buf[size:100], out int size); - std_destroy(*); -}; -\end{verbatim} -This defines a class called `standard\_ops' whose request codes are -chosen by AIL from the range 1000-1999. Request codes are small -integers used to identify remote operations. The author of the class -must specify a range from which AIL chooses, and class authors must -make sure they avoid conflicts, e.g. by using an `assigned number -administration office'. In the example, `std\_info' will be assigned -request code 1000 and `std\_destroy' will get code 1001. There is -also an option to explicitly assign request codes, for compatibility -with servers with manually written interfaces. - -The class `standard\_ops' defines two operations, `std\_info' and -`std\_destroy'. The first parameter of each operation is a star -(`*'); this is a placeholder for a capability that must be passed when -the operation is called. The description of Amoeba below explains the -meaning and usage of capabilities; for now, it is sufficient to know -that a capability is a small structure that uniquely identifies an -object and a server or service. - -The standard operation `std\_info' has two output parameters: a -variable-size character buffer (which will be filled with a short -descriptive string of the object to which the operation is applied) -and an integer giving the length of this string. The standard -operation `std\_destroy' has no further parameters --- it just -destroys the object, if the caller has the right to do so. - -The next class is called `tty': -\begin{verbatim} -class tty [2000 .. 2099] { - inherit standard_ops; - const TTY_MAXBUF = 1000; - tty_write(*, char buf[size:TTY_MAXBUF], int size); - tty_read(*, out char buf[size:TTY_MAXBUF], out int size); -}; -\end{verbatim} -The request codes for operations defined in this class lie in the -range 2000-2099; inherited operations use the request codes already -assigned to them. The operations defined by this class are -`tty\_read' and `tty\_write', which pass variable-sized data buffers -between client and server. Class `tty' inherits class -`standard\_ops', so tty objects also support the operations -`std\_info' and `std\_destroy'. - -Only the {\em interface} for `std\_info' and `std\_destroy' is shared -between tty objects and other objects whose interface inherits -`standard\_ops'; the implementation may differ. Even multiple -implementations of the `tty' interface may exist, e.g. a driver for a -console terminal and a terminal emulator in a window. To expand on -the latter example, consider: -\begin{verbatim} -class window [2100 .. 2199] { - inherit standard_ops; - win_create(*, int x, int y, int width, int height, - out capability win_cap); - win_reconfigure(*, int x, int y, int width, int height); -}; - -class tty_emulator [2200 .. 2299] { - inherit tty, window; -}; -\end{verbatim} -Here two new interface classes are defined. -Class `window' could be used for creating and manipulating windows. -Note that `win\_create' returns a capability for the new window. -This request should probably should be sent to a generic window -server capability, or it might create a subwindow when applied to a -window object. - -Class `tty\_emulator' demonstrates the essence of multiple inheritance. -It is presumably the interface to a window-based terminal emulator. -Inheritance is transitive, so `tty\_emulator' also implicitly inherits -`standard\_ops'. -In fact, it inherits it twice: once via `tty' and once via `window'. -Since AIL class inheritance only means interface sharing, not -implementation sharing, inheriting the same class multiple times is -never a problem and has the same effect as inheriting it once. - -Note that the power of AIL classes doesn't go as far as C++. -AIL classes cannot have data members, and there is -no mechanism for a server that implements a derived class -to inherit the implementation of the base -class --- other than copying the source code. -The syntax for class definitions and inheritance is also different. - -\subsection{Amoeba} - -The smell of `object-orientedness' that the use of classes in AIL -creates matches nicely with Amoeba's object-oriented approach to -RPC\@. In Amoeba, almost all operating system entities (files, -directories, processes, devices etc.) are implemented as {\em -objects}. Objects are managed by {\em services} and represented by -{\em capabilities}. A capability gives its holder access to the -object it represents. Capabilities are protected cryptographically -against forgery and can thus be kept in user space. A capability is a -128-bit binary string, subdivided as follows: - -% XXX Need a better version of this picture! -\begin{verbatim} - 48 24 8 48 Bits -+----------------+------------+--------+---------------+ -| Service | Object | Perm. | Check | -| port | number | bits | word | -+----------------+------------+--------+---------------+ -\end{verbatim} - -The service port is used by the RPC implementation in the Amoeba -kernel to locate a server implementing the service that manages the -object. In many cases there is a one-to-one correspondence between -servers and services (each service is implemented by exactly one -server process), but some services are replicated. For instance, -Amoeba's directory service, which is crucial for gaining access to most -other services, is implemented by two servers that listen on the same -port and know about exactly the same objects. - -The object number in the capability is used by the server receiving -the request for identifying the object to which the operation applies. -The permission bits specify which operations the holder of the capability -may apply. The last part of a capability is a 48-bit long `check -word', which is used to prevent forgery. The check word is computed -by the server based upon the permission bits and a random key per object -that it keeps secret. If you change the permission bits you must compute -the proper check word or else the server will refuse the capability. -Due to the size of the check word and the nature of the cryptographic -`one-way function' used to compute it, inverting this function is -impractical, so forging capabilities is impossible.% -\footnote{ -As computers become faster, inverting the one-way function becomes -less impractical. -Therefore, a next version of Amoeba will have 64-bit check words. -} - -A working Amoeba system is a collection of diverse servers, managing -files, directories, processes, devices etc. While most servers have -their own interface, there are some requests that make sense for some -or all object types. For instance, the {\em std\_info()} request, -which returns a short descriptive string, applies to all object types. -Likewise, {\em std\_destroy()} applies to files, directories and -processes, but not to devices. - -Similarly, different file server implementations may want to offer the -same interface for operations like {\em read()} and {\em write()} to -their clients. AIL's grouping of requests into classes is ideally -suited to describe this kind of interface sharing, and a class -hierarchy results which clearly shows the similarities between server -interfaces (not necessarily their implementations!). - -The base class of all classes defines the {\em std\_info()} request. -Most server interfaces actually inherit a derived class that also -defines {\em std\_destroy().} File servers inherit a class that -defines the common operations on files, etc. - -\subsection{How AIL Works} - -The AIL stub generator functions in three phases: -\begin{itemize} -\item -parsing, -\item -strategy determination, -\item -code generation. -\end{itemize} - -{\bf Phase one} parses the input and builds a symbol table containing -everything it knows about the classes and other definitions found in -the input. - -{\bf Phase two} determines the strategy to use for each function -declaration in turn and decides upon the request and reply message -formats. This is not a simple matter, because of various optimization -attempts. Amoeba's kernel interface for RPC requests takes a -fixed-size header and one arbitrary-size buffer. A large part of the -header holds the capability of the object to which the request is -directed, but there is some space left for a few integer parameters -whose interpretation is left up to the server. AIL tries to use these -slots for simple integer parameters, for two reasons. - -First, unlike the buffer, header fields are byte-swapped by the RPC -layer in the kernel if necessary, so it saves a few byte swapping -instructions in the user code. Second, and more important, a common -form of request transfers a few integers and one large buffer to or -from a server. The {\em read()} and {\em write()} requests of most -file servers have this form, for instance. If it is possible to place -all integer parameters in the header, the address of the buffer -parameter can be passed directly to the kernel RPC layer. While AIL -is perfectly capable of handling requests that do not fit this format, -the resulting code involves allocating a new buffer and copying all -parameters into it. It is a top priority to avoid this copying -(`marshalling') if at all possible, in order to maintain Amoeba's -famous RPC performance. - -When AIL resorts to copying parameters into a buffer, it reorders them -so that integers indicating the lengths of variable-size arrays are -placed in the buffer before the arrays they describe, since otherwise -decoding the request would be impossible. It also adds occasional -padding bytes to ensure integers are aligned properly in the buffer --- -this can speed up (un)marshalling. - -{\bf Phase three} is the code generator, or back-end. There are in -fact many different back-ends that may be called in a single run to -generate different types of output. The most important output types -are header files (for inclusion by the clients of an interface), -client stubs, and `server main loop' code. The latter decodes -incoming requests in the server. The generated code depends on the -programming language requested, and there are separate back-ends for -each supported language. - -It is important that the strategy chosen by phase two is independent -of the language requested for phase three --- otherwise the -interoperability of servers and clients written in different languages -would be compromised. - -\section{Linking AIL to Python} - -From the previous section it can be concluded that linking AIL to -Python is a matter of writing a back-end for Python. This is indeed -what we did. - -Considerable time went into the design of the back-end in order to -make the resulting RPC interface for Python fit as smoothly as -possible in Python's programming style. For instance, the issues of -parameter transfer, variable-size arrays, error handling, and call -syntax were all solved in a manner that favors ease of use in Python -rather than strict correspondence with the stubs generated for C, -without compromising network-level compatibility. - -\subsection{Mapping AIL Entities to Python} - -For each programming language that AIL is to support, a mapping must -be designed between the data types in AIL and those in that language. -Other aspects of the programming languages, such as differences in -function call semantics, must also be taken care of. - -While the mapping for C is mostly straightforward, the mapping for -Python requires a little thinking to get the best results for Python -programmers. - -\subsubsection{Parameter Transfer Direction} - -Perhaps the simplest issue is that of parameter transfer direction. -Parameters of functions declared in AIL are categorized as being of -type {\tt in}, {\tt out} or {\tt in} {\tt out} (the same distinction -as made in Ada). Python only has call-by-value parameter semantics; -functions can return multiple values as a tuple. This means that, -unlike the C back-end, the Python back-end cannot always generate -Python functions with exactly the same parameter list as the AIL -functions. - -Instead, the Python parameter list consists of all {\tt in} and {\tt -in} {\tt out} parameters, in the order in which they occur in the AIL -parameter list; similarly, the Python function returns a tuple -containing all {\tt in} {\tt out} and {\tt out} parameters. In fact -Python packs function parameters into a tuple as well, stressing the -symmetry between parameters and return value. For example, a stub -with this AIL parameter list: -\begin{verbatim} -(*, in int p1, in out int p2, in int p3, out int p4) -\end{verbatim} -will have the following parameter list and return values in Python: -\begin{verbatim} -(p1, p2, p3) -> (p2, p4) -\end{verbatim} - -\subsubsection{Variable-size Entities} - -The support for variable-size objects in AIL is strongly guided by the -limitations of C in this matter. Basically, AIL allows what is -feasible in C: functions may have variable-size arrays as parameters -(both input or output), provided their length is passed separately. -In practice this is narrowed to the following rule: for each -variable-size array parameter, there must be an integer parameter -giving its length. (An exception for null-terminated strings is -planned but not yet realized.) - -Variable-size arrays in AIL or C correspond to {\em sequences} in -Python: lists, tuples or strings. These are much easier to use than -their C counterparts. Given a sequence object in Python, it is always -possible to determine its size: the built-in function {\tt len()} -returns it. It would be annoying to require the caller of an RPC stub -with a variable-size parameter to also pass a parameter that -explicitly gives its size. Therefore we eliminate all parameters from -the Python parameter list whose value is used as the size of a -variable-size array. Such parameters are easily found: the array -bound expression contains the name of the parameter giving its size. -This requires the stub code to work harder (it has to recover the -value for size parameters from the corresponding sequence parameter), -but at least part of this work would otherwise be needed as well, to -check that the given and actual sizes match. - -Because of the symmetry in Python between the parameter list and the -return value of a function, the same elimination is performed on -return values containing variable-size arrays: integers returned -solely to tell the client the size of a returned array are not -returned explicitly to the caller in Python. - -\subsubsection{Error Handling} - -Another point where Python is really better than C is the issue of -error handling. It is a fact of life that everything involving RPC -may fail, for a variety of reasons outside the user's control: the -network may be disconnected, the server may be down, etc. Clients -must be prepared to handle such failures and recover from them, or at -least print an error message and die. In C this means that every -function returns an error status that must be checked by the caller, -causing programs to be cluttered with error checks --- or worse, -programs that ignore errors and carry on working with garbage data. - -In Python, errors are generally indicated by exceptions, which can be -handled out of line from the main flow of control if necessary, and -cause immediate program termination (with a stack trace) if ignored. -To profit from this feature, all RPC errors that may be encountered by -AIL-generated stubs in Python are turned into exceptions. An extra -value passed together with the exception is used to relay the error -code returned by the server to the handler. Since in general RPC -failures are rare, Python test programs can usually ignore exceptions ---- making the program simpler --- without the risk of occasional -errors going undetected. (I still remember the embarrassment a -hundredfold speed improvement reported, long, long, ago, about a new -version of a certain program, which later had to be attributed to a -benchmark that silently dumped core...) - -\subsubsection{Function Call Syntax} - -Amoeba RPC operations always need a capability parameter (this is what -the `*' in the AIL function templates stands for); the service is -identified by the port field of the capability. In C, the capability -must always be the first parameter of the stub function, but in Python -we can do better. - -A Python capability is an opaque object type in its own right, which -is used, for instance, as parameter to and return value from Amoeba's -name server functions. Python objects can have methods, so it is -convenient to make all AIL-generated stubs methods of capabilities -instead of just functions. Therefore, instead of writing -\begin{verbatim} -some_stub(cap, other_parameters) -\end{verbatim} -as in C, Python programmers can write -\begin{verbatim} -cap.some_stub(other_parameters) -\end{verbatim} -This is better because it reduces name conflicts: in Python, no -confusion is possible between a stub and a local or global variable or -user-defined function with the same name. - -\subsubsection{Example} - -All the preceding principles can be seen at work in the following -example. Suppose a function is declared in AIL as follows: -\begin{verbatim} -some_stub(*, in char buf[size:1000], in int size, - out int n_done, out int status); -\end{verbatim} -In C it might be called by the following code (including declarations, -for clarity, but not initializations): -\begin{verbatim} -int err, n_done, status; -capability cap; -char buf[500]; -... -err = some_stub(&cap, buf, sizeof buf, &n_done, &status); -if (err != 0) return err; -printf("%d done; status = %d\n", n_done, status); -\end{verbatim} -Equivalent code in Python might be the following: -\begin{verbatim} -cap = ... -buf = ... -n_done, status = cap.some_stub(buf) -print n_done, 'done;', 'status =', status -\end{verbatim} -No explicit error check is required in Python: if the RPC fails, an -exception is raised so the {\tt print} statement is never reached. - -\subsection{The Implementation} - -More or less orthogonal to the issue of how to map AIL operations to -the Python language is the question of how they should be implemented. - -In principle it would be possible to use the same strategy that is -used for C: add an interface to Amoeba's low-level RPC primitives to -Python and generate Python code to marshal parameters into and out of -a buffer. However, Python's high-level data types are not well suited -for marshalling: byte-level operations are clumsy and expensive, with -the result that marshalling a single byte of data can take several -Python statements. This would mean that a large amount of code would -be needed to implement a stub, which would cost a lot of time to parse -and take up a lot of space in `compiled' form (as parse tree or pseudo -code). Execution of the marshalling code would be sluggish as well. - -We therefore chose an alternate approach, writing the marshalling in -C, which is efficient at such byte-level operations. While it is easy -enough to generate C code that can be linked with the Python -interpreter, it would obviously not stimulate the use of Python for -server testing if each change to an interface required relinking the -interpreter (dynamic loading of C code is not yet available on -Amoeba). This is circumvented by the following solution: the -marshalling is handled by a simple {\em virtual machine}, and AIL -generates instructions for this machine. An interpreter for the -machine is linked into the Python interpreter and reads its -instructions from a file written by AIL. - -The machine language for our virtual machine is dubbed {\em Stubcode}. -Stubcode is a super-specialized language. There are two sets of of -about a dozen instructions each: one set marshals Python objects -representing parameters into a buffer, the other set (similar but not -quite symmetric) unmarshals results from a buffer into Python objects. -The Stubcode interpreter uses a stack to hold Python intermediate -results. Other state elements are an Amoeba header and buffer, a -pointer indicating the current position in the buffer, and of course a -program counter. Besides (un)marshalling, the virtual machine must -also implement type checking, and raise a Python exception when a -parameter does not have the expected type. - -The Stubcode interpreter marshals Python data types very efficiently, -since each instruction can marshal a large amount of data. For -instance, a whole Python string is marshalled by a single Stubcode -instruction, which (after some checking) executes the most efficient -byte-copying loop possible --- it calls {\tt memcpy()}. - - -Construction details of the Stubcode interpreter are straightforward. -Most complications are caused by the peculiarities of AIL's strategy -module and Python's type system. By far the most complex single -instruction is the `loop' instruction, which is used to marshal -arrays. - -As an example, here is the complete Stubcode program (with spaces and -comments added for clarity) generated for the function {\tt -some\_stub()} of the example above. The stack contains pointers to -Python objects, and its initial contents is the parameter to the -function, the string {\tt buf}. The final stack contents will be the -function return value, the tuple {\tt (n\_done, status)}. The name -{\tt header} refers to the fixed size Amoeba RPC header structure. -\vspace{1em} - -{\tt -\begin{tabular}{l l l} -BufSize & 1000 & {\em Allocate RPC buffer of 1000 bytes} \\ -Dup & 1 & {\em Duplicate stack top} \\ -StringS & & {\em Replace stack top by its string size} \\ -PutI & h\_extra int32 & {\em Store top element in }header.h\_extra \\ -TStringSlt & 1000 & {\em Assert string size less than 1000} \\ -PutVS & & {\em Marshal variable-size string} \\ - & & \\ -Trans & 1234 & {\em Execute the RPC (request code 1234)} \\ - & & \\ -GetI & h\_extra int32 & {\em Push integer from} header.h\_extra \\ -GetI & h\_size int32 & {\em Push integer from} header.h\_size \\ -Pack & 2 & {\em Pack top 2 elements into a tuple} \\ -\end{tabular} -} -\vspace{1em} - -As much work as possible is done by the Python back-end in AIL, rather -than in the Stubcode interpreter, to make the latter both simple and -fast. For instance, the decision to eliminate an array size parameter -from the Python parameter list is taken by AIL, and Stubcode -instructions are generated to recover the size from the actual -parameter and to marshal it properly. Similarly, there is a special -alignment instruction (not used in the example) to meet alignment -requirements. - -Communication between AIL and the Stubcode generator is via the file -system. For each stub function, AIL creates a file in its output -directory, named after the stub with a specific suffix. This file -contains a machine-readable version of the Stubcode program for the -stub. The Python user can specify a search path containing -directories which the interpreter searches for a Stubcode file the -first time the definition for a particular stub is needed. - -The transformations on the parameter list and data types needed to map -AIL data types to Python data types make it necessary to help the -Python programmer a bit in figuring out the parameters to a call. -Although in most cases the rules are simple enough, it is sometimes -hard to figure out exactly what the parameter and return values of a -particular stub are. There are two sources of help in this case: -first, the exception contains enough information so that the user can -figure what type was expected; second, AIL's Python back-end -optionally generates a human-readable `interface specification' file. - -\section{Conclusion} - -We have succeeded in creating a useful extension to Python that -enables Amoeba server writers to test and experiment with their server -in a much more interactive manner. We hope that this facility will -add to the popularity of AIL amongst Amoeba programmers. - -Python's extensibility was proven convincingly by the exercise -(performed by the second author) of adding the Stubcode interpreter to -Python. Standard data abstraction techniques are used to insulate -extension modules from details of the rest of the Python interpreter. -In the case of the Stubcode interpreter this worked well enough that -it survived a major overhaul of the main Python interpreter virtually -unchanged. - -On the other hand, adding a new back-end to AIL turned out to be quite -a bit of work. One problem, specific to Python, was to be expected: -Python's variable-size data types differ considerably from the -C-derived data model that AIL favors. Two additional problems we -encountered were the complexity of the interface between AIL's second -and third phases, and a number of remaining bugs in the second phase -that surfaced when the implementation of the Python back-end was -tested. The bugs have been tracked down and fixed, but nothing -has been done about the complexity of the interface. - -\subsection{Future Plans} - -AIL's C back-end generates server main loop code as well as client -stubs. The Python back-end currently only generates client stubs, so -it is not yet possible to write servers in Python. While it is -clearly more important to be able to use Python as a client than as a -server, the ability to write server prototypes in Python would be a -valuable addition: it allows server designers to experiment with -interfaces in a much earlier stage of the design, with a much smaller -programming effort. This makes it possible to concentrate on concepts -first, before worrying about efficient implementation. - -The unmarshalling done in the server is almost symmetric with the -marshalling in the client, and vice versa, so relative small -extensions to the Stubcode virtual machine will allow its use in a -server main loop. We hope to find the time to add this feature to a -future version of Python. - -\section{Availability} - -The Python source distribution is available to Internet users by -anonymous ftp to site {\tt ftp.cwi.nl} [IP address 192.16.184.180] -from directory {\tt /pub}, file name {\tt python*.tar.Z} (where the -{\tt *} stands for a version number). This is a compressed UNIX tar -file containing the C source and \LaTeX documentation for the Python -interpreter. It includes the Python library modules and the {\em -Stubcode} interpreter, as well as many example Python programs. Total -disk space occupied by the distribution is about 3 Mb; compilation -requires 1-3 Mb depending on the configuration built, the compile -options, etc. - -\bibliographystyle{plain} - -\bibliography{quabib} - -\end{document} diff --git a/Doc/quabib.bib b/Doc/quabib.bib deleted file mode 100644 index 97b93f6d55..0000000000 --- a/Doc/quabib.bib +++ /dev/null @@ -1,139 +0,0 @@ -@inproceedings{bult:usenix91, - title = "A Structure for Transportable, Dynamic Multimedia Documents", - author = "Dick C.A. Bulterman - and Guido van Rossum - and Robert van Liere", - booktitle = "Proceedings of the 1991 Summer USENIX Conference", - publisher = "The USENIX Association", - year = "1991", -} - -@techreport{bult:gogh90, - title = "The {CWI} van {G}ogh Multimedia Research Project: Goals - and Objectives", - author = "Dick C.A. Bulterman", - institution = "CWI", - year = "1990", - number = "CST-90.1004", -} - -@article{Amoeba:IEEE, - title = "{A}moeba: A Distributed Operating System for the 1990s", - author = "S.J. Mullender - and G. van Rossum - and A.S. Tanenbaum - and R. van Renesse - and J.M. van Staveren", - journal = "IEEE Computer Magazine", - volume = "23", - number = "5", - month = "May", - year = "1990", - pages = "44-53", -} - -@article{Amoeba:CACM, - title = "Experiences with the {A}moeba Distributed Operating System", - author = "A.S. Tanenbaum -and R. van Renesse -and J.M. van Staveren -and G.J. Sharp -and S.J. Mullender -and A.J. Jansen -and G. van Rossum", -journal = "Communications of the ACM", -volume = "33", -number = "12", -month = "December", -year ="1990", -pages = "46-63", -} - -@inproceedings{AIL, -title = "{AIL} --- A Class-Oriented Stub Generator for {A}moeba", -author = "G. van Rossum", -editor = {E W. Schr\"{o}der-Preikschat -and E. W. Zimmer}, -booktitle = "Workshop on Progress in Distributed Operating Systems and Distributed Systems Management", -publisher = "Springer Verlag", -series = "Lecture Notes in Computer Science", -volume = "433", -year = "1990", -pages = "13-21", -} - -@techreport{STDWIN, -title = "{STDWIN} --- A Standard Window System Interface", -author = "G. van Rossum", -number = "CS-R8817", -institution = "CWI", -address = "Amsterdam", -month = "April", -year = "1988", -} - -@book{ABC, -title = "{ABC} Programmer's Handbook", -author = "Leo Geurts -and Lambert Meertens -and Steven Pemberton", -publisher = "Prentice-Hall", -address = "London", -year = "1990", -note = "ISBN 0-13-000027-2", -} - -@manual{Flume, -title = "{F}lume --- Remote Procedure Call Stub Generator for {M}odula-2+", -author = "A.D. Birrell -and E.D. Lazowska -and E. Wobber", -organization = "DEC SRC", -address = "Palo Alto, CA", -year = "1987", -note = "(Topaz manual page)", -} - -@techreport{Evolving, -title = "Evolving the {UNIX} System Interface to Support Multithreaded Programs", -author = "P.R. McJones -and G.F. Swart", -number = "21", -institution = "DEC SRC", -address = "Palo Alto, CA", -month = "September", -year = "1987", -} - -@inproceedings{Tcl, -title = "{T}cl: an Embeddable Command Language", -author = "John K. Ousterhout", -booktitle = "Proceedings of the Winter 1990 USENIX Conference", -publisher = "USENIX Association", -address = "Washington, DC", -month = "January", -year = "1990", -pages = "133-146", -} - -@article{RPC, -title = "Implementing Remote Procedure Calls", -author = "A. D. Birrell -and B. J. Nelson", -journal = "ACM Transactions on Computer Systems", -volume = "2", -number = "1", -month = "February", -year = "1984", -pages = "39-59", -} - -@techreport{Modula-3, -title = "{M}odula-3 Report (revised)", -author = "Luca Cardelli et al.", -number = "52", -institution = "DEC SRC", -address = "Palo Alto, CA", -month = "November", -year = "1989", -} diff --git a/Doc/ref.tex b/Doc/ref.tex deleted file mode 100644 index f0cb559f19..0000000000 --- a/Doc/ref.tex +++ /dev/null @@ -1,73 +0,0 @@ -\documentstyle[twoside,11pt,myformat]{report} - -\title{\bf Python Reference Manual} - -\author{ - Guido van Rossum \\ - Dept. CST, CWI, P.O. Box 94079 \\ - 1090 GB Amsterdam, The Netherlands \\ - E-mail: {\tt guido@cwi.nl} -} - -\date{19 November 1993 \\ Release 0.9.9.++} % XXX update before release! - -% Tell \index to actually write the .idx file -\makeindex - -\begin{document} - -\pagenumbering{roman} - -\maketitle - -\begin{abstract} - -\noindent -Python is a simple, yet powerful, interpreted programming language -that bridges the gap between C and shell programming, and is thus -ideally suited for ``throw-away programming'' and rapid prototyping. -Its syntax is put together from constructs borrowed from a variety of -other languages; most prominent are influences from ABC, C, Modula-3 -and Icon. - -The Python interpreter is easily extended with new functions and data -types implemented in C. Python is also suitable as an extension -language for highly customizable C applications such as editors or -window managers. - -Python is available for various operating systems, amongst which -several flavors of {\UNIX}, Amoeba, the Apple Macintosh O.S., -and MS-DOS. - -This reference manual describes the syntax and ``core semantics'' of -the language. It is terse, but attempts to be exact and complete. -The semantics of non-essential built-in object types and of the -built-in functions and modules are described in the {\em Python -Library Reference}. For an informal introduction to the language, see -the {\em Python Tutorial}. - -\end{abstract} - -\pagebreak - -{ -\parskip = 0mm -\tableofcontents -} - -\pagebreak - -\pagenumbering{arabic} - -\include{ref1} % Introduction -\include{ref2} % Lexical analysis -\include{ref3} % Data model -\include{ref4} % Execution model -\include{ref5} % Expressions and conditions -\include{ref6} % Simple statements -\include{ref7} % Compound statements -\include{ref8} % Top-level components - -\input{ref.ind} - -\end{document} diff --git a/Doc/ref/ref.tex b/Doc/ref/ref.tex deleted file mode 100644 index f0cb559f19..0000000000 --- a/Doc/ref/ref.tex +++ /dev/null @@ -1,73 +0,0 @@ -\documentstyle[twoside,11pt,myformat]{report} - -\title{\bf Python Reference Manual} - -\author{ - Guido van Rossum \\ - Dept. CST, CWI, P.O. Box 94079 \\ - 1090 GB Amsterdam, The Netherlands \\ - E-mail: {\tt guido@cwi.nl} -} - -\date{19 November 1993 \\ Release 0.9.9.++} % XXX update before release! - -% Tell \index to actually write the .idx file -\makeindex - -\begin{document} - -\pagenumbering{roman} - -\maketitle - -\begin{abstract} - -\noindent -Python is a simple, yet powerful, interpreted programming language -that bridges the gap between C and shell programming, and is thus -ideally suited for ``throw-away programming'' and rapid prototyping. -Its syntax is put together from constructs borrowed from a variety of -other languages; most prominent are influences from ABC, C, Modula-3 -and Icon. - -The Python interpreter is easily extended with new functions and data -types implemented in C. Python is also suitable as an extension -language for highly customizable C applications such as editors or -window managers. - -Python is available for various operating systems, amongst which -several flavors of {\UNIX}, Amoeba, the Apple Macintosh O.S., -and MS-DOS. - -This reference manual describes the syntax and ``core semantics'' of -the language. It is terse, but attempts to be exact and complete. -The semantics of non-essential built-in object types and of the -built-in functions and modules are described in the {\em Python -Library Reference}. For an informal introduction to the language, see -the {\em Python Tutorial}. - -\end{abstract} - -\pagebreak - -{ -\parskip = 0mm -\tableofcontents -} - -\pagebreak - -\pagenumbering{arabic} - -\include{ref1} % Introduction -\include{ref2} % Lexical analysis -\include{ref3} % Data model -\include{ref4} % Execution model -\include{ref5} % Expressions and conditions -\include{ref6} % Simple statements -\include{ref7} % Compound statements -\include{ref8} % Top-level components - -\input{ref.ind} - -\end{document} diff --git a/Doc/ref/ref1.tex b/Doc/ref/ref1.tex deleted file mode 100644 index b373e3666c..0000000000 --- a/Doc/ref/ref1.tex +++ /dev/null @@ -1,81 +0,0 @@ -\chapter{Introduction} - -This reference manual describes the Python programming language. -It is not intended as a tutorial. - -While I am trying to be as precise as possible, I chose to use English -rather than formal specifications for everything except syntax and -lexical analysis. This should make the document better understandable -to the average reader, but will leave room for ambiguities. -Consequently, if you were coming from Mars and tried to re-implement -Python from this document alone, you might have to guess things and in -fact you would probably end up implementing quite a different language. -On the other hand, if you are using -Python and wonder what the precise rules about a particular area of -the language are, you should definitely be able to find them here. - -It is dangerous to add too many implementation details to a language -reference document --- the implementation may change, and other -implementations of the same language may work differently. On the -other hand, there is currently only one Python implementation, and -its particular quirks are sometimes worth being mentioned, especially -where the implementation imposes additional limitations. Therefore, -you'll find short ``implementation notes'' sprinkled throughout the -text. - -Every Python implementation comes with a number of built-in and -standard modules. These are not documented here, but in the separate -{\em Python Library Reference} document. A few built-in modules are -mentioned when they interact in a significant way with the language -definition. - -\section{Notation} - -The descriptions of lexical analysis and syntax use a modified BNF -grammar notation. This uses the following style of definition: -\index{BNF} -\index{grammar} -\index{syntax} -\index{notation} - -\begin{verbatim} -name: lc_letter (lc_letter | "_")* -lc_letter: "a"..."z" -\end{verbatim} - -The first line says that a \verb\name\ is an \verb\lc_letter\ followed by -a sequence of zero or more \verb\lc_letter\s and underscores. An -\verb\lc_letter\ in turn is any of the single characters `a' through `z'. -(This rule is actually adhered to for the names defined in lexical and -grammar rules in this document.) - -Each rule begins with a name (which is the name defined by the rule) -and a colon. A vertical bar (\verb\|\) is used to separate -alternatives; it is the least binding operator in this notation. A -star (\verb\*\) means zero or more repetitions of the preceding item; -likewise, a plus (\verb\+\) means one or more repetitions, and a -phrase enclosed in square brackets (\verb\[ ]\) means zero or one -occurrences (in other words, the enclosed phrase is optional). The -\verb\*\ and \verb\+\ operators bind as tightly as possible; -parentheses are used for grouping. Literal strings are enclosed in -double quotes. White space is only meaningful to separate tokens. -Rules are normally contained on a single line; rules with many -alternatives may be formatted alternatively with each line after the -first beginning with a vertical bar. - -In lexical definitions (as the example above), two more conventions -are used: Two literal characters separated by three dots mean a choice -of any single character in the given (inclusive) range of ASCII -characters. A phrase between angular brackets (\verb\<...>\) gives an -informal description of the symbol defined; e.g. this could be used -to describe the notion of `control character' if needed. -\index{lexical definitions} -\index{ASCII} - -Even though the notation used is almost the same, there is a big -difference between the meaning of lexical and syntactic definitions: -a lexical definition operates on the individual characters of the -input source, while a syntax definition operates on the stream of -tokens generated by the lexical analysis. All uses of BNF in the next -chapter (``Lexical Analysis'') are lexical definitions; uses in -subsequent chapters are syntactic definitions. diff --git a/Doc/ref/ref2.tex b/Doc/ref/ref2.tex deleted file mode 100644 index 250bd2e771..0000000000 --- a/Doc/ref/ref2.tex +++ /dev/null @@ -1,349 +0,0 @@ -\chapter{Lexical analysis} - -A Python program is read by a {\em parser}. Input to the parser is a -stream of {\em tokens}, generated by the {\em lexical analyzer}. This -chapter describes how the lexical analyzer breaks a file into tokens. -\index{lexical analysis} -\index{parser} -\index{token} - -\section{Line structure} - -A Python program is divided in a number of logical lines. The end of -a logical line is represented by the token NEWLINE. Statements cannot -cross logical line boundaries except where NEWLINE is allowed by the -syntax (e.g. between statements in compound statements). -\index{line structure} -\index{logical line} -\index{NEWLINE token} - -\subsection{Comments} - -A comment starts with a hash character (\verb\#\) that is not part of -a string literal, and ends at the end of the physical line. A comment -always signifies the end of the logical line. Comments are ignored by -the syntax. -\index{comment} -\index{logical line} -\index{physical line} -\index{hash character} - -\subsection{Line joining} - -Two or more physical lines may be joined into logical lines using -backslash characters (\verb/\/), as follows: when a physical line ends -in a backslash that is not part of a string literal or comment, it is -joined with the following forming a single logical line, deleting the -backslash and the following end-of-line character. For example: -\index{physical line} -\index{line joining} -\index{backslash character} -% -\begin{verbatim} -month_names = ['Januari', 'Februari', 'Maart', \ - 'April', 'Mei', 'Juni', \ - 'Juli', 'Augustus', 'September', \ - 'Oktober', 'November', 'December'] -\end{verbatim} - -\subsection{Blank lines} - -A logical line that contains only spaces, tabs, and possibly a -comment, is ignored (i.e., no NEWLINE token is generated), except that -during interactive input of statements, an entirely blank logical line -terminates a multi-line statement. -\index{blank line} - -\subsection{Indentation} - -Leading whitespace (spaces and tabs) at the beginning of a logical -line is used to compute the indentation level of the line, which in -turn is used to determine the grouping of statements. -\index{indentation} -\index{whitespace} -\index{leading whitespace} -\index{space} -\index{tab} -\index{grouping} -\index{statement grouping} - -First, tabs are replaced (from left to right) by one to eight spaces -such that the total number of characters up to there is a multiple of -eight (this is intended to be the same rule as used by {\UNIX}). The -total number of spaces preceding the first non-blank character then -determines the line's indentation. Indentation cannot be split over -multiple physical lines using backslashes. - -The indentation levels of consecutive lines are used to generate -INDENT and DEDENT tokens, using a stack, as follows. -\index{INDENT token} -\index{DEDENT token} - -Before the first line of the file is read, a single zero is pushed on -the stack; this will never be popped off again. The numbers pushed on -the stack will always be strictly increasing from bottom to top. At -the beginning of each logical line, the line's indentation level is -compared to the top of the stack. If it is equal, nothing happens. -If it is larger, it is pushed on the stack, and one INDENT token is -generated. If it is smaller, it {\em must} be one of the numbers -occurring on the stack; all numbers on the stack that are larger are -popped off, and for each number popped off a DEDENT token is -generated. At the end of the file, a DEDENT token is generated for -each number remaining on the stack that is larger than zero. - -Here is an example of a correctly (though confusingly) indented piece -of Python code: - -\begin{verbatim} -def perm(l): - # Compute the list of all permutations of l - - if len(l) <= 1: - return [l] - r = [] - for i in range(len(l)): - s = l[:i] + l[i+1:] - p = perm(s) - for x in p: - r.append(l[i:i+1] + x) - return r -\end{verbatim} - -The following example shows various indentation errors: - -\begin{verbatim} - def perm(l): # error: first line indented - for i in range(len(l)): # error: not indented - s = l[:i] + l[i+1:] - p = perm(l[:i] + l[i+1:]) # error: unexpected indent - for x in p: - r.append(l[i:i+1] + x) - return r # error: inconsistent dedent -\end{verbatim} - -(Actually, the first three errors are detected by the parser; only the -last error is found by the lexical analyzer --- the indentation of -\verb\return r\ does not match a level popped off the stack.) - -\section{Other tokens} - -Besides NEWLINE, INDENT and DEDENT, the following categories of tokens -exist: identifiers, keywords, literals, operators, and delimiters. -Spaces and tabs are not tokens, but serve to delimit tokens. Where -ambiguity exists, a token comprises the longest possible string that -forms a legal token, when read from left to right. - -\section{Identifiers} - -Identifiers (also referred to as names) are described by the following -lexical definitions: -\index{identifier} -\index{name} - -\begin{verbatim} -identifier: (letter|"_") (letter|digit|"_")* -letter: lowercase | uppercase -lowercase: "a"..."z" -uppercase: "A"..."Z" -digit: "0"..."9" -\end{verbatim} - -Identifiers are unlimited in length. Case is significant. - -\subsection{Keywords} - -The following identifiers are used as reserved words, or {\em -keywords} of the language, and cannot be used as ordinary -identifiers. They must be spelled exactly as written here: -\index{keyword} -\index{reserved word} - -\begin{verbatim} -and del for in print -break elif from is raise -class else global not return -continue except if or try -def finally import pass while -\end{verbatim} - -% # This Python program sorts and formats the above table -% import string -% l = [] -% try: -% while 1: -% l = l + string.split(raw_input()) -% except EOFError: -% pass -% l.sort() -% for i in range((len(l)+4)/5): -% for j in range(i, len(l), 5): -% print string.ljust(l[j], 10), -% print - -\section{Literals} \label{literals} - -Literals are notations for constant values of some built-in types. -\index{literal} -\index{constant} - -\subsection{String literals} - -String literals are described by the following lexical definitions: -\index{string literal} - -\begin{verbatim} -stringliteral: "'" stringitem* "'" -stringitem: stringchar | escapeseq -stringchar: -escapeseq: "'" -\end{verbatim} -\index{ASCII} - -String literals cannot span physical line boundaries. Escape -sequences in strings are actually interpreted according to rules -similar to those used by Standard C. The recognized escape sequences -are: -\index{physical line} -\index{escape sequence} -\index{Standard C} -\index{C} - -\begin{center} -\begin{tabular}{|l|l|} -\hline -\verb/\\/ & Backslash (\verb/\/) \\ -\verb/\'/ & Single quote (\verb/'/) \\ -\verb/\a/ & ASCII Bell (BEL) \\ -\verb/\b/ & ASCII Backspace (BS) \\ -%\verb/\E/ & ASCII Escape (ESC) \\ -\verb/\f/ & ASCII Formfeed (FF) \\ -\verb/\n/ & ASCII Linefeed (LF) \\ -\verb/\r/ & ASCII Carriage Return (CR) \\ -\verb/\t/ & ASCII Horizontal Tab (TAB) \\ -\verb/\v/ & ASCII Vertical Tab (VT) \\ -\verb/\/{\em ooo} & ASCII character with octal value {\em ooo} \\ -\verb/\x/{\em xx...} & ASCII character with hex value {\em xx...} \\ -\hline -\end{tabular} -\end{center} -\index{ASCII} - -In strict compatibility with Standard C, up to three octal digits are -accepted, but an unlimited number of hex digits is taken to be part of -the hex escape (and then the lower 8 bits of the resulting hex number -are used in all current implementations...). - -All unrecognized escape sequences are left in the string unchanged, -i.e., {\em the backslash is left in the string.} (This behavior is -useful when debugging: if an escape sequence is mistyped, the -resulting output is more easily recognized as broken. It also helps a -great deal for string literals used as regular expressions or -otherwise passed to other modules that do their own escape handling.) -\index{unrecognized escape sequence} - -\subsection{Numeric literals} - -There are three types of numeric literals: plain integers, long -integers, and floating point numbers. -\index{number} -\index{numeric literal} -\index{integer literal} -\index{plain integer literal} -\index{long integer literal} -\index{floating point literal} -\index{hexadecimal literal} -\index{octal literal} -\index{decimal literal} - -Integer and long integer literals are described by the following -lexical definitions: - -\begin{verbatim} -longinteger: integer ("l"|"L") -integer: decimalinteger | octinteger | hexinteger -decimalinteger: nonzerodigit digit* | "0" -octinteger: "0" octdigit+ -hexinteger: "0" ("x"|"X") hexdigit+ - -nonzerodigit: "1"..."9" -octdigit: "0"..."7" -hexdigit: digit|"a"..."f"|"A"..."F" -\end{verbatim} - -Although both lower case `l' and upper case `L' are allowed as suffix -for long integers, it is strongly recommended to always use `L', since -the letter `l' looks too much like the digit `1'. - -Plain integer decimal literals must be at most $2^{31} - 1$ (i.e., the -largest positive integer, assuming 32-bit arithmetic). Plain octal and -hexadecimal literals may be as large as $2^{32} - 1$, but values -larger than $2^{31} - 1$ are converted to a negative value by -subtracting $2^{32}$. There is no limit for long integer literals. - -Some examples of plain and long integer literals: - -\begin{verbatim} -7 2147483647 0177 0x80000000 -3L 79228162514264337593543950336L 0377L 0x100000000L -\end{verbatim} - -Floating point literals are described by the following lexical -definitions: - -\begin{verbatim} -floatnumber: pointfloat | exponentfloat -pointfloat: [intpart] fraction | intpart "." -exponentfloat: (intpart | pointfloat) exponent -intpart: digit+ -fraction: "." digit+ -exponent: ("e"|"E") ["+"|"-"] digit+ -\end{verbatim} - -The allowed range of floating point literals is -implementation-dependent. - -Some examples of floating point literals: - -\begin{verbatim} -3.14 10. .001 1e100 3.14e-10 -\end{verbatim} - -Note that numeric literals do not include a sign; a phrase like -\verb\-1\ is actually an expression composed of the operator -\verb\-\ and the literal \verb\1\. - -\section{Operators} - -The following tokens are operators: -\index{operators} - -\begin{verbatim} -+ - * / % -<< >> & | ^ ~ -< == > <= <> != >= -\end{verbatim} - -The comparison operators \verb\<>\ and \verb\!=\ are alternate -spellings of the same operator. - -\section{Delimiters} - -The following tokens serve as delimiters or otherwise have a special -meaning: -\index{delimiters} - -\begin{verbatim} -( ) [ ] { } -; , : . ` = -\end{verbatim} - -The following printing ASCII characters are not used in Python. Their -occurrence outside string literals and comments is an unconditional -error: -\index{ASCII} - -\begin{verbatim} -@ $ " ? -\end{verbatim} - -They may be used by future versions of the language though! diff --git a/Doc/ref/ref3.tex b/Doc/ref/ref3.tex deleted file mode 100644 index 41ce23426e..0000000000 --- a/Doc/ref/ref3.tex +++ /dev/null @@ -1,760 +0,0 @@ -\chapter{Data model} - -\section{Objects, values and types} - -{\em Objects} are Python's abstraction for data. All data in a Python -program is represented by objects or by relations between objects. -(In a sense, and in conformance to Von Neumann's model of a -``stored program computer'', code is also represented by objects.) -\index{object} -\index{data} - -Every object has an identity, a type and a value. An object's {\em -identity} never changes once it has been created; you may think of it -as the object's address in memory. An object's {\em type} is also -unchangeable. It determines the operations that an object supports -(e.g. ``does it have a length?'') and also defines the possible -values for objects of that type. The {\em value} of some objects can -change. Objects whose value can change are said to be {\em mutable}; -objects whose value is unchangeable once they are created are called -{\em immutable}. The type determines an object's (im)mutability. -\index{identity of an object} -\index{value of an object} -\index{type of an object} -\index{mutable object} -\index{immutable object} - -Objects are never explicitly destroyed; however, when they become -unreachable they may be garbage-collected. An implementation is -allowed to delay garbage collection or omit it altogether --- it is a -matter of implementation quality how garbage collection is -implemented, as long as no objects are collected that are still -reachable. (Implementation note: the current implementation uses a -reference-counting scheme which collects most objects as soon as they -become unreachable, but never collects garbage containing circular -references.) -\index{garbage collection} -\index{reference counting} -\index{unreachable object} - -Note that the use of the implementation's tracing or debugging -facilities may keep objects alive that would normally be collectable. - -Some objects contain references to ``external'' resources such as open -files or windows. It is understood that these resources are freed -when the object is garbage-collected, but since garbage collection is -not guaranteed to happen, such objects also provide an explicit way to -release the external resource, usually a \verb\close\ method. -Programs are strongly recommended to always explicitly close such -objects. - -Some objects contain references to other objects; these are called -{\em containers}. Examples of containers are tuples, lists and -dictionaries. The references are part of a container's value. In -most cases, when we talk about the value of a container, we imply the -values, not the identities of the contained objects; however, when we -talk about the (im)mutability of a container, only the identities of -the immediately contained objects are implied. (So, if an immutable -container contains a reference to a mutable object, its value changes -if that mutable object is changed.) -\index{container} - -Types affect almost all aspects of objects' lives. Even the meaning -of object identity is affected in some sense: for immutable types, -operations that compute new values may actually return a reference to -any existing object with the same type and value, while for mutable -objects this is not allowed. E.g. after - -\begin{verbatim} -a = 1; b = 1; c = []; d = [] -\end{verbatim} - -\verb\a\ and \verb\b\ may or may not refer to the same object with the -value one, depending on the implementation, but \verb\c\ and \verb\d\ -are guaranteed to refer to two different, unique, newly created empty -lists. - -\section{The standard type hierarchy} \label{types} - -Below is a list of the types that are built into Python. Extension -modules written in C can define additional types. Future versions of -Python may add types to the type hierarchy (e.g. rational or complex -numbers, efficiently stored arrays of integers, etc.). -\index{type} -\indexii{data}{type} -\indexii{type}{hierarchy} -\indexii{extension}{module} -\index{C} - -Some of the type descriptions below contain a paragraph listing -`special attributes'. These are attributes that provide access to the -implementation and are not intended for general use. Their definition -may change in the future. There are also some `generic' special -attributes, not listed with the individual objects: \verb\__methods__\ -is a list of the method names of a built-in object, if it has any; -\verb\__members__\ is a list of the data attribute names of a built-in -object, if it has any. -\index{attribute} -\indexii{special}{attribute} -\indexiii{generic}{special}{attribute} -\ttindex{__methods__} -\ttindex{__members__} - -\begin{description} - -\item[None] -This type has a single value. There is a single object with this value. -This object is accessed through the built-in name \verb\None\. -It is returned from functions that don't explicitly return an object. -\ttindex{None} -\obindex{None@{\tt None}} - -\item[Numbers] -These are created by numeric literals and returned as results by -arithmetic operators and arithmetic built-in functions. Numeric -objects are immutable; once created their value never changes. Python -numbers are of course strongly related to mathematical numbers, but -subject to the limitations of numerical representation in computers. -\obindex{number} -\obindex{numeric} - -Python distinguishes between integers and floating point numbers: - -\begin{description} -\item[Integers] -These represent elements from the mathematical set of whole numbers. -\obindex{integer} - -There are two types of integers: - -\begin{description} - -\item[Plain integers] -These represent numbers in the range $-2^{31}$ through $2^{31}-1$. -(The range may be larger on machines with a larger natural word -size, but not smaller.) -When the result of an operation falls outside this range, the -exception \verb\OverflowError\ is raised. -For the purpose of shift and mask operations, integers are assumed to -have a binary, 2's complement notation using 32 or more bits, and -hiding no bits from the user (i.e., all $2^{32}$ different bit -patterns correspond to different values). -\obindex{plain integer} - -\item[Long integers] -These represent numbers in an unlimited range, subject to available -(virtual) memory only. For the purpose of shift and mask operations, -a binary representation is assumed, and negative numbers are -represented in a variant of 2's complement which gives the illusion of -an infinite string of sign bits extending to the left. -\obindex{long integer} - -\end{description} % Integers - -The rules for integer representation are intended to give the most -meaningful interpretation of shift and mask operations involving -negative integers and the least surprises when switching between the -plain and long integer domains. For any operation except left shift, -if it yields a result in the plain integer domain without causing -overflow, it will yield the same result in the long integer domain or -when using mixed operands. -\indexii{integer}{representation} - -\item[Floating point numbers] -These represent machine-level double precision floating point numbers. -You are at the mercy of the underlying machine architecture and -C implementation for the accepted range and handling of overflow. -\obindex{floating point} -\indexii{floating point}{number} -\index{C} - -\end{description} % Numbers - -\item[Sequences] -These represent finite ordered sets indexed by natural numbers. -The built-in function \verb\len()\ returns the number of elements -of a sequence. When this number is $n$, the index set contains -the numbers $0, 1, \ldots, n-1$. Element \verb\i\ of sequence -\verb\a\ is selected by \verb\a[i]\. -\obindex{seqence} -\bifuncindex{len} -\index{index operation} -\index{item selection} -\index{subscription} - -Sequences also support slicing: \verb\a[i:j]\ selects all elements -with index $k$ such that $i <= k < j$. When used as an expression, -a slice is a sequence of the same type --- this implies that the -index set is renumbered so that it starts at 0 again. -\index{slicing} - -Sequences are distinguished according to their mutability: - -\begin{description} -% -\item[Immutable sequences] -An object of an immutable sequence type cannot change once it is -created. (If the object contains references to other objects, -these other objects may be mutable and may be changed; however -the collection of objects directly referenced by an immutable object -cannot change.) -\obindex{immutable sequence} -\obindex{immutable} - -The following types are immutable sequences: - -\begin{description} - -\item[Strings] -The elements of a string are characters. There is no separate -character type; a character is represented by a string of one element. -Characters represent (at least) 8-bit bytes. The built-in -functions \verb\chr()\ and \verb\ord()\ convert between characters -and nonnegative integers representing the byte values. -Bytes with the values 0-127 represent the corresponding ASCII values. -The string data type is also used to represent arrays of bytes, e.g. -to hold data read from a file. -\obindex{string} -\index{character} -\index{byte} -\index{ASCII} -\bifuncindex{chr} -\bifuncindex{ord} - -(On systems whose native character set is not ASCII, strings may use -EBCDIC in their internal representation, provided the functions -\verb\chr()\ and \verb\ord()\ implement a mapping between ASCII and -EBCDIC, and string comparison preserves the ASCII order. -Or perhaps someone can propose a better rule?) -\index{ASCII} -\index{EBCDIC} -\index{character set} -\indexii{string}{comparison} -\bifuncindex{chr} -\bifuncindex{ord} - -\item[Tuples] -The elements of a tuple are arbitrary Python objects. -Tuples of two or more elements are formed by comma-separated lists -of expressions. A tuple of one element (a `singleton') can be formed -by affixing a comma to an expression (an expression by itself does -not create a tuple, since parentheses must be usable for grouping of -expressions). An empty tuple can be formed by enclosing `nothing' in -parentheses. -\obindex{tuple} -\indexii{singleton}{tuple} -\indexii{empty}{tuple} - -\end{description} % Immutable sequences - -\item[Mutable sequences] -Mutable sequences can be changed after they are created. The -subscription and slicing notations can be used as the target of -assignment and \verb\del\ (delete) statements. -\obindex{mutable sequece} -\obindex{mutable} -\indexii{assignment}{statement} -\index{delete} -\stindex{del} -\index{subscription} -\index{slicing} - -There is currently a single mutable sequence type: - -\begin{description} - -\item[Lists] -The elements of a list are arbitrary Python objects. Lists are formed -by placing a comma-separated list of expressions in square brackets. -(Note that there are no special cases needed to form lists of length 0 -or 1.) -\obindex{list} - -\end{description} % Mutable sequences - -\end{description} % Sequences - -\item[Mapping types] -These represent finite sets of objects indexed by arbitrary index sets. -The subscript notation \verb\a[k]\ selects the element indexed -by \verb\k\ from the mapping \verb\a\; this can be used in -expressions and as the target of assignments or \verb\del\ statements. -The built-in function \verb\len()\ returns the number of elements -in a mapping. -\bifuncindex{len} -\index{subscription} -\obindex{mapping} - -There is currently a single mapping type: - -\begin{description} - -\item[Dictionaries] -These represent finite sets of objects indexed by almost arbitrary -values. The only types of values not acceptable as keys are values -containing lists or dictionaries or other mutable types that are -compared by value rather than by object identity --- the reason being -that the implementation requires that a key's hash value be constant. -Numeric types used for keys obey the normal rules for numeric -comparison: if two numbers compare equal (e.g. 1 and 1.0) then they -can be used interchangeably to index the same dictionary entry. - -Dictionaries are mutable; they are created by the \verb\{...}\ -notation (see section \ref{dict}). -\obindex{dictionary} -\obindex{mutable} - -\end{description} % Mapping types - -\item[Callable types] -These are the types to which the function call (invocation) operation, -written as \verb\function(argument, argument, ...)\, can be applied: -\indexii{function}{call} -\index{invocation} -\indexii{function}{argument} -\obindex{callable} - -\begin{description} - -\item[User-defined functions] -A user-defined function object is created by a function definition -(see section \ref{function}). It should be called with an argument -list containing the same number of items as the function's formal -parameter list. -\indexii{user-defined}{function} -\obindex{function} -\obindex{user-defined function} - -Special read-only attributes: \verb\func_code\ is the code object -representing the compiled function body, and \verb\func_globals\ is (a -reference to) the dictionary that holds the function's global -variables --- it implements the global name space of the module in -which the function was defined. -\ttindex{func_code} -\ttindex{func_globals} -\indexii{global}{name space} - -\item[User-defined methods] -A user-defined method (a.k.a. {\em object closure}) is a pair of a -class instance object and a user-defined function. It should be -called with an argument list containing one item less than the number -of items in the function's formal parameter list. When called, the -class instance becomes the first argument, and the call arguments are -shifted one to the right. -\obindex{method} -\obindex{user-defined method} -\indexii{user-defined}{method} -\index{object closure} - -Special read-only attributes: \verb\im_self\ is the class instance -object, \verb\im_func\ is the function object. -\ttindex{im_func} -\ttindex{im_self} - -\item[Built-in functions] -A built-in function object is a wrapper around a C function. Examples -of built-in functions are \verb\len\ and \verb\math.sin\. There -are no special attributes. The number and type of the arguments are -determined by the C function. -\obindex{built-in function} -\obindex{function} -\index{C} - -\item[Built-in methods] -This is really a different disguise of a built-in function, this time -containing an object passed to the C function as an implicit extra -argument. An example of a built-in method is \verb\list.append\ if -\verb\list\ is a list object. -\obindex{built-in method} -\obindex{method} -\indexii{built-in}{method} - -\item[Classes] -Class objects are described below. When a class object is called as a -parameterless function, a new class instance (also described below) is -created and returned. The class's initialization function is not -called --- this is the responsibility of the caller. It is illegal to -call a class object with one or more arguments. -\obindex{class} -\obindex{class instance} -\obindex{instance} -\indexii{class object}{call} - -\end{description} - -\item[Modules] -Modules are imported by the \verb\import\ statement (see section -\ref{import}). A module object is a container for a module's name -space, which is a dictionary (the same dictionary as referenced by the -\verb\func_globals\ attribute of functions defined in the module). -Module attribute references are translated to lookups in this -dictionary. A module object does not contain the code object used to -initialize the module (since it isn't needed once the initialization -is done). -\stindex{import} -\obindex{module} - -Attribute assignment update the module's name space dictionary. - -Special read-only attributes: \verb\__dict__\ yields the module's name -space as a dictionary object; \verb\__name__\ yields the module's name -as a string object. -\ttindex{__dict__} -\ttindex{__name__} -\indexii{module}{name space} - -\item[Classes] -Class objects are created by class definitions (see section -\ref{class}). A class is a container for a dictionary containing the -class's name space. Class attribute references are translated to -lookups in this dictionary. When an attribute name is not found -there, the attribute search continues in the base classes. The search -is depth-first, left-to-right in the order of their occurrence in the -base class list. -\obindex{class} -\obindex{class instance} -\obindex{instance} -\indexii{class object}{call} -\index{container} -\obindex{dictionary} -\indexii{class}{attribute} - -Class attribute assignments update the class's dictionary, never the -dictionary of a base class. -\indexiii{class}{attribute}{assignment} - -A class can be called as a parameterless function to yield a class -instance (see above). -\indexii{class object}{call} - -Special read-only attributes: \verb\__dict__\ yields the dictionary -containing the class's name space; \verb\__bases__\ yields a tuple -(possibly empty or a singleton) containing the base classes, in the -order of their occurrence in the base class list. -\ttindex{__dict__} -\ttindex{__bases__} - -\item[Class instances] -A class instance is created by calling a class object as a -parameterless function. A class instance has a dictionary in which -attribute references are searched. When an attribute is not found -there, and the instance's class has an attribute by that name, and -that class attribute is a user-defined function (and in no other -cases), the instance attribute reference yields a user-defined method -object (see above) constructed from the instance and the function. -\obindex{class instance} -\obindex{instance} -\indexii{class}{instance} -\indexii{class instance}{attribute} - -Attribute assignments update the instance's dictionary. -\indexiii{class instance}{attribute}{assignment} - -Class instances can pretend to be numbers, sequences, or mappings if -they have methods with certain special names. These are described in -section \ref{specialnames}. -\obindex{number} -\obindex{sequence} -\obindex{mapping} - -Special read-only attributes: \verb\__dict__\ yields the attribute -dictionary; \verb\__class__\ yields the instance's class. -\ttindex{__dict__} -\ttindex{__class__} - -\item[Files] -A file object represents an open file. (It is a wrapper around a C -{\tt stdio} file pointer.) File objects are created by the -\verb\open()\ built-in function, and also by \verb\posix.popen()\ and -the \verb\makefile\ method of socket objects. \verb\sys.stdin\, -\verb\sys.stdout\ and \verb\sys.stderr\ are file objects corresponding -the the interpreter's standard input, output and error streams. -See the Python Library Reference for methods of file objects and other -details. -\obindex{file} -\index{C} -\index{stdio} -\bifuncindex{open} -\bifuncindex{popen} -\bifuncindex{makefile} -\ttindex{stdin} -\ttindex{stdout} -\ttindex{stderr} -\ttindex{sys.stdin} -\ttindex{sys.stdout} -\ttindex{sys.stderr} - -\item[Internal types] -A few types used internally by the interpreter are exposed to the user. -Their definition may change with future versions of the interpreter, -but they are mentioned here for completeness. -\index{internal type} - -\begin{description} - -\item[Code objects] -Code objects represent executable code. The difference between a code -object and a function object is that the function object contains an -explicit reference to the function's context (the module in which it -was defined) which a code object contains no context. There is no way -to execute a bare code object. -\obindex{code} - -Special read-only attributes: \verb\co_code\ is a string representing -the sequence of instructions; \verb\co_consts\ is a list of literals -used by the code; \verb\co_names\ is a list of names (strings) used by -the code; \verb\co_filename\ is the filename from which the code was -compiled. (To find out the line numbers, you would have to decode the -instructions; the standard library module \verb\dis\ contains an -example of how to do this.) -\ttindex{co_code} -\ttindex{co_consts} -\ttindex{co_names} -\ttindex{co_filename} - -\item[Frame objects] -Frame objects represent execution frames. They may occur in traceback -objects (see below). -\obindex{frame} - -Special read-only attributes: \verb\f_back\ is to the previous -stack frame (towards the caller), or \verb\None\ if this is the bottom -stack frame; \verb\f_code\ is the code object being executed in this -frame; \verb\f_globals\ is the dictionary used to look up global -variables; \verb\f_locals\ is used for local variables; -\verb\f_lineno\ gives the line number and \verb\f_lasti\ gives the -precise instruction (this is an index into the instruction string of -the code object). -\ttindex{f_back} -\ttindex{f_code} -\ttindex{f_globals} -\ttindex{f_locals} -\ttindex{f_lineno} -\ttindex{f_lasti} - -\item[Traceback objects] \label{traceback} -Traceback objects represent a stack trace of an exception. A -traceback object is created when an exception occurs. When the search -for an exception handler unwinds the execution stack, at each unwound -level a traceback object is inserted in front of the current -traceback. When an exception handler is entered -(see also section \ref{try}), the stack trace is -made available to the program as \verb\sys.exc_traceback\. When the -program contains no suitable handler, the stack trace is written -(nicely formatted) to the standard error stream; if the interpreter is -interactive, it is also made available to the user as -\verb\sys.last_traceback\. -\obindex{traceback} -\indexii{stack}{trace} -\indexii{exception}{handler} -\indexii{execution}{stack} -\ttindex{exc_traceback} -\ttindex{last_traceback} -\ttindex{sys.exc_traceback} -\ttindex{sys.last_traceback} - -Special read-only attributes: \verb\tb_next\ is the next level in the -stack trace (towards the frame where the exception occurred), or -\verb\None\ if there is no next level; \verb\tb_frame\ points to the -execution frame of the current level; \verb\tb_lineno\ gives the line -number where the exception occurred; \verb\tb_lasti\ indicates the -precise instruction. The line number and last instruction in the -traceback may differ from the line number of its frame object if the -exception occurred in a \verb\try\ statement with no matching -\verb\except\ clause or with a \verb\finally\ clause. -\ttindex{tb_next} -\ttindex{tb_frame} -\ttindex{tb_lineno} -\ttindex{tb_lasti} -\stindex{try} - -\end{description} % Internal types - -\end{description} % Types - - -\section{Special method names} \label{specialnames} - -A class can implement certain operations that are invoked by special -syntax (such as subscription or arithmetic operations) by defining -methods with special names. For instance, if a class defines a -method named \verb\__getitem__\, and \verb\x\ is an instance of this -class, then \verb\x[i]\ is equivalent to \verb\x.__getitem__(i)\. -(The reverse is not true --- if \verb\x\ is a list object, -\verb\x.__getitem__(i)\ is not equivalent to \verb\x[i]\.) - -Except for \verb\__repr__\, \verb\__str__\ and \verb\__cmp__\, -attempts to execute an -operation raise an exception when no appropriate method is defined. -For \verb\__repr__\ and \verb\__cmp__\, the traditional -interpretations are used in this case. -For \verb\__str__\, the \verb\__repr__\ method is used. - - -\subsection{Special methods for any type} - -\begin{description} - -\item[\tt __init__(self, args...)] -Called when the instance is created. The arguments are those passed -to the class constructor expression. If a base class has an -\code{__init__} method the derived class's \code{__init__} method must -explicitly call it to ensure proper initialization of the base class -part of the instance. - -\item[\tt __del__(self)] -Called when the instance is about to be destroyed. If a base class -has an \code{__del__} method the derived class's \code{__del__} method -must explicitly call it to ensure proper deletion of the base class -part of the instance. Note that it is possible for the \code{__del__} -method to postpone destruction of the instance by creating a new -reference to it. It may then be called at a later time when this new -reference is deleted. Also note that it is not guaranteed that -\code{__del__} methods are called for objects that still exist when -the interpreter exits. - -\item[\tt __repr__(self)] -Called by the \verb\repr()\ built-in function and by conversions -(reverse quotes) to compute the string representation of an object. - -\item[\tt __str__(self)] -Called by the \verb\str()\ built-in function and by the \verb\print\ -statement compute the string representation of an object. - -\item[\tt __cmp__(self, other)] -Called by all comparison operations. Should return -1 if -\verb\self < other\, 0 if \verb\self == other\, +1 if -\verb\self > other\. If no \code{__cmp__} operation is defined, class -instances are compared by object identity (``address''). -(Implementation note: due to limitations in the interpreter, -exceptions raised by comparisons are ignored, and the objects will be -considered equal in this case.) - -\item[\tt __hash__(self)] -Called by dictionary operations and by the built-in function -\code{hash()}. Should return a 32-bit integer usable as a hash value -for dictionary operations. The only required property is that objects -which compare equal have the same hash value; it is advised to somehow -mix together (e.g. using exclusing or) the hash values for the -components of the object that also play a part in comparison of -objects. If a class does not define a \code{__cmp__} method it should -not define a \code{__hash__} operation either; if it defines -\code{__cmp__} but not \code{__hash__} its instances will not be -usable as dictionary keys. If a class defines mutable objects and -implements a \code{__cmp__} method it should not implement -\code{__hash__}, since the dictionary implementation assumes that a -key's hash value is a constant. -\obindex{dictionary} - -\end{description} - - -\subsection{Special methods for sequence and mapping types} - -\begin{description} - -\item[\tt __len__(self)] -Called to implement the built-in function \verb\len()\. Should return -the length of the object, an integer \verb\>=\ 0. Also, an object -whose \verb\__len__()\ method returns 0 is considered to be false in a -Boolean context. - -\item[\tt __getitem__(self, key)] -Called to implement evaluation of \verb\self[key]\. Note that the -special interpretation of negative keys (if the class wishes to -emulate a sequence type) is up to the \verb\__getitem__\ method. - -\item[\tt __setitem__(self, key, value)] -Called to implement assignment to \verb\self[key]\. Same note as for -\verb\__getitem__\. - -\item[\tt __delitem__(self, key)] -Called to implement deletion of \verb\self[key]\. Same note as for -\verb\__getitem__\. - -\end{description} - - -\subsection{Special methods for sequence types} - -\begin{description} - -\item[\tt __getslice__(self, i, j)] -Called to implement evaluation of \verb\self[i:j]\. Note that missing -\verb\i\ or \verb\j\ are replaced by 0 or \verb\len(self)\, -respectively, and \verb\len(self)\ has been added (once) to originally -negative \verb\i\ or \verb\j\ by the time this function is called -(unlike for \verb\__getitem__\). - -\item[\tt __setslice__(self, i, j, sequence)] -Called to implement assignment to \verb\self[i:j]\. Same notes as for -\verb\__getslice__\. - -\item[\tt __delslice__(self, i, j)] -Called to implement deletion of \verb\self[i:j]\. Same notes as for -\verb\__getslice__\. - -\end{description} - - -\subsection{Special methods for numeric types} - -\begin{description} - -\item[\tt __add__(self, other)]\itemjoin -\item[\tt __sub__(self, other)]\itemjoin -\item[\tt __mul__(self, other)]\itemjoin -\item[\tt __div__(self, other)]\itemjoin -\item[\tt __mod__(self, other)]\itemjoin -\item[\tt __divmod__(self, other)]\itemjoin -\item[\tt __pow__(self, other)]\itemjoin -\item[\tt __lshift__(self, other)]\itemjoin -\item[\tt __rshift__(self, other)]\itemjoin -\item[\tt __and__(self, other)]\itemjoin -\item[\tt __xor__(self, other)]\itemjoin -\item[\tt __or__(self, other)]\itembreak -Called to implement the binary arithmetic operations (\verb\+\, -\verb\-\, \verb\*\, \verb\/\, \verb\%\, \verb\divmod()\, \verb\pow()\, -\verb\<<\, \verb\>>\, \verb\&\, \verb\^\, \verb\|\). - -\item[\tt __neg__(self)]\itemjoin -\item[\tt __pos__(self)]\itemjoin -\item[\tt __abs__(self)]\itemjoin -\item[\tt __invert__(self)]\itembreak -Called to implement the unary arithmetic operations (\verb\-\, \verb\+\, -\verb\abs()\ and \verb\~\). - -\item[\tt __nonzero__(self)] -Called to implement boolean testing; should return 0 or 1. An -alternative name for this method is \verb\__len__\. - -\item[\tt __coerce__(self, other)] -Called to implement ``mixed-mode'' numeric arithmetic. Should either -return a tuple containing self and other converted to a common numeric -type, or None if no way of conversion is known. When the common type -would be the type of other, it is sufficient to return None, since the -interpreter will also ask the other object to attempt a coercion (but -sometimes, if the implementation of the other type cannot be changed, -it is useful to do the conversion to the other type here). - -Note that this method is not called to coerce the arguments to \verb\+\ -and \verb\*\, because these are also used to implement sequence -concatenation and repetition, respectively. Also note that, for the -same reason, in \verb\n*x\, where \verb\n\ is a built-in number and -\verb\x\ is an instance, a call to \verb\x.__mul__(n)\ is made.% -\footnote{The interpreter should really distinguish between -user-defined classes implementing sequences, mappings or numbers, but -currently it doesn't --- hence this strange exception.} - -\item[\tt __int__(self)]\itemjoin -\item[\tt __long__(self)]\itemjoin -\item[\tt __float__(self)]\itembreak -Called to implement the built-in functions \verb\int()\, \verb\long()\ -and \verb\float()\. Should return a value of the appropriate type. - -\item[\tt __oct__(self)]\itemjoin -\item[\tt __hex__(self)]\itembreak -Called to implement the built-in functions \verb\oct()\ and -\verb\hex()\. Should return a string value. - -\end{description} diff --git a/Doc/ref/ref4.tex b/Doc/ref/ref4.tex deleted file mode 100644 index 62db120989..0000000000 --- a/Doc/ref/ref4.tex +++ /dev/null @@ -1,148 +0,0 @@ -\chapter{Execution model} -\index{execution model} - -\section{Code blocks, execution frames, and name spaces} \label{execframes} -\index{code block} -\indexii{execution}{frame} -\index{name space} - -A {\em code block} is a piece of Python program text that can be -executed as a unit, such as a module, a class definition or a function -body. Some code blocks (like modules) are executed only once, others -(like function bodies) may be executed many times. Code block may -textually contain other code blocks. Code blocks may invoke other -code blocks (that may or may not be textually contained in them) as -part of their execution, e.g. by invoking (calling) a function. -\index{code block} -\indexii{code}{block} - -The following are code blocks: A module is a code block. A function -body is a code block. A class definition is a code block. Each -command typed interactively is a separate code block; a script file is -a code block. The string argument passed to the built-in function -\verb\eval\ and to the \verb\exec\ statement are code blocks. -And finally, the -expression read and evaluated by the built-in function \verb\input\ is -a code block. - -A code block is executed in an execution frame. An {\em execution -frame} contains some administrative information (used for debugging), -determines where and how execution continues after the code block's -execution has completed, and (perhaps most importantly) defines two -name spaces, the local and the global name space, that affect -execution of the code block. -\indexii{execution}{frame} - -A {\em name space} is a mapping from names (identifiers) to objects. -A particular name space may be referenced by more than one execution -frame, and from other places as well. Adding a name to a name space -is called {\em binding} a name (to an object); changing the mapping of -a name is called {\em rebinding}; removing a name is {\em unbinding}. -Name spaces are functionally equivalent to dictionaries. -\index{name space} -\indexii{binding}{name} -\indexii{rebinding}{name} -\indexii{unbinding}{name} - -The {\em local name space} of an execution frame determines the default -place where names are defined and searched. The {\em global name -space} determines the place where names listed in \verb\global\ -statements are defined and searched, and where names that are not -explicitly bound in the current code block are searched. -\indexii{local}{name space} -\indexii{global}{name space} -\stindex{global} - -Whether a name is local or global in a code block is determined by -static inspection of the source text for the code block: in the -absence of \verb\global\ statements, a name that is bound anywhere in -the code block is local in the entire code block; all other names are -considered global. The \verb\global\ statement forces global -interpretation of selected names throughout the code block. The -following constructs bind names: formal parameters, \verb\import\ -statements, class and function definitions (these bind the class or -function name), and targets that are identifiers if occurring in an -assignment, \verb\for\ loop header, or \verb\except\ clause header. -(A target occurring in a \verb\del\ statement does not bind a name.) - -When a global name is not found in the global name space, it is -searched in the list of ``built-in'' names (which is actually the -global name space of the module \verb\__builtin__\). When a name is not -found at all, the \verb\NameError\ exception is raised. - -The following table lists the meaning of the local and global name -space for various types of code blocks. The name space for a -particular module is automatically created when the module is first -referenced. - -\begin{center} -\begin{tabular}{|l|l|l|l|} -\hline -Code block type & Global name space & Local name space & Notes \\ -\hline -Module & n.s. for this module & same as global & \\ -Script & n.s. for \verb\__main__\ & same as global & \\ -Interactive command & n.s. for \verb\__main__\ & same as global & \\ -Class definition & global n.s. of containing block & new n.s. & \\ -Function body & global n.s. of containing block & new n.s. & \\ -String passed to \verb\exec\ or \verb\eval\ - & global n.s. of caller & local n.s. of caller & (1) \\ -File read by \verb\execfile\ - & global n.s. of caller & local n.s. of caller & (1) \\ -Expression read by \verb\input\ - & global n.s. of caller & local n.s. of caller & \\ -\hline -\end{tabular} -\end{center} - -Notes: - -\begin{description} - -\item[n.s.] means {\em name space} - -\item[(1)] The global and local name space for these functions can be -overridden with optional extra arguments. - -\end{description} - -\section{Exceptions} - -Exceptions are a means of breaking out of the normal flow of control -of a code block in order to handle errors or other exceptional -conditions. An exception is {\em raised} at the point where the error -is detected; it may be {\em handled} by the surrounding code block or -by any code block that directly or indirectly invoked the code block -where the error occurred. -\index{exception} -\index{raise an exception} -\index{handle an exception} -\index{exception handler} -\index{errors} -\index{error handling} - -The Python interpreter raises an exception when it detects an run-time -error (such as division by zero). A Python program can also -explicitly raise an exception with the \verb\raise\ statement. -Exception handlers are specified with the \verb\try...except\ -statement. - -Python uses the ``termination'' model of error handling: an exception -handler can find out what happened and continue execution at an outer -level, but it cannot repair the cause of the error and retry the -failing operation (except by re-entering the the offending piece of -code from the top). - -When an exception is not handled at all, the interpreter terminates -execution of the program, or returns to its interactive main loop. - -Exceptions are identified by string objects. Two different string -objects with the same value identify different exceptions. - -When an exception is raised, an object (maybe \verb\None\) is passed -as the exception's ``parameter''; this object does not affect the -selection of an exception handler, but is passed to the selected -exception handler as additional information. - -See also the description of the \verb\try\ and \verb\raise\ -statements. diff --git a/Doc/ref/ref5.tex b/Doc/ref/ref5.tex deleted file mode 100644 index 55f523fb17..0000000000 --- a/Doc/ref/ref5.tex +++ /dev/null @@ -1,689 +0,0 @@ -\chapter{Expressions and conditions} -\index{expression} -\index{condition} - -{\bf Note:} In this and the following chapters, extended BNF notation -will be used to describe syntax, not lexical analysis. -\index{BNF} - -This chapter explains the meaning of the elements of expressions and -conditions. Conditions are a superset of expressions, and a condition -may be used wherever an expression is required by enclosing it in -parentheses. The only places where expressions are used in the syntax -instead of conditions is in expression statements and on the -right-hand side of assignment statements; this catches some nasty bugs -like accidentally writing \verb\x == 1\ instead of \verb\x = 1\. -\indexii{assignment}{statement} - -The comma plays several roles in Python's syntax. It is usually an -operator with a lower precedence than all others, but occasionally -serves other purposes as well; e.g. it separates function arguments, -is used in list and dictionary constructors, and has special semantics -in \verb\print\ statements. -\index{comma} - -When (one alternative of) a syntax rule has the form - -\begin{verbatim} -name: othername -\end{verbatim} - -and no semantics are given, the semantics of this form of \verb\name\ -are the same as for \verb\othername\. -\index{syntax} - -\section{Arithmetic conversions} -\indexii{arithmetic}{conversion} - -When a description of an arithmetic operator below uses the phrase -``the numeric arguments are converted to a common type'', -this both means that if either argument is not a number, a -\verb\TypeError\ exception is raised, and that otherwise -the following conversions are applied: -\exindex{TypeError} -\indexii{floating point}{number} -\indexii{long}{integer} -\indexii{plain}{integer} - -\begin{itemize} -\item first, if either argument is a floating point number, - the other is converted to floating point; -\item else, if either argument is a long integer, - the other is converted to long integer; -\item otherwise, both must be plain integers and no conversion - is necessary. -\end{itemize} - -\section{Atoms} -\index{atom} - -Atoms are the most basic elements of expressions. Forms enclosed in -reverse quotes or in parentheses, brackets or braces are also -categorized syntactically as atoms. The syntax for atoms is: - -\begin{verbatim} -atom: identifier | literal | enclosure -enclosure: parenth_form | list_display | dict_display | string_conversion -\end{verbatim} - -\subsection{Identifiers (Names)} -\index{name} -\index{identifier} - -An identifier occurring as an atom is a reference to a local, global -or built-in name binding. If a name can be assigned to anywhere in a -code block, and is not mentioned in a \verb\global\ statement in that -code block, it refers to a local name throughout that code block. -Otherwise, it refers to a global name if one exists, else to a -built-in name. -\indexii{name}{binding} -\index{code block} -\stindex{global} -\indexii{built-in}{name} -\indexii{global}{name} - -When the name is bound to an object, evaluation of the atom yields -that object. When a name is not bound, an attempt to evaluate it -raises a \verb\NameError\ exception. -\exindex{NameError} - -\subsection{Literals} -\index{literal} - -Python knows string and numeric literals: - -\begin{verbatim} -literal: stringliteral | integer | longinteger | floatnumber -\end{verbatim} - -Evaluation of a literal yields an object of the given type (string, -integer, long integer, floating point number) with the given value. -The value may be approximated in the case of floating point literals. -See section \ref{literals} for details. - -All literals correspond to immutable data types, and hence the -object's identity is less important than its value. Multiple -evaluations of literals with the same value (either the same -occurrence in the program text or a different occurrence) may obtain -the same object or a different object with the same value. -\indexiii{immutable}{data}{type} - -(In the original implementation, all literals in the same code block -with the same type and value yield the same object.) - -\subsection{Parenthesized forms} -\index{parenthesized form} - -A parenthesized form is an optional condition list enclosed in -parentheses: - -\begin{verbatim} -parenth_form: "(" [condition_list] ")" -\end{verbatim} - -A parenthesized condition list yields whatever that condition list -yields. - -An empty pair of parentheses yields an empty tuple object. Since -tuples are immutable, the rules for literals apply here. -\indexii{empty}{tuple} - -(Note that tuples are not formed by the parentheses, but rather by use -of the comma operator. The exception is the empty tuple, for which -parentheses {\em are} required --- allowing unparenthesized ``nothing'' -in expressions would causes ambiguities and allow common typos to -pass uncaught.) -\index{comma} -\indexii{tuple}{display} - -\subsection{List displays} -\indexii{list}{display} - -A list display is a possibly empty series of conditions enclosed in -square brackets: - -\begin{verbatim} -list_display: "[" [condition_list] "]" -\end{verbatim} - -A list display yields a new list object. -\obindex{list} - -If it has no condition list, the list object has no items. Otherwise, -the elements of the condition list are evaluated from left to right -and inserted in the list object in that order. -\indexii{empty}{list} - -\subsection{Dictionary displays} \label{dict} -\indexii{dictionary}{display} - -A dictionary display is a possibly empty series of key/datum pairs -enclosed in curly braces: -\index{key} -\index{datum} -\index{key/datum pair} - -\begin{verbatim} -dict_display: "{" [key_datum_list] "}" -key_datum_list: key_datum ("," key_datum)* [","] -key_datum: condition ":" condition -\end{verbatim} - -A dictionary display yields a new dictionary object. -\obindex{dictionary} - -The key/datum pairs are evaluated from left to right to define the -entries of the dictionary: each key object is used as a key into the -dictionary to store the corresponding datum. - -Restrictions on the types of the key values are listed earlier in -section \ref{types}. -Clashes between duplicate keys are not detected; the last -datum (textually rightmost in the display) stored for a given key -value prevails. -\exindex{TypeError} - -\subsection{String conversions} -\indexii{string}{conversion} - -A string conversion is a condition list enclosed in reverse (or -backward) quotes: - -\begin{verbatim} -string_conversion: "`" condition_list "`" -\end{verbatim} - -A string conversion evaluates the contained condition list and -converts the resulting object into a string according to rules -specific to its type. - -If the object is a string, a number, \verb\None\, or a tuple, list or -dictionary containing only objects whose type is one of these, the -resulting string is a valid Python expression which can be passed to -the built-in function \verb\eval()\ to yield an expression with the -same value (or an approximation, if floating point numbers are -involved). - -(In particular, converting a string adds quotes around it and converts -``funny'' characters to escape sequences that are safe to print.) - -It is illegal to attempt to convert recursive objects (e.g. lists or -dictionaries that contain a reference to themselves, directly or -indirectly.) -\obindex{recursive} - -\section{Primaries} \label{primaries} -\index{primary} - -Primaries represent the most tightly bound operations of the language. -Their syntax is: - -\begin{verbatim} -primary: atom | attributeref | subscription | slicing | call -\end{verbatim} - -\subsection{Attribute references} -\indexii{attribute}{reference} - -An attribute reference is a primary followed by a period and a name: - -\begin{verbatim} -attributeref: primary "." identifier -\end{verbatim} - -The primary must evaluate to an object of a type that supports -attribute references, e.g. a module or a list. This object is then -asked to produce the attribute whose name is the identifier. If this -attribute is not available, the exception \verb\AttributeError\ is -raised. Otherwise, the type and value of the object produced is -determined by the object. Multiple evaluations of the same attribute -reference may yield different objects. -\obindex{module} -\obindex{list} - -\subsection{Subscriptions} -\index{subscription} - -A subscription selects an item of a sequence (string, tuple or list) -or mapping (dictionary) object: -\obindex{sequence} -\obindex{mapping} -\obindex{string} -\obindex{tuple} -\obindex{list} -\obindex{dictionary} -\indexii{sequence}{item} - -\begin{verbatim} -subscription: primary "[" condition "]" -\end{verbatim} - -The primary must evaluate to an object of a sequence or mapping type. - -If it is a mapping, the condition must evaluate to an object whose -value is one of the keys of the mapping, and the subscription selects -the value in the mapping that corresponds to that key. - -If it is a sequence, the condition must evaluate to a plain integer. -If this value is negative, the length of the sequence is added to it -(so that, e.g. \verb\x[-1]\ selects the last item of \verb\x\.) -The resulting value must be a nonnegative integer smaller than the -number of items in the sequence, and the subscription selects the item -whose index is that value (counting from zero). - -A string's items are characters. A character is not a separate data -type but a string of exactly one character. -\index{character} -\indexii{string}{item} - -\subsection{Slicings} -\index{slicing} -\index{slice} - -A slicing (or slice) selects a range of items in a sequence (string, -tuple or list) object: -\obindex{sequence} -\obindex{string} -\obindex{tuple} -\obindex{list} - -\begin{verbatim} -slicing: primary "[" [condition] ":" [condition] "]" -\end{verbatim} - -The primary must evaluate to a sequence object. The lower and upper -bound expressions, if present, must evaluate to plain integers; -defaults are zero and the sequence's length, respectively. If either -bound is negative, the sequence's length is added to it. The slicing -now selects all items with index $k$ such that $i <= k < j$ where $i$ -and $j$ are the specified lower and upper bounds. This may be an -empty sequence. It is not an error if $i$ or $j$ lie outside the -range of valid indexes (such items don't exist so they aren't -selected). - -\subsection{Calls} \label{calls} -\index{call} - -A call calls a callable object (e.g. a function) with a possibly empty -series of arguments: -\obindex{callable} - -\begin{verbatim} -call: primary "(" [condition_list] ")" -\end{verbatim} - -The primary must evaluate to a callable object (user-defined -functions, built-in functions, methods of built-in objects, class -objects, and methods of class instances are callable). If it is a -class, the argument list must be empty; otherwise, the arguments are -evaluated. - -A call always returns some value, possibly \verb\None\, unless it -raises an exception. How this value is computed depends on the type -of the callable object. If it is: - -\begin{description} - -\item[a user-defined function:] the code block for the function is -executed, passing it the argument list. The first thing the code -block will do is bind the formal parameters to the arguments; this is -described in section \ref{function}. When the code block executes a -\verb\return\ statement, this specifies the return value of the -function call. -\indexii{function}{call} -\indexiii{user-defined}{function}{call} -\obindex{user-defined function} -\obindex{function} - -\item[a built-in function or method:] the result is up to the -interpreter; see the library reference manual for the descriptions of -built-in functions and methods. -\indexii{function}{call} -\indexii{built-in function}{call} -\indexii{method}{call} -\indexii{built-in method}{call} -\obindex{built-in method} -\obindex{built-in function} -\obindex{method} -\obindex{function} - -\item[a class object:] a new instance of that class is returned. -\obindex{class} -\indexii{class object}{call} - -\item[a class instance method:] the corresponding user-defined -function is called, with an argument list that is one longer than the -argument list of the call: the instance becomes the first argument. -\obindex{class instance} -\obindex{instance} -\indexii{instance}{call} -\indexii{class instance}{call} - -\end{description} - -\section{Unary arithmetic operations} -\indexiii{unary}{arithmetic}{operation} -\indexiii{unary}{bit-wise}{operation} - -All unary arithmetic (and bit-wise) operations have the same priority: - -\begin{verbatim} -u_expr: primary | "-" u_expr | "+" u_expr | "~" u_expr -\end{verbatim} - -The unary \verb\"-"\ (minus) operator yields the negation of its -numeric argument. -\index{negation} -\index{minus} - -The unary \verb\"+"\ (plus) operator yields its numeric argument -unchanged. -\index{plus} - -The unary \verb\"~"\ (invert) operator yields the bit-wise inversion -of its plain or long integer argument. The bit-wise inversion of -\verb\x\ is defined as \verb\-(x+1)\. -\index{inversion} - -In all three cases, if the argument does not have the proper type, -a \verb\TypeError\ exception is raised. -\exindex{TypeError} - -\section{Binary arithmetic operations} -\indexiii{binary}{arithmetic}{operation} - -The binary arithmetic operations have the conventional priority -levels. Note that some of these operations also apply to certain -non-numeric types. There is no ``power'' operator, so there are only -two levels, one for multiplicative operators and one for additive -operators: - -\begin{verbatim} -m_expr: u_expr | m_expr "*" u_expr - | m_expr "/" u_expr | m_expr "%" u_expr -a_expr: m_expr | aexpr "+" m_expr | aexpr "-" m_expr -\end{verbatim} - -The \verb\"*"\ (multiplication) operator yields the product of its -arguments. The arguments must either both be numbers, or one argument -must be a plain integer and the other must be a sequence. In the -former case, the numbers are converted to a common type and then -multiplied together. In the latter case, sequence repetition is -performed; a negative repetition factor yields an empty sequence. -\index{multiplication} - -The \verb\"/"\ (division) operator yields the quotient of its -arguments. The numeric arguments are first converted to a common -type. Plain or long integer division yields an integer of the same -type; the result is that of mathematical division with the `floor' -function applied to the result. Division by zero raises the -\verb\ZeroDivisionError\ exception. -\exindex{ZeroDivisionError} -\index{division} - -The \verb\"%"\ (modulo) operator yields the remainder from the -division of the first argument by the second. The numeric arguments -are first converted to a common type. A zero right argument raises -the \verb\ZeroDivisionError\ exception. The arguments may be floating -point numbers, e.g. \verb\3.14 % 0.7\ equals \verb\0.34\. The modulo -operator always yields a result with the same sign as its second -operand (or zero); the absolute value of the result is strictly -smaller than the second operand. -\index{modulo} - -The integer division and modulo operators are connected by the -following identity: \verb\x == (x/y)*y + (x%y)\. Integer division and -modulo are also connected with the built-in function \verb\divmod()\: -\verb\divmod(x, y) == (x/y, x%y)\. These identities don't hold for -floating point numbers; there a similar identity holds where -\verb\x/y\ is replaced by \verb\floor(x/y)\). - -The \verb\"+"\ (addition) operator yields the sum of its arguments. -The arguments must either both be numbers, or both sequences of the -same type. In the former case, the numbers are converted to a common -type and then added together. In the latter case, the sequences are -concatenated. -\index{addition} - -The \verb\"-"\ (subtraction) operator yields the difference of its -arguments. The numeric arguments are first converted to a common -type. -\index{subtraction} - -\section{Shifting operations} -\indexii{shifting}{operation} - -The shifting operations have lower priority than the arithmetic -operations: - -\begin{verbatim} -shift_expr: a_expr | shift_expr ( "<<" | ">>" ) a_expr -\end{verbatim} - -These operators accept plain or long integers as arguments. The -arguments are converted to a common type. They shift the first -argument to the left or right by the number of bits given by the -second argument. - -A right shift by $n$ bits is defined as division by $2^n$. A left -shift by $n$ bits is defined as multiplication with $2^n$; for plain -integers there is no overflow check so this drops bits and flip the -sign if the result is not less than $2^{31}$ in absolute value. - -Negative shift counts raise a \verb\ValueError\ exception. -\exindex{ValueError} - -\section{Binary bit-wise operations} -\indexiii{binary}{bit-wise}{operation} - -Each of the three bitwise operations has a different priority level: - -\begin{verbatim} -and_expr: shift_expr | and_expr "&" shift_expr -xor_expr: and_expr | xor_expr "^" and_expr -or_expr: xor_expr | or_expr "|" xor_expr -\end{verbatim} - -The \verb\"&"\ operator yields the bitwise AND of its arguments, which -must be plain or long integers. The arguments are converted to a -common type. -\indexii{bit-wise}{and} - -The \verb\"^"\ operator yields the bitwise XOR (exclusive OR) of its -arguments, which must be plain or long integers. The arguments are -converted to a common type. -\indexii{bit-wise}{xor} -\indexii{exclusive}{or} - -The \verb\"|"\ operator yields the bitwise (inclusive) OR of its -arguments, which must be plain or long integers. The arguments are -converted to a common type. -\indexii{bit-wise}{or} -\indexii{inclusive}{or} - -\section{Comparisons} -\index{comparison} - -Contrary to C, all comparison operations in Python have the same -priority, which is lower than that of any arithmetic, shifting or -bitwise operation. Also contrary to C, expressions like -\verb\a < b < c\ have the interpretation that is conventional in -mathematics: -\index{C} - -\begin{verbatim} -comparison: or_expr (comp_operator or_expr)* -comp_operator: "<"|">"|"=="|">="|"<="|"<>"|"!="|"is" ["not"]|["not"] "in" -\end{verbatim} - -Comparisons yield integer values: 1 for true, 0 for false. - -Comparisons can be chained arbitrarily, e.g. $x < y <= z$ is -equivalent to $x < y$ \verb\and\ $y <= z$, except that $y$ is -evaluated only once (but in both cases $z$ is not evaluated at all -when $x < y$ is found to be false). -\indexii{chaining}{comparisons} - -\catcode`\_=8 -Formally, $e_0 op_1 e_1 op_2 e_2 ...e_{n-1} op_n e_n$ is equivalent to -$e_0 op_1 e_1$ \verb\and\ $e_1 op_2 e_2$ \verb\and\ ... \verb\and\ -$e_{n-1} op_n e_n$, except that each expression is evaluated at most once. - -Note that $e_0 op_1 e_1 op_2 e_2$ does not imply any kind of comparison -between $e_0$ and $e_2$, e.g. $x < y > z$ is perfectly legal. -\catcode`\_=12 - -The forms \verb\<>\ and \verb\!=\ are equivalent; for consistency with -C, \verb\!=\ is preferred; where \verb\!=\ is mentioned below -\verb\<>\ is also implied. - -The operators {\tt "<", ">", "==", ">=", "<="}, and {\tt "!="} compare -the values of two objects. The objects needn't have the same type. -If both are numbers, they are coverted to a common type. Otherwise, -objects of different types {\em always} compare unequal, and are -ordered consistently but arbitrarily. - -(This unusual definition of comparison is done to simplify the -definition of operations like sorting and the \verb\in\ and \verb\not -in\ operators.) - -Comparison of objects of the same type depends on the type: - -\begin{itemize} - -\item -Numbers are compared arithmetically. - -\item -Strings are compared lexicographically using the numeric equivalents -(the result of the built-in function \verb\ord\) of their characters. - -\item -Tuples and lists are compared lexicographically using comparison of -corresponding items. - -\item -Mappings (dictionaries) are compared through lexicographic -comparison of their sorted (key, value) lists.% -\footnote{This is expensive since it requires sorting the keys first, -but about the only sensible definition. An earlier version of Python -compared dictionaries by identity only, but this caused surprises -because people expected to be able to test a dictionary for emptiness -by comparing it to {\tt \{\}}.} - -\item -Most other types compare unequal unless they are the same object; -the choice whether one object is considered smaller or larger than -another one is made arbitrarily but consistently within one -execution of a program. - -\end{itemize} - -The operators \verb\in\ and \verb\not in\ test for sequence -membership: if $y$ is a sequence, $x ~\verb\in\~ y$ is true if and -only if there exists an index $i$ such that $x = y[i]$. -$x ~\verb\not in\~ y$ yields the inverse truth value. The exception -\verb\TypeError\ is raised when $y$ is not a sequence, or when $y$ is -a string and $x$ is not a string of length one.% -\footnote{The latter restriction is sometimes a nuisance.} -\opindex{in} -\opindex{not in} -\indexii{membership}{test} -\obindex{sequence} - -The operators \verb\is\ and \verb\is not\ test for object identity: -$x ~\verb\is\~ y$ is true if and only if $x$ and $y$ are the same -object. $x ~\verb\is not\~ y$ yields the inverse truth value. -\opindex{is} -\opindex{is not} -\indexii{identity}{test} - -\section{Boolean operations} \label{Booleans} -\indexii{Boolean}{operation} - -Boolean operations have the lowest priority of all Python operations: - -\begin{verbatim} -condition: or_test | lambda_form -or_test: and_test | or_test "or" and_test -and_test: not_test | and_test "and" not_test -not_test: comparison | "not" not_test -lambda_form: "lambda" [parameter_list]: condition -\end{verbatim} - -In the context of Boolean operations, and also when conditions are -used by control flow statements, the following values are interpreted -as false: \verb\None\, numeric zero of all types, empty sequences -(strings, tuples and lists), and empty mappings (dictionaries). All -other values are interpreted as true. - -The operator \verb\not\ yields 1 if its argument is false, 0 otherwise. -\opindex{not} - -The condition $x ~\verb\and\~ y$ first evaluates $x$; if $x$ is false, -its value is returned; otherwise, $y$ is evaluated and the resulting -value is returned. -\opindex{and} - -The condition $x ~\verb\or\~ y$ first evaluates $x$; if $x$ is true, -its value is returned; otherwise, $y$ is evaluated and the resulting -value is returned. -\opindex{or} - -(Note that \verb\and\ and \verb\or\ do not restrict the value and type -they return to 0 and 1, but rather return the last evaluated argument. -This is sometimes useful, e.g. if \verb\s\ is a string that should be -replaced by a default value if it is empty, the expression -\verb\s or 'foo'\ yields the desired value. Because \verb\not\ has to -invent a value anyway, it does not bother to return a value of the -same type as its argument, so e.g. \verb\not 'foo'\ yields \verb\0\, -not \verb\''\.) - -Lambda forms (lambda expressions) have the same syntactic position as -conditions. They are a shorthand to create anonymous functions; the -expression \verb\lambda\ {\em arguments}\verb\:\ {\em condition} -yields a function object that behaves virtually identical to one -defined with \verb\def\ {\em name}\verb\(\{\em arguments}\verb\) : -return\ {\em condition}. See section \ref{function} for the syntax of -parameter lists. Note that functions created with lambda forms cannot -contain statements. -\label{lambda} -\indexii{lambda}{expression} -\indexii{lambda}{form} -\indexii{anonmymous}{function} - -\section{Expression lists and condition lists} -\indexii{expression}{list} -\indexii{condition}{list} - -\begin{verbatim} -expr_list: or_expr ("," or_expr)* [","] -cond_list: condition ("," condition)* [","] -\end{verbatim} - -The only difference between expression lists and condition lists is -the lowest priority of operators that can be used in them without -being enclosed in parentheses; condition lists allow all operators, -while expression lists don't allow comparisons and Boolean operators -(they do allow bitwise and shift operators though). - -Expression lists are used in expression statements and assignments; -condition lists are used everywhere else where a list of -comma-separated values is required. - -An expression (condition) list containing at least one comma yields a -tuple. The length of the tuple is the number of expressions -(conditions) in the list. The expressions (conditions) are evaluated -from left to right. (Conditions lists are used syntactically is a few -places where no tuple is constructed but a list of values is needed -nevertheless.) -\obindex{tuple} - -The trailing comma is required only to create a single tuple (a.k.a. a -{\em singleton}); it is optional in all other cases. A single -expression (condition) without a trailing comma doesn't create a -tuple, but rather yields the value of that expression (condition). -\indexii{trailing}{comma} - -(To create an empty tuple, use an empty pair of parentheses: -\verb\()\.) diff --git a/Doc/ref/ref6.tex b/Doc/ref/ref6.tex deleted file mode 100644 index 086d49bed2..0000000000 --- a/Doc/ref/ref6.tex +++ /dev/null @@ -1,507 +0,0 @@ -\chapter{Simple statements} -\indexii{simple}{statement} - -Simple statements are comprised within a single logical line. -Several simple statements may occur on a single line separated -by semicolons. The syntax for simple statements is: - -\begin{verbatim} -simple_stmt: expression_stmt - | assignment_stmt - | pass_stmt - | del_stmt - | print_stmt - | return_stmt - | raise_stmt - | break_stmt - | continue_stmt - | import_stmt - | global_stmt - | access_stmt - | exec_stmt -\end{verbatim} - -\section{Expression statements} -\indexii{expression}{statement} - -Expression statements are used (mostly interactively) to compute and -write a value, or (usually) to call a procedure (a function that -returns no meaningful result; in Python, procedures return the value -\verb\None\): - -\begin{verbatim} -expression_stmt: expression_list -\end{verbatim} - -An expression statement evaluates the expression list (which may be a -single expression). If the value is not \verb\None\, it is converted -to a string using the rules for string conversions (expressions in -reverse quotes), and the resulting string is written to standard -output (see section \ref{print}) on a line by itself. -\indexii{expression}{list} -\ttindex{None} -\indexii{string}{conversion} -\index{output} -\indexii{standard}{output} -\indexii{writing}{values} - -(The exception for \verb\None\ is made so that procedure calls, which -are syntactically equivalent to expressions, do not cause any output. -A tuple with only \verb\None\ items is written normally.) -\indexii{procedure}{call} - -\section{Assignment statements} -\indexii{assignment}{statement} - -Assignment statements are used to (re)bind names to values and to -modify attributes or items of mutable objects: -\indexii{binding}{name} -\indexii{rebinding}{name} -\obindex{mutable} -\indexii{attribute}{assignment} - -\begin{verbatim} -assignment_stmt: (target_list "=")+ expression_list -target_list: target ("," target)* [","] -target: identifier | "(" target_list ")" | "[" target_list "]" - | attributeref | subscription | slicing -\end{verbatim} - -(See section \ref{primaries} for the syntax definitions for the last -three symbols.) - -An assignment statement evaluates the expression list (remember that -this can be a single expression or a comma-separated list, the latter -yielding a tuple) and assigns the single resulting object to each of -the target lists, from left to right. -\indexii{expression}{list} - -Assignment is defined recursively depending on the form of the target -(list). When a target is part of a mutable object (an attribute -reference, subscription or slicing), the mutable object must -ultimately perform the assignment and decide about its validity, and -may raise an exception if the assignment is unacceptable. The rules -observed by various types and the exceptions raised are given with the -definition of the object types (see section \ref{types}). -\index{target} -\indexii{target}{list} - -Assignment of an object to a target list is recursively defined as -follows. -\indexiii{target}{list}{assignment} - -\begin{itemize} -\item -If the target list is a single target: the object is assigned to that -target. - -\item -If the target list is a comma-separated list of targets: the object -must be a tuple with the same number of items as the list contains -targets, and the items are assigned, from left to right, to the -corresponding targets. - -\end{itemize} - -Assignment of an object to a single target is recursively defined as -follows. - -\begin{itemize} % nested - -\item -If the target is an identifier (name): - -\begin{itemize} - -\item -If the name does not occur in a \verb\global\ statement in the current -code block: the name is bound to the object in the current local name -space. -\stindex{global} - -\item -Otherwise: the name is bound to the object in the current global name -space. - -\end{itemize} % nested - -The name is rebound if it was already bound. - -\item -If the target is a target list enclosed in parentheses: the object is -assigned to that target list as described above. - -\item -If the target is a target list enclosed in square brackets: the object -must be a list with the same number of items as the target list -contains targets, and its items are assigned, from left to right, to -the corresponding targets. - -\item -If the target is an attribute reference: The primary expression in the -reference is evaluated. It should yield an object with assignable -attributes; if this is not the case, \verb\TypeError\ is raised. That -object is then asked to assign the assigned object to the given -attribute; if it cannot perform the assignment, it raises an exception -(usually but not necessarily \verb\AttributeError\). -\indexii{attribute}{assignment} - -\item -If the target is a subscription: The primary expression in the -reference is evaluated. It should yield either a mutable sequence -(list) object or a mapping (dictionary) object. Next, the subscript -expression is evaluated. -\indexii{subscription}{assignment} -\obindex{mutable} - -If the primary is a mutable sequence object (a list), the subscript -must yield a plain integer. If it is negative, the sequence's length -is added to it. The resulting value must be a nonnegative integer -less than the sequence's length, and the sequence is asked to assign -the assigned object to its item with that index. If the index is out -of range, \verb\IndexError\ is raised (assignment to a subscripted -sequence cannot add new items to a list). -\obindex{sequence} -\obindex{list} - -If the primary is a mapping (dictionary) object, the subscript must -have a type compatible with the mapping's key type, and the mapping is -then asked to to create a key/datum pair which maps the subscript to -the assigned object. This can either replace an existing key/value -pair with the same key value, or insert a new key/value pair (if no -key with the same value existed). -\obindex{mapping} -\obindex{dictionary} - -\item -If the target is a slicing: The primary expression in the reference is -evaluated. It should yield a mutable sequence (list) object. The -assigned object should be a sequence object of the same type. Next, -the lower and upper bound expressions are evaluated, insofar they are -present; defaults are zero and the sequence's length. The bounds -should evaluate to (small) integers. If either bound is negative, the -sequence's length is added to it. The resulting bounds are clipped to -lie between zero and the sequence's length, inclusive. Finally, the -sequence object is asked to replace the items indicated by the slice -with the items of the assigned sequence. This may change the -sequence's length, if it allows it. -\indexii{slicing}{assignment} - -\end{itemize} - -(In the original implementation, the syntax for targets is taken -to be the same as for expressions, and invalid syntax is rejected -during the code generation phase, causing less detailed error -messages.) - -\section{The {\tt pass} statement} -\stindex{pass} - -\begin{verbatim} -pass_stmt: "pass" -\end{verbatim} - -\verb\pass\ is a null operation --- when it is executed, nothing -happens. It is useful as a placeholder when a statement is -required syntactically, but no code needs to be executed, for example: -\indexii{null}{operation} - -\begin{verbatim} -def f(arg): pass # a function that does nothing (yet) - -class C: pass # an class with no methods (yet) -\end{verbatim} - -\section{The {\tt del} statement} -\stindex{del} - -\begin{verbatim} -del_stmt: "del" target_list -\end{verbatim} - -Deletion is recursively defined very similar to the way assignment is -defined. Rather that spelling it out in full details, here are some -hints. -\indexii{deletion}{target} -\indexiii{deletion}{target}{list} - -Deletion of a target list recursively deletes each target, from left -to right. - -Deletion of a name removes the binding of that name (which must exist) -from the local or global name space, depending on whether the name -occurs in a \verb\global\ statement in the same code block. -\stindex{global} -\indexii{unbinding}{name} - -Deletion of attribute references, subscriptions and slicings -is passed to the primary object involved; deletion of a slicing -is in general equivalent to assignment of an empty slice of the -right type (but even this is determined by the sliced object). -\indexii{attribute}{deletion} - -\section{The {\tt print} statement} \label{print} -\stindex{print} - -\begin{verbatim} -print_stmt: "print" [ condition ("," condition)* [","] ] -\end{verbatim} - -\verb\print\ evaluates each condition in turn and writes the resulting -object to standard output (see below). If an object is not a string, -it is first converted to a string using the rules for string -conversions. The (resulting or original) string is then written. A -space is written before each object is (converted and) written, unless -the output system believes it is positioned at the beginning of a -line. This is the case: (1) when no characters have yet been written -to standard output; or (2) when the last character written to standard -output is \verb/\n/; or (3) when the last write operation on standard -output was not a \verb\print\ statement. (In some cases it may be -functional to write an empty string to standard output for this -reason.) -\index{output} -\indexii{writing}{values} - -A \verb/"\n"/ character is written at the end, unless the \verb\print\ -statement ends with a comma. This is the only action if the statement -contains just the keyword \verb\print\. -\indexii{trailing}{comma} -\indexii{newline}{suppression} - -Standard output is defined as the file object named \verb\stdout\ -in the built-in module \verb\sys\. If no such object exists, -or if it is not a writable file, a \verb\RuntimeError\ exception is raised. -(The original implementation attempts to write to the system's original -standard output instead, but this is not safe, and should be fixed.) -\indexii{standard}{output} -\bimodindex{sys} -\ttindex{stdout} -\exindex{RuntimeError} - -\section{The {\tt return} statement} -\stindex{return} - -\begin{verbatim} -return_stmt: "return" [condition_list] -\end{verbatim} - -\verb\return\ may only occur syntactically nested in a function -definition, not within a nested class definition. -\indexii{function}{definition} -\indexii{class}{definition} - -If a condition list is present, it is evaluated, else \verb\None\ -is substituted. - -\verb\return\ leaves the current function call with the condition -list (or \verb\None\) as return value. - -When \verb\return\ passes control out of a \verb\try\ statement -with a \verb\finally\ clause, that finally clause is executed -before really leaving the function. -\kwindex{finally} - -\section{The {\tt raise} statement} -\stindex{raise} - -\begin{verbatim} -raise_stmt: "raise" condition ["," condition] -\end{verbatim} - -\verb\raise\ evaluates its first condition, which must yield -a string object. If there is a second condition, this is evaluated, -else \verb\None\ is substituted. -\index{exception} -\indexii{raising}{exception} - -It then raises the exception identified by the first object, -with the second one (or \verb\None\) as its parameter. - -\section{The {\tt break} statement} -\stindex{break} - -\begin{verbatim} -break_stmt: "break" -\end{verbatim} - -\verb\break\ may only occur syntactically nested in a \verb\for\ -or \verb\while\ loop, not nested in a function or class definition. -\stindex{for} -\stindex{while} -\indexii{loop}{statement} - -It terminates the neares enclosing loop, skipping the optional -\verb\else\ clause if the loop has one. -\kwindex{else} - -If a \verb\for\ loop is terminated by \verb\break\, the loop control -target keeps its current value. -\indexii{loop control}{target} - -When \verb\break\ passes control out of a \verb\try\ statement -with a \verb\finally\ clause, that finally clause is executed -before really leaving the loop. -\kwindex{finally} - -\section{The {\tt continue} statement} -\stindex{continue} - -\begin{verbatim} -continue_stmt: "continue" -\end{verbatim} - -\verb\continue\ may only occur syntactically nested in a \verb\for\ or -\verb\while\ loop, not nested in a function or class definition, and -not nested in the \verb\try\ clause of a \verb\try\ statement with a -\verb\finally\ clause (it may occur nested in a \verb\except\ or -\verb\finally\ clause of a \verb\try\ statement though). -\stindex{for} -\stindex{while} -\indexii{loop}{statement} -\kwindex{finally} - -It continues with the next cycle of the nearest enclosing loop. - -\section{The {\tt import} statement} \label{import} -\stindex{import} - -\begin{verbatim} -import_stmt: "import" identifier ("," identifier)* - | "from" identifier "import" identifier ("," identifier)* - | "from" identifier "import" "*" -\end{verbatim} - -Import statements are executed in two steps: (1) find a module, and -initialize it if necessary; (2) define a name or names in the local -name space (of the scope where the \verb\import\ statement occurs). -The first form (without \verb\from\) repeats these steps for each -identifier in the list, the \verb\from\ form performs them once, with -the first identifier specifying the module name. -\indexii{importing}{module} -\indexii{name}{binding} -\kwindex{from} - -The system maintains a table of modules that have been initialized, -indexed by module name. (The current implementation makes this table -accessible as \verb\sys.modules\.) When a module name is found in -this table, step (1) is finished. If not, a search for a module -definition is started. This first looks for a built-in module -definition, and if no built-in module if the given name is found, it -searches a user-specified list of directories for a file whose name is -the module name with extension \verb\".py"\. (The current -implementation uses the list of strings \verb\sys.path\ as the search -path; it is initialized from the shell environment variable -\verb\$PYTHONPATH\, with an installation-dependent default.) -\ttindex{modules} -\ttindex{sys.modules} -\indexii{module}{name} -\indexii{built-in}{module} -\indexii{user-defined}{module} -\bimodindex{sys} -\ttindex{path} -\ttindex{sys.path} -\indexii{filename}{extension} - -If a built-in module is found, its built-in initialization code is -executed and step (1) is finished. If no matching file is found, -\verb\ImportError\ is raised. If a file is found, it is parsed, -yielding an executable code block. If a syntax error occurs, -\verb\SyntaxError\ is raised. Otherwise, an empty module of the given -name is created and inserted in the module table, and then the code -block is executed in the context of this module. Exceptions during -this execution terminate step (1). -\indexii{module}{initialization} -\exindex{SyntaxError} -\exindex{ImportError} -\index{code block} - -When step (1) finishes without raising an exception, step (2) can -begin. - -The first form of \verb\import\ statement binds the module name in the -local name space to the module object, and then goes on to import the -next identifier, if any. The \verb\from\ from does not bind the -module name: it goes through the list of identifiers, looks each one -of them up in the module found in step (1), and binds the name in the -local name space to the object thus found. If a name is not found, -\verb\ImportError\ is raised. If the list of identifiers is replaced -by a star (\verb\*\), all names defined in the module are bound, -except those beginning with an underscore(\verb\_\). -\indexii{name}{binding} -\exindex{ImportError} - -Names bound by import statements may not occur in \verb\global\ -statements in the same scope. -\stindex{global} - -The \verb\from\ form with \verb\*\ may only occur in a module scope. -\kwindex{from} -\ttindex{from ... import *} - -(The current implementation does not enforce the latter two -restrictions, but programs should not abuse this freedom, as future -implementations may enforce them or silently change the meaning of the -program.) - -\section{The {\tt global} statement} \label{global} -\stindex{global} - -\begin{verbatim} -global_stmt: "global" identifier ("," identifier)* -\end{verbatim} - -The \verb\global\ statement is a declaration which holds for the -entire current scope. It means that the listed identifiers are to be -interpreted as globals. While {\em using} global names is automatic -if they are not defined in the local scope, {\em assigning} to global -names would be impossible without \verb\global\. -\indexiii{global}{name}{binding} - -Names listed in a \verb\global\ statement must not be used in the same -scope before that \verb\global\ statement is executed. - -Names listed in a \verb\global\ statement must not be defined as formal -parameters or in a \verb\for\ loop control target, \verb\class\ -definition, function definition, or \verb\import\ statement. - -(The current implementation does not enforce the latter two -restrictions, but programs should not abuse this freedom, as future -implementations may enforce them or silently change the meaning of the -program.) - -\section{The {\tt access} statement} \label{access} -\stindex{access} - -\begin{verbatim} -access_stmt: "access" ... -\end{verbatim} - -This statement will be used in the future to control access to -instance and class variables. Currently its syntax and effects are -undefined; however the keyword \verb\access\ is a reserved word for -the parser. - -\section{The {\tt exec} statement} \label{exec} -\stindex{exec} - -\begin{verbatim} -exec_stmt: "exec" expression ["in" expression ["," expression]] -\end{verbatim} - -This statement supports dynamic execution of Python code. The first -expression should evaluate to either a string, an open file object, or -a code object. If it is a string, the string is parsed as a suite of -Python statements which is then executed (unless a syntax error -occurs). If it is an open file, the file is parsed until EOF and -executed. If it is a code object, it is simply executed. - -In all cases, if the optional parts are omitted, the code is executed -in the current scope. If only the first expression after \verb\in\ is -specified, it should be a dictionary, which will be used for both the -global and the local variables. If two expressions are given, both -must be dictionaries and they are used for the global and local -variables, respectively. - -Note: dynamic evaluation of expressions is supported by the built-in -function \verb\eval\. - diff --git a/Doc/ref/ref7.tex b/Doc/ref/ref7.tex deleted file mode 100644 index 670eec0a5e..0000000000 --- a/Doc/ref/ref7.tex +++ /dev/null @@ -1,364 +0,0 @@ -\chapter{Compound statements} -\indexii{compound}{statement} - -Compound statements contain (groups of) other statements; they affect -or control the execution of those other statements in some way. In -general, compound statements span multiple lines, although in simple -incarnations a whole compound statement may be contained in one line. - -The \verb\if\, \verb\while\ and \verb\for\ statements implement -traditional control flow constructs. \verb\try\ specifies exception -handlers and/or cleanup code for a group of statements. Function and -class definitions are also syntactically compound statements. - -Compound statements consist of one or more `clauses'. A clause -consists of a header and a `suite'. The clause headers of a -particular compound statement are all at the same indentation level. -Each clause header begins with a uniquely identifying keyword and ends -with a colon. A suite is a group of statements controlled by a -clause. A suite can be one or more semicolon-separated simple -statements on the same line as the header, following the header's -colon, or it can be one or more indented statements on subsequent -lines. Only the latter form of suite can contain nested compound -statements; the following is illegal, mostly because it wouldn't be -clear to which \verb\if\ clause a following \verb\else\ clause would -belong: -\index{clause} -\index{suite} - -\begin{verbatim} -if test1: if test2: print x -\end{verbatim} - -Also note that the semicolon binds tighter than the colon in this -context, so that in the following example, either all or none of the -\verb\print\ statements are executed: - -\begin{verbatim} -if x < y < z: print x; print y; print z -\end{verbatim} - -Summarizing: - -\begin{verbatim} -compound_stmt: if_stmt | while_stmt | for_stmt - | try_stmt | funcdef | classdef -suite: stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT -statement: stmt_list NEWLINE | compound_stmt -stmt_list: simple_stmt (";" simple_stmt)* [";"] -\end{verbatim} - -Note that statements always end in a \verb\NEWLINE\ possibly followed -by a \verb\DEDENT\. -\index{NEWLINE token} -\index{DEDENT token} - -Also note that optional continuation clauses always begin with a -keyword that cannot start a statement, thus there are no ambiguities -(the `dangling \verb\else\' problem is solved in Python by requiring -nested \verb\if\ statements to be indented). -\indexii{dangling}{else} - -The formatting of the grammar rules in the following sections places -each clause on a separate line for clarity. - -\section{The {\tt if} statement} -\stindex{if} - -The \verb\if\ statement is used for conditional execution: - -\begin{verbatim} -if_stmt: "if" condition ":" suite - ("elif" condition ":" suite)* - ["else" ":" suite] -\end{verbatim} - -It selects exactly one of the suites by evaluating the conditions one -by one until one is found to be true (see section \ref{Booleans} for -the definition of true and false); then that suite is executed (and no -other part of the \verb\if\ statement is executed or evaluated). If -all conditions are false, the suite of the \verb\else\ clause, if -present, is executed. -\kwindex{elif} -\kwindex{else} - -\section{The {\tt while} statement} -\stindex{while} -\indexii{loop}{statement} - -The \verb\while\ statement is used for repeated execution as long as a -condition is true: - -\begin{verbatim} -while_stmt: "while" condition ":" suite - ["else" ":" suite] -\end{verbatim} - -This repeatedly tests the condition and, if it is true, executes the -first suite; if the condition is false (which may be the first time it -is tested) the suite of the \verb\else\ clause, if present, is -executed and the loop terminates. -\kwindex{else} - -A \verb\break\ statement executed in the first suite terminates the -loop without executing the \verb\else\ clause's suite. A -\verb\continue\ statement executed in the first suite skips the rest -of the suite and goes back to testing the condition. -\stindex{break} -\stindex{continue} - -\section{The {\tt for} statement} -\stindex{for} -\indexii{loop}{statement} - -The \verb\for\ statement is used to iterate over the elements of a -sequence (string, tuple or list): -\obindex{sequence} - -\begin{verbatim} -for_stmt: "for" target_list "in" condition_list ":" suite - ["else" ":" suite] -\end{verbatim} - -The condition list is evaluated once; it should yield a sequence. The -suite is then executed once for each item in the sequence, in the -order of ascending indices. Each item in turn is assigned to the -target list using the standard rules for assignments, and then the -suite is executed. When the items are exhausted (which is immediately -when the sequence is empty), the suite in the \verb\else\ clause, if -present, is executed, and the loop terminates. -\kwindex{in} -\kwindex{else} -\indexii{target}{list} - -A \verb\break\ statement executed in the first suite terminates the -loop without executing the \verb\else\ clause's suite. A -\verb\continue\ statement executed in the first suite skips the rest -of the suite and continues with the next item, or with the \verb\else\ -clause if there was no next item. -\stindex{break} -\stindex{continue} - -The suite may assign to the variable(s) in the target list; this does -not affect the next item assigned to it. - -The target list is not deleted when the loop is finished, but if the -sequence is empty, it will not have been assigned to at all by the -loop. - -Hint: the built-in function \verb\range()\ returns a sequence of -integers suitable to emulate the effect of Pascal's \verb\for i := a -to b do\; e.g. \verb\range(3)\ returns the list \verb\[0, 1, 2]\. -\bifuncindex{range} -\index{Pascal} - -{\bf Warning:} There is a subtlety when the sequence is being modified -by the loop (this can only occur for mutable sequences, i.e. lists). -An internal counter is used to keep track of which item is used next, -and this is incremented on each iteration. When this counter has -reached the length of the sequence the loop terminates. This means that -if the suite deletes the current (or a previous) item from the -sequence, the next item will be skipped (since it gets the index of -the current item which has already been treated). Likewise, if the -suite inserts an item in the sequence before the current item, the -current item will be treated again the next time through the loop. -This can lead to nasty bugs that can be avoided by making a temporary -copy using a slice of the whole sequence, e.g. -\index{loop!over mutable sequence} -\index{mutable sequence!loop over} - -\begin{verbatim} -for x in a[:]: - if x < 0: a.remove(x) -\end{verbatim} - -\section{The {\tt try} statement} \label{try} -\stindex{try} - -The \verb\try\ statement specifies exception handlers and/or cleanup -code for a group of statements: - -\begin{verbatim} -try_stmt: try_exc_stmt | try_fin_stmt -try_exc_stmt: "try" ":" suite - ("except" [condition ["," target]] ":" suite)+ -try_fin_stmt: "try" ":" suite - "finally" ":" suite -\end{verbatim} - -There are two forms of \verb\try\ statement: \verb\try...except\ and -\verb\try...finally\. These forms cannot be mixed. - -The \verb\try...except\ form specifies one or more exception handlers -(the \verb\except\ clauses). When no exception occurs in the -\verb\try\ clause, no exception handler is executed. When an -exception occurs in the \verb\try\ suite, a search for an exception -handler is started. This inspects the except clauses in turn until -one is found that matches the exception. A condition-less except -clause, if present, must be last; it matches any exception. For an -except clause with a condition, that condition is evaluated, and the -clause matches the exception if the resulting object is ``compatible'' -with the exception. An object is compatible with an exception if it -is either the object that identifies the exception or it is a tuple -containing an item that is compatible with the exception. Note that -the object identities must match, i.e. it must be the same object, not -just an object with the same value. -\kwindex{except} - -If no except clause matches the exception, the search for an exception -handler continues in the surrounding code and on the invocation stack. - -If the evaluation of a condition in the header of an except clause -raises an exception, the original search for a handler is cancelled -and a search starts for the new exception in the surrounding code and -on the call stack (it is treated as if the entire \verb\try\ statement -raised the exception). - -When a matching except clause is found, the exception's parameter is -assigned to the target specified in that except clause, if present, -and the except clause's suite is executed. When the end of this suite -is reached, execution continues normally after the entire try -statement. (This means that if two nested handlers exist for the same -exception, and the exception occurs in the try clause of the inner -handler, the outer handler will not handle the exception.) - -Before an except clause's suite is executed, details about the -exception are assigned to three variables in the \verb\sys\ module: -\verb\sys.exc_type\ receives the object identifying the exception; -\verb\sys.exc_value\ receives the exception's parameter; -\verb\sys.exc_traceback\ receives a traceback object (see section -\ref{traceback}) identifying the point in the program where the -exception occurred. -\bimodindex{sys} -\ttindex{exc_type} -\ttindex{exc_value} -\ttindex{exc_traceback} -\obindex{traceback} - -The \verb\try...finally\ form specifies a `cleanup' handler. The -\verb\try\ clause is executed. When no exception occurs, the -\verb\finally\ clause is executed. When an exception occurs in the -\verb\try\ clause, the exception is temporarily saved, the -\verb\finally\ clause is executed, and then the saved exception is -re-raised. If the \verb\finally\ clause raises another exception or -executes a \verb\return\, \verb\break\ or \verb\continue\ statement, -the saved exception is lost. -\kwindex{finally} - -When a \verb\return\ or \verb\break\ statement is executed in the -\verb\try\ suite of a \verb\try...finally\ statement, the -\verb\finally\ clause is also executed `on the way out'. A -\verb\continue\ statement is illegal in the \verb\try\ clause. (The -reason is a problem with the current implementation --- this -restriction may be lifted in the future). -\stindex{return} -\stindex{break} -\stindex{continue} - -\section{Function definitions} \label{function} -\indexii{function}{definition} - -A function definition defines a user-defined function object (see -section \ref{types}): -\obindex{user-defined function} -\obindex{function} - -\begin{verbatim} -funcdef: "def" funcname "(" [parameter_list] ")" ":" suite -parameter_list: (parameter ",")* ("*" identifier | parameter [","]) -sublist: parameter ("," parameter)* [","] -parameter: identifier | "(" sublist ")" -funcname: identifier -\end{verbatim} - -A function definition is an executable statement. Its execution binds -the function name in the current local name space to a function object -(a wrapper around the executable code for the function). This -function object contains a reference to the current global name space -as the global name space to be used when the function is called. -\indexii{function}{name} -\indexii{name}{binding} - -The function definition does not execute the function body; this gets -executed only when the function is called. - -Function call semantics are described in section \ref{calls}. When a -user-defined function is called, the arguments (a.k.a. actual -parameters) are bound to the (formal) parameters, as follows: -\indexii{function}{call} -\indexiii{user-defined}{function}{call} -\index{parameter} -\index{argument} -\indexii{parameter}{formal} -\indexii{parameter}{actual} - -It is also possible to create anonymous functions (functions not bound -to a name), for immediate use in expressions. This uses lambda forms, -described in section \ref{lambda}. - -\begin{itemize} - -\item -If there are no formal parameters, there must be no arguments. - -\item -If the formal parameter list does not end in a star followed by an -identifier, there must be exactly as many arguments as there are -parameters in the formal parameter list (at the top level); the -arguments are assigned to the formal parameters one by one. Note that -the presence or absence of a trailing comma at the top level in either -the formal or the actual parameter list makes no difference. The -assignment to a formal parameter is performed as if the parameter -occurs on the left hand side of an assignment statement whose right -hand side's value is that of the argument. - -\item -If the formal parameter list ends in a star followed by an identifier, -preceded by zero or more comma-followed parameters, there must be at -least as many arguments as there are parameters preceding the star. -Call this number {\em N}. The first {\em N} arguments are assigned to -the corresponding formal parameters in the way descibed above. A -tuple containing the remaining arguments, if any, is then assigned to -the identifier following the star. This variable will always be a -tuple: if there are no extra arguments, its value is \verb\()\, if -there is just one extra argument, it is a singleton tuple. -\indexii{variable length}{parameter list} - -\end{itemize} - -Note that the `variable length parameter list' feature only works at -the top level of the parameter list; individual parameters use a model -corresponding more closely to that of ordinary assignment. While the -latter model is generally preferable, because of the greater type -safety it offers (wrong-sized tuples aren't silently mistreated), -variable length parameter lists are a sufficiently accepted practice -in most programming languages that a compromise has been worked out. -(And anyway, assignment has no equivalent for empty argument lists.) - -\section{Class definitions} \label{class} -\indexii{class}{definition} - -A class definition defines a class object (see section \ref{types}): -\obindex{class} - -\begin{verbatim} -classdef: "class" classname [inheritance] ":" suite -inheritance: "(" [condition_list] ")" -classname: identifier -\end{verbatim} - -A class definition is an executable statement. It first evaluates the -inheritance list, if present. Each item in the inheritance list -should evaluate to a class object. The class's suite is then executed -in a new execution frame (see section \ref{execframes}), using a newly -created local name space and the original global name space. -(Usually, the suite contains only function definitions.) When the -class's suite finishes execution, its execution frame is discarded but -its local name space is saved. A class object is then created using -the inheritance list for the base classes and the saved local name -space for the attribute dictionary. The class name is bound to this -class object in the original local name space. -\index{inheritance} -\indexii{class}{name} -\indexii{name}{binding} -\indexii{execution}{frame} diff --git a/Doc/ref/ref8.tex b/Doc/ref/ref8.tex deleted file mode 100644 index aeb65bf721..0000000000 --- a/Doc/ref/ref8.tex +++ /dev/null @@ -1,104 +0,0 @@ -\chapter{Top-level components} - -The Python interpreter can get its input from a number of sources: -from a script passed to it as standard input or as program argument, -typed in interactively, from a module source file, etc. This chapter -gives the syntax used in these cases. -\index{interpreter} - -\section{Complete Python programs} -\index{program} - -While a language specification need not prescribe how the language -interpreter is invoked, it is useful to have a notion of a complete -Python program. A complete Python program is executed in a minimally -initialized environment: all built-in and standard modules are -available, but none have been initialized, except for \verb\sys\ -(various system services), \verb\__builtin__\ (built-in functions, -exceptions and \verb\None\) and \verb\__main__\. The latter is used -to provide the local and global name space for execution of the -complete program. -\bimodindex{sys} -\bimodindex{__main__} -\bimodindex{__builtin__} - -The syntax for a complete Python program is that for file input, -described in the next section. - -The interpreter may also be invoked in interactive mode; in this case, -it does not read and execute a complete program but reads and executes -one statement (possibly compound) at a time. The initial environment -is identical to that of a complete program; each statement is executed -in the name space of \verb\__main__\. -\index{interactive mode} - -Under {\UNIX}, a complete program can be passed to the interpreter in -three forms: with the {\bf -c} {\it string} command line option, as a -file passed as the first command line argument, or as standard input. -If the file or standard input is a tty device, the interpreter enters -interactive mode; otherwise, it executes the file as a complete -program. -\index{UNIX} -\index{command line} -\index{standard input} - -\section{File input} - -All input read from non-interactive files has the same form: - -\begin{verbatim} -file_input: (NEWLINE | statement)* -\end{verbatim} - -This syntax is used in the following situations: - -\begin{itemize} - -\item when parsing a complete Python program (from a file or from a string); - -\item when parsing a module; - -\item when parsing a string passed to the \verb\exec\ statement; - -\end{itemize} - -\section{Interactive input} - -Input in interactive mode is parsed using the following grammar: - -\begin{verbatim} -interactive_input: [stmt_list] NEWLINE | compound_stmt NEWLINE -\end{verbatim} - -Note that a (top-level) compound statement must be followed by a blank -line in interactive mode; this is needed to help the parser detect the -end of the input. - -\section{Expression input} -\index{input} - -There are two forms of expression input. Both ignore leading -whitespace. - -The string argument to \verb\eval()\ must have the following form: -\bifuncindex{eval} - -\begin{verbatim} -eval_input: condition_list NEWLINE* -\end{verbatim} - -The input line read by \verb\input()\ must have the following form: -\bifuncindex{input} - -\begin{verbatim} -input_input: condition_list NEWLINE -\end{verbatim} - -Note: to read `raw' input line without interpretation, you can use the -built-in function \verb\raw_input()\ or the \verb\readline()\ method -of file objects. -\obindex{file} -\index{input!raw} -\index{raw input} -\bifuncindex{raw_index} -\ttindex{readline} diff --git a/Doc/ref1.tex b/Doc/ref1.tex deleted file mode 100644 index b373e3666c..0000000000 --- a/Doc/ref1.tex +++ /dev/null @@ -1,81 +0,0 @@ -\chapter{Introduction} - -This reference manual describes the Python programming language. -It is not intended as a tutorial. - -While I am trying to be as precise as possible, I chose to use English -rather than formal specifications for everything except syntax and -lexical analysis. This should make the document better understandable -to the average reader, but will leave room for ambiguities. -Consequently, if you were coming from Mars and tried to re-implement -Python from this document alone, you might have to guess things and in -fact you would probably end up implementing quite a different language. -On the other hand, if you are using -Python and wonder what the precise rules about a particular area of -the language are, you should definitely be able to find them here. - -It is dangerous to add too many implementation details to a language -reference document --- the implementation may change, and other -implementations of the same language may work differently. On the -other hand, there is currently only one Python implementation, and -its particular quirks are sometimes worth being mentioned, especially -where the implementation imposes additional limitations. Therefore, -you'll find short ``implementation notes'' sprinkled throughout the -text. - -Every Python implementation comes with a number of built-in and -standard modules. These are not documented here, but in the separate -{\em Python Library Reference} document. A few built-in modules are -mentioned when they interact in a significant way with the language -definition. - -\section{Notation} - -The descriptions of lexical analysis and syntax use a modified BNF -grammar notation. This uses the following style of definition: -\index{BNF} -\index{grammar} -\index{syntax} -\index{notation} - -\begin{verbatim} -name: lc_letter (lc_letter | "_")* -lc_letter: "a"..."z" -\end{verbatim} - -The first line says that a \verb\name\ is an \verb\lc_letter\ followed by -a sequence of zero or more \verb\lc_letter\s and underscores. An -\verb\lc_letter\ in turn is any of the single characters `a' through `z'. -(This rule is actually adhered to for the names defined in lexical and -grammar rules in this document.) - -Each rule begins with a name (which is the name defined by the rule) -and a colon. A vertical bar (\verb\|\) is used to separate -alternatives; it is the least binding operator in this notation. A -star (\verb\*\) means zero or more repetitions of the preceding item; -likewise, a plus (\verb\+\) means one or more repetitions, and a -phrase enclosed in square brackets (\verb\[ ]\) means zero or one -occurrences (in other words, the enclosed phrase is optional). The -\verb\*\ and \verb\+\ operators bind as tightly as possible; -parentheses are used for grouping. Literal strings are enclosed in -double quotes. White space is only meaningful to separate tokens. -Rules are normally contained on a single line; rules with many -alternatives may be formatted alternatively with each line after the -first beginning with a vertical bar. - -In lexical definitions (as the example above), two more conventions -are used: Two literal characters separated by three dots mean a choice -of any single character in the given (inclusive) range of ASCII -characters. A phrase between angular brackets (\verb\<...>\) gives an -informal description of the symbol defined; e.g. this could be used -to describe the notion of `control character' if needed. -\index{lexical definitions} -\index{ASCII} - -Even though the notation used is almost the same, there is a big -difference between the meaning of lexical and syntactic definitions: -a lexical definition operates on the individual characters of the -input source, while a syntax definition operates on the stream of -tokens generated by the lexical analysis. All uses of BNF in the next -chapter (``Lexical Analysis'') are lexical definitions; uses in -subsequent chapters are syntactic definitions. diff --git a/Doc/ref2.tex b/Doc/ref2.tex deleted file mode 100644 index 250bd2e771..0000000000 --- a/Doc/ref2.tex +++ /dev/null @@ -1,349 +0,0 @@ -\chapter{Lexical analysis} - -A Python program is read by a {\em parser}. Input to the parser is a -stream of {\em tokens}, generated by the {\em lexical analyzer}. This -chapter describes how the lexical analyzer breaks a file into tokens. -\index{lexical analysis} -\index{parser} -\index{token} - -\section{Line structure} - -A Python program is divided in a number of logical lines. The end of -a logical line is represented by the token NEWLINE. Statements cannot -cross logical line boundaries except where NEWLINE is allowed by the -syntax (e.g. between statements in compound statements). -\index{line structure} -\index{logical line} -\index{NEWLINE token} - -\subsection{Comments} - -A comment starts with a hash character (\verb\#\) that is not part of -a string literal, and ends at the end of the physical line. A comment -always signifies the end of the logical line. Comments are ignored by -the syntax. -\index{comment} -\index{logical line} -\index{physical line} -\index{hash character} - -\subsection{Line joining} - -Two or more physical lines may be joined into logical lines using -backslash characters (\verb/\/), as follows: when a physical line ends -in a backslash that is not part of a string literal or comment, it is -joined with the following forming a single logical line, deleting the -backslash and the following end-of-line character. For example: -\index{physical line} -\index{line joining} -\index{backslash character} -% -\begin{verbatim} -month_names = ['Januari', 'Februari', 'Maart', \ - 'April', 'Mei', 'Juni', \ - 'Juli', 'Augustus', 'September', \ - 'Oktober', 'November', 'December'] -\end{verbatim} - -\subsection{Blank lines} - -A logical line that contains only spaces, tabs, and possibly a -comment, is ignored (i.e., no NEWLINE token is generated), except that -during interactive input of statements, an entirely blank logical line -terminates a multi-line statement. -\index{blank line} - -\subsection{Indentation} - -Leading whitespace (spaces and tabs) at the beginning of a logical -line is used to compute the indentation level of the line, which in -turn is used to determine the grouping of statements. -\index{indentation} -\index{whitespace} -\index{leading whitespace} -\index{space} -\index{tab} -\index{grouping} -\index{statement grouping} - -First, tabs are replaced (from left to right) by one to eight spaces -such that the total number of characters up to there is a multiple of -eight (this is intended to be the same rule as used by {\UNIX}). The -total number of spaces preceding the first non-blank character then -determines the line's indentation. Indentation cannot be split over -multiple physical lines using backslashes. - -The indentation levels of consecutive lines are used to generate -INDENT and DEDENT tokens, using a stack, as follows. -\index{INDENT token} -\index{DEDENT token} - -Before the first line of the file is read, a single zero is pushed on -the stack; this will never be popped off again. The numbers pushed on -the stack will always be strictly increasing from bottom to top. At -the beginning of each logical line, the line's indentation level is -compared to the top of the stack. If it is equal, nothing happens. -If it is larger, it is pushed on the stack, and one INDENT token is -generated. If it is smaller, it {\em must} be one of the numbers -occurring on the stack; all numbers on the stack that are larger are -popped off, and for each number popped off a DEDENT token is -generated. At the end of the file, a DEDENT token is generated for -each number remaining on the stack that is larger than zero. - -Here is an example of a correctly (though confusingly) indented piece -of Python code: - -\begin{verbatim} -def perm(l): - # Compute the list of all permutations of l - - if len(l) <= 1: - return [l] - r = [] - for i in range(len(l)): - s = l[:i] + l[i+1:] - p = perm(s) - for x in p: - r.append(l[i:i+1] + x) - return r -\end{verbatim} - -The following example shows various indentation errors: - -\begin{verbatim} - def perm(l): # error: first line indented - for i in range(len(l)): # error: not indented - s = l[:i] + l[i+1:] - p = perm(l[:i] + l[i+1:]) # error: unexpected indent - for x in p: - r.append(l[i:i+1] + x) - return r # error: inconsistent dedent -\end{verbatim} - -(Actually, the first three errors are detected by the parser; only the -last error is found by the lexical analyzer --- the indentation of -\verb\return r\ does not match a level popped off the stack.) - -\section{Other tokens} - -Besides NEWLINE, INDENT and DEDENT, the following categories of tokens -exist: identifiers, keywords, literals, operators, and delimiters. -Spaces and tabs are not tokens, but serve to delimit tokens. Where -ambiguity exists, a token comprises the longest possible string that -forms a legal token, when read from left to right. - -\section{Identifiers} - -Identifiers (also referred to as names) are described by the following -lexical definitions: -\index{identifier} -\index{name} - -\begin{verbatim} -identifier: (letter|"_") (letter|digit|"_")* -letter: lowercase | uppercase -lowercase: "a"..."z" -uppercase: "A"..."Z" -digit: "0"..."9" -\end{verbatim} - -Identifiers are unlimited in length. Case is significant. - -\subsection{Keywords} - -The following identifiers are used as reserved words, or {\em -keywords} of the language, and cannot be used as ordinary -identifiers. They must be spelled exactly as written here: -\index{keyword} -\index{reserved word} - -\begin{verbatim} -and del for in print -break elif from is raise -class else global not return -continue except if or try -def finally import pass while -\end{verbatim} - -% # This Python program sorts and formats the above table -% import string -% l = [] -% try: -% while 1: -% l = l + string.split(raw_input()) -% except EOFError: -% pass -% l.sort() -% for i in range((len(l)+4)/5): -% for j in range(i, len(l), 5): -% print string.ljust(l[j], 10), -% print - -\section{Literals} \label{literals} - -Literals are notations for constant values of some built-in types. -\index{literal} -\index{constant} - -\subsection{String literals} - -String literals are described by the following lexical definitions: -\index{string literal} - -\begin{verbatim} -stringliteral: "'" stringitem* "'" -stringitem: stringchar | escapeseq -stringchar: -escapeseq: "'" -\end{verbatim} -\index{ASCII} - -String literals cannot span physical line boundaries. Escape -sequences in strings are actually interpreted according to rules -similar to those used by Standard C. The recognized escape sequences -are: -\index{physical line} -\index{escape sequence} -\index{Standard C} -\index{C} - -\begin{center} -\begin{tabular}{|l|l|} -\hline -\verb/\\/ & Backslash (\verb/\/) \\ -\verb/\'/ & Single quote (\verb/'/) \\ -\verb/\a/ & ASCII Bell (BEL) \\ -\verb/\b/ & ASCII Backspace (BS) \\ -%\verb/\E/ & ASCII Escape (ESC) \\ -\verb/\f/ & ASCII Formfeed (FF) \\ -\verb/\n/ & ASCII Linefeed (LF) \\ -\verb/\r/ & ASCII Carriage Return (CR) \\ -\verb/\t/ & ASCII Horizontal Tab (TAB) \\ -\verb/\v/ & ASCII Vertical Tab (VT) \\ -\verb/\/{\em ooo} & ASCII character with octal value {\em ooo} \\ -\verb/\x/{\em xx...} & ASCII character with hex value {\em xx...} \\ -\hline -\end{tabular} -\end{center} -\index{ASCII} - -In strict compatibility with Standard C, up to three octal digits are -accepted, but an unlimited number of hex digits is taken to be part of -the hex escape (and then the lower 8 bits of the resulting hex number -are used in all current implementations...). - -All unrecognized escape sequences are left in the string unchanged, -i.e., {\em the backslash is left in the string.} (This behavior is -useful when debugging: if an escape sequence is mistyped, the -resulting output is more easily recognized as broken. It also helps a -great deal for string literals used as regular expressions or -otherwise passed to other modules that do their own escape handling.) -\index{unrecognized escape sequence} - -\subsection{Numeric literals} - -There are three types of numeric literals: plain integers, long -integers, and floating point numbers. -\index{number} -\index{numeric literal} -\index{integer literal} -\index{plain integer literal} -\index{long integer literal} -\index{floating point literal} -\index{hexadecimal literal} -\index{octal literal} -\index{decimal literal} - -Integer and long integer literals are described by the following -lexical definitions: - -\begin{verbatim} -longinteger: integer ("l"|"L") -integer: decimalinteger | octinteger | hexinteger -decimalinteger: nonzerodigit digit* | "0" -octinteger: "0" octdigit+ -hexinteger: "0" ("x"|"X") hexdigit+ - -nonzerodigit: "1"..."9" -octdigit: "0"..."7" -hexdigit: digit|"a"..."f"|"A"..."F" -\end{verbatim} - -Although both lower case `l' and upper case `L' are allowed as suffix -for long integers, it is strongly recommended to always use `L', since -the letter `l' looks too much like the digit `1'. - -Plain integer decimal literals must be at most $2^{31} - 1$ (i.e., the -largest positive integer, assuming 32-bit arithmetic). Plain octal and -hexadecimal literals may be as large as $2^{32} - 1$, but values -larger than $2^{31} - 1$ are converted to a negative value by -subtracting $2^{32}$. There is no limit for long integer literals. - -Some examples of plain and long integer literals: - -\begin{verbatim} -7 2147483647 0177 0x80000000 -3L 79228162514264337593543950336L 0377L 0x100000000L -\end{verbatim} - -Floating point literals are described by the following lexical -definitions: - -\begin{verbatim} -floatnumber: pointfloat | exponentfloat -pointfloat: [intpart] fraction | intpart "." -exponentfloat: (intpart | pointfloat) exponent -intpart: digit+ -fraction: "." digit+ -exponent: ("e"|"E") ["+"|"-"] digit+ -\end{verbatim} - -The allowed range of floating point literals is -implementation-dependent. - -Some examples of floating point literals: - -\begin{verbatim} -3.14 10. .001 1e100 3.14e-10 -\end{verbatim} - -Note that numeric literals do not include a sign; a phrase like -\verb\-1\ is actually an expression composed of the operator -\verb\-\ and the literal \verb\1\. - -\section{Operators} - -The following tokens are operators: -\index{operators} - -\begin{verbatim} -+ - * / % -<< >> & | ^ ~ -< == > <= <> != >= -\end{verbatim} - -The comparison operators \verb\<>\ and \verb\!=\ are alternate -spellings of the same operator. - -\section{Delimiters} - -The following tokens serve as delimiters or otherwise have a special -meaning: -\index{delimiters} - -\begin{verbatim} -( ) [ ] { } -; , : . ` = -\end{verbatim} - -The following printing ASCII characters are not used in Python. Their -occurrence outside string literals and comments is an unconditional -error: -\index{ASCII} - -\begin{verbatim} -@ $ " ? -\end{verbatim} - -They may be used by future versions of the language though! diff --git a/Doc/ref3.tex b/Doc/ref3.tex deleted file mode 100644 index 41ce23426e..0000000000 --- a/Doc/ref3.tex +++ /dev/null @@ -1,760 +0,0 @@ -\chapter{Data model} - -\section{Objects, values and types} - -{\em Objects} are Python's abstraction for data. All data in a Python -program is represented by objects or by relations between objects. -(In a sense, and in conformance to Von Neumann's model of a -``stored program computer'', code is also represented by objects.) -\index{object} -\index{data} - -Every object has an identity, a type and a value. An object's {\em -identity} never changes once it has been created; you may think of it -as the object's address in memory. An object's {\em type} is also -unchangeable. It determines the operations that an object supports -(e.g. ``does it have a length?'') and also defines the possible -values for objects of that type. The {\em value} of some objects can -change. Objects whose value can change are said to be {\em mutable}; -objects whose value is unchangeable once they are created are called -{\em immutable}. The type determines an object's (im)mutability. -\index{identity of an object} -\index{value of an object} -\index{type of an object} -\index{mutable object} -\index{immutable object} - -Objects are never explicitly destroyed; however, when they become -unreachable they may be garbage-collected. An implementation is -allowed to delay garbage collection or omit it altogether --- it is a -matter of implementation quality how garbage collection is -implemented, as long as no objects are collected that are still -reachable. (Implementation note: the current implementation uses a -reference-counting scheme which collects most objects as soon as they -become unreachable, but never collects garbage containing circular -references.) -\index{garbage collection} -\index{reference counting} -\index{unreachable object} - -Note that the use of the implementation's tracing or debugging -facilities may keep objects alive that would normally be collectable. - -Some objects contain references to ``external'' resources such as open -files or windows. It is understood that these resources are freed -when the object is garbage-collected, but since garbage collection is -not guaranteed to happen, such objects also provide an explicit way to -release the external resource, usually a \verb\close\ method. -Programs are strongly recommended to always explicitly close such -objects. - -Some objects contain references to other objects; these are called -{\em containers}. Examples of containers are tuples, lists and -dictionaries. The references are part of a container's value. In -most cases, when we talk about the value of a container, we imply the -values, not the identities of the contained objects; however, when we -talk about the (im)mutability of a container, only the identities of -the immediately contained objects are implied. (So, if an immutable -container contains a reference to a mutable object, its value changes -if that mutable object is changed.) -\index{container} - -Types affect almost all aspects of objects' lives. Even the meaning -of object identity is affected in some sense: for immutable types, -operations that compute new values may actually return a reference to -any existing object with the same type and value, while for mutable -objects this is not allowed. E.g. after - -\begin{verbatim} -a = 1; b = 1; c = []; d = [] -\end{verbatim} - -\verb\a\ and \verb\b\ may or may not refer to the same object with the -value one, depending on the implementation, but \verb\c\ and \verb\d\ -are guaranteed to refer to two different, unique, newly created empty -lists. - -\section{The standard type hierarchy} \label{types} - -Below is a list of the types that are built into Python. Extension -modules written in C can define additional types. Future versions of -Python may add types to the type hierarchy (e.g. rational or complex -numbers, efficiently stored arrays of integers, etc.). -\index{type} -\indexii{data}{type} -\indexii{type}{hierarchy} -\indexii{extension}{module} -\index{C} - -Some of the type descriptions below contain a paragraph listing -`special attributes'. These are attributes that provide access to the -implementation and are not intended for general use. Their definition -may change in the future. There are also some `generic' special -attributes, not listed with the individual objects: \verb\__methods__\ -is a list of the method names of a built-in object, if it has any; -\verb\__members__\ is a list of the data attribute names of a built-in -object, if it has any. -\index{attribute} -\indexii{special}{attribute} -\indexiii{generic}{special}{attribute} -\ttindex{__methods__} -\ttindex{__members__} - -\begin{description} - -\item[None] -This type has a single value. There is a single object with this value. -This object is accessed through the built-in name \verb\None\. -It is returned from functions that don't explicitly return an object. -\ttindex{None} -\obindex{None@{\tt None}} - -\item[Numbers] -These are created by numeric literals and returned as results by -arithmetic operators and arithmetic built-in functions. Numeric -objects are immutable; once created their value never changes. Python -numbers are of course strongly related to mathematical numbers, but -subject to the limitations of numerical representation in computers. -\obindex{number} -\obindex{numeric} - -Python distinguishes between integers and floating point numbers: - -\begin{description} -\item[Integers] -These represent elements from the mathematical set of whole numbers. -\obindex{integer} - -There are two types of integers: - -\begin{description} - -\item[Plain integers] -These represent numbers in the range $-2^{31}$ through $2^{31}-1$. -(The range may be larger on machines with a larger natural word -size, but not smaller.) -When the result of an operation falls outside this range, the -exception \verb\OverflowError\ is raised. -For the purpose of shift and mask operations, integers are assumed to -have a binary, 2's complement notation using 32 or more bits, and -hiding no bits from the user (i.e., all $2^{32}$ different bit -patterns correspond to different values). -\obindex{plain integer} - -\item[Long integers] -These represent numbers in an unlimited range, subject to available -(virtual) memory only. For the purpose of shift and mask operations, -a binary representation is assumed, and negative numbers are -represented in a variant of 2's complement which gives the illusion of -an infinite string of sign bits extending to the left. -\obindex{long integer} - -\end{description} % Integers - -The rules for integer representation are intended to give the most -meaningful interpretation of shift and mask operations involving -negative integers and the least surprises when switching between the -plain and long integer domains. For any operation except left shift, -if it yields a result in the plain integer domain without causing -overflow, it will yield the same result in the long integer domain or -when using mixed operands. -\indexii{integer}{representation} - -\item[Floating point numbers] -These represent machine-level double precision floating point numbers. -You are at the mercy of the underlying machine architecture and -C implementation for the accepted range and handling of overflow. -\obindex{floating point} -\indexii{floating point}{number} -\index{C} - -\end{description} % Numbers - -\item[Sequences] -These represent finite ordered sets indexed by natural numbers. -The built-in function \verb\len()\ returns the number of elements -of a sequence. When this number is $n$, the index set contains -the numbers $0, 1, \ldots, n-1$. Element \verb\i\ of sequence -\verb\a\ is selected by \verb\a[i]\. -\obindex{seqence} -\bifuncindex{len} -\index{index operation} -\index{item selection} -\index{subscription} - -Sequences also support slicing: \verb\a[i:j]\ selects all elements -with index $k$ such that $i <= k < j$. When used as an expression, -a slice is a sequence of the same type --- this implies that the -index set is renumbered so that it starts at 0 again. -\index{slicing} - -Sequences are distinguished according to their mutability: - -\begin{description} -% -\item[Immutable sequences] -An object of an immutable sequence type cannot change once it is -created. (If the object contains references to other objects, -these other objects may be mutable and may be changed; however -the collection of objects directly referenced by an immutable object -cannot change.) -\obindex{immutable sequence} -\obindex{immutable} - -The following types are immutable sequences: - -\begin{description} - -\item[Strings] -The elements of a string are characters. There is no separate -character type; a character is represented by a string of one element. -Characters represent (at least) 8-bit bytes. The built-in -functions \verb\chr()\ and \verb\ord()\ convert between characters -and nonnegative integers representing the byte values. -Bytes with the values 0-127 represent the corresponding ASCII values. -The string data type is also used to represent arrays of bytes, e.g. -to hold data read from a file. -\obindex{string} -\index{character} -\index{byte} -\index{ASCII} -\bifuncindex{chr} -\bifuncindex{ord} - -(On systems whose native character set is not ASCII, strings may use -EBCDIC in their internal representation, provided the functions -\verb\chr()\ and \verb\ord()\ implement a mapping between ASCII and -EBCDIC, and string comparison preserves the ASCII order. -Or perhaps someone can propose a better rule?) -\index{ASCII} -\index{EBCDIC} -\index{character set} -\indexii{string}{comparison} -\bifuncindex{chr} -\bifuncindex{ord} - -\item[Tuples] -The elements of a tuple are arbitrary Python objects. -Tuples of two or more elements are formed by comma-separated lists -of expressions. A tuple of one element (a `singleton') can be formed -by affixing a comma to an expression (an expression by itself does -not create a tuple, since parentheses must be usable for grouping of -expressions). An empty tuple can be formed by enclosing `nothing' in -parentheses. -\obindex{tuple} -\indexii{singleton}{tuple} -\indexii{empty}{tuple} - -\end{description} % Immutable sequences - -\item[Mutable sequences] -Mutable sequences can be changed after they are created. The -subscription and slicing notations can be used as the target of -assignment and \verb\del\ (delete) statements. -\obindex{mutable sequece} -\obindex{mutable} -\indexii{assignment}{statement} -\index{delete} -\stindex{del} -\index{subscription} -\index{slicing} - -There is currently a single mutable sequence type: - -\begin{description} - -\item[Lists] -The elements of a list are arbitrary Python objects. Lists are formed -by placing a comma-separated list of expressions in square brackets. -(Note that there are no special cases needed to form lists of length 0 -or 1.) -\obindex{list} - -\end{description} % Mutable sequences - -\end{description} % Sequences - -\item[Mapping types] -These represent finite sets of objects indexed by arbitrary index sets. -The subscript notation \verb\a[k]\ selects the element indexed -by \verb\k\ from the mapping \verb\a\; this can be used in -expressions and as the target of assignments or \verb\del\ statements. -The built-in function \verb\len()\ returns the number of elements -in a mapping. -\bifuncindex{len} -\index{subscription} -\obindex{mapping} - -There is currently a single mapping type: - -\begin{description} - -\item[Dictionaries] -These represent finite sets of objects indexed by almost arbitrary -values. The only types of values not acceptable as keys are values -containing lists or dictionaries or other mutable types that are -compared by value rather than by object identity --- the reason being -that the implementation requires that a key's hash value be constant. -Numeric types used for keys obey the normal rules for numeric -comparison: if two numbers compare equal (e.g. 1 and 1.0) then they -can be used interchangeably to index the same dictionary entry. - -Dictionaries are mutable; they are created by the \verb\{...}\ -notation (see section \ref{dict}). -\obindex{dictionary} -\obindex{mutable} - -\end{description} % Mapping types - -\item[Callable types] -These are the types to which the function call (invocation) operation, -written as \verb\function(argument, argument, ...)\, can be applied: -\indexii{function}{call} -\index{invocation} -\indexii{function}{argument} -\obindex{callable} - -\begin{description} - -\item[User-defined functions] -A user-defined function object is created by a function definition -(see section \ref{function}). It should be called with an argument -list containing the same number of items as the function's formal -parameter list. -\indexii{user-defined}{function} -\obindex{function} -\obindex{user-defined function} - -Special read-only attributes: \verb\func_code\ is the code object -representing the compiled function body, and \verb\func_globals\ is (a -reference to) the dictionary that holds the function's global -variables --- it implements the global name space of the module in -which the function was defined. -\ttindex{func_code} -\ttindex{func_globals} -\indexii{global}{name space} - -\item[User-defined methods] -A user-defined method (a.k.a. {\em object closure}) is a pair of a -class instance object and a user-defined function. It should be -called with an argument list containing one item less than the number -of items in the function's formal parameter list. When called, the -class instance becomes the first argument, and the call arguments are -shifted one to the right. -\obindex{method} -\obindex{user-defined method} -\indexii{user-defined}{method} -\index{object closure} - -Special read-only attributes: \verb\im_self\ is the class instance -object, \verb\im_func\ is the function object. -\ttindex{im_func} -\ttindex{im_self} - -\item[Built-in functions] -A built-in function object is a wrapper around a C function. Examples -of built-in functions are \verb\len\ and \verb\math.sin\. There -are no special attributes. The number and type of the arguments are -determined by the C function. -\obindex{built-in function} -\obindex{function} -\index{C} - -\item[Built-in methods] -This is really a different disguise of a built-in function, this time -containing an object passed to the C function as an implicit extra -argument. An example of a built-in method is \verb\list.append\ if -\verb\list\ is a list object. -\obindex{built-in method} -\obindex{method} -\indexii{built-in}{method} - -\item[Classes] -Class objects are described below. When a class object is called as a -parameterless function, a new class instance (also described below) is -created and returned. The class's initialization function is not -called --- this is the responsibility of the caller. It is illegal to -call a class object with one or more arguments. -\obindex{class} -\obindex{class instance} -\obindex{instance} -\indexii{class object}{call} - -\end{description} - -\item[Modules] -Modules are imported by the \verb\import\ statement (see section -\ref{import}). A module object is a container for a module's name -space, which is a dictionary (the same dictionary as referenced by the -\verb\func_globals\ attribute of functions defined in the module). -Module attribute references are translated to lookups in this -dictionary. A module object does not contain the code object used to -initialize the module (since it isn't needed once the initialization -is done). -\stindex{import} -\obindex{module} - -Attribute assignment update the module's name space dictionary. - -Special read-only attributes: \verb\__dict__\ yields the module's name -space as a dictionary object; \verb\__name__\ yields the module's name -as a string object. -\ttindex{__dict__} -\ttindex{__name__} -\indexii{module}{name space} - -\item[Classes] -Class objects are created by class definitions (see section -\ref{class}). A class is a container for a dictionary containing the -class's name space. Class attribute references are translated to -lookups in this dictionary. When an attribute name is not found -there, the attribute search continues in the base classes. The search -is depth-first, left-to-right in the order of their occurrence in the -base class list. -\obindex{class} -\obindex{class instance} -\obindex{instance} -\indexii{class object}{call} -\index{container} -\obindex{dictionary} -\indexii{class}{attribute} - -Class attribute assignments update the class's dictionary, never the -dictionary of a base class. -\indexiii{class}{attribute}{assignment} - -A class can be called as a parameterless function to yield a class -instance (see above). -\indexii{class object}{call} - -Special read-only attributes: \verb\__dict__\ yields the dictionary -containing the class's name space; \verb\__bases__\ yields a tuple -(possibly empty or a singleton) containing the base classes, in the -order of their occurrence in the base class list. -\ttindex{__dict__} -\ttindex{__bases__} - -\item[Class instances] -A class instance is created by calling a class object as a -parameterless function. A class instance has a dictionary in which -attribute references are searched. When an attribute is not found -there, and the instance's class has an attribute by that name, and -that class attribute is a user-defined function (and in no other -cases), the instance attribute reference yields a user-defined method -object (see above) constructed from the instance and the function. -\obindex{class instance} -\obindex{instance} -\indexii{class}{instance} -\indexii{class instance}{attribute} - -Attribute assignments update the instance's dictionary. -\indexiii{class instance}{attribute}{assignment} - -Class instances can pretend to be numbers, sequences, or mappings if -they have methods with certain special names. These are described in -section \ref{specialnames}. -\obindex{number} -\obindex{sequence} -\obindex{mapping} - -Special read-only attributes: \verb\__dict__\ yields the attribute -dictionary; \verb\__class__\ yields the instance's class. -\ttindex{__dict__} -\ttindex{__class__} - -\item[Files] -A file object represents an open file. (It is a wrapper around a C -{\tt stdio} file pointer.) File objects are created by the -\verb\open()\ built-in function, and also by \verb\posix.popen()\ and -the \verb\makefile\ method of socket objects. \verb\sys.stdin\, -\verb\sys.stdout\ and \verb\sys.stderr\ are file objects corresponding -the the interpreter's standard input, output and error streams. -See the Python Library Reference for methods of file objects and other -details. -\obindex{file} -\index{C} -\index{stdio} -\bifuncindex{open} -\bifuncindex{popen} -\bifuncindex{makefile} -\ttindex{stdin} -\ttindex{stdout} -\ttindex{stderr} -\ttindex{sys.stdin} -\ttindex{sys.stdout} -\ttindex{sys.stderr} - -\item[Internal types] -A few types used internally by the interpreter are exposed to the user. -Their definition may change with future versions of the interpreter, -but they are mentioned here for completeness. -\index{internal type} - -\begin{description} - -\item[Code objects] -Code objects represent executable code. The difference between a code -object and a function object is that the function object contains an -explicit reference to the function's context (the module in which it -was defined) which a code object contains no context. There is no way -to execute a bare code object. -\obindex{code} - -Special read-only attributes: \verb\co_code\ is a string representing -the sequence of instructions; \verb\co_consts\ is a list of literals -used by the code; \verb\co_names\ is a list of names (strings) used by -the code; \verb\co_filename\ is the filename from which the code was -compiled. (To find out the line numbers, you would have to decode the -instructions; the standard library module \verb\dis\ contains an -example of how to do this.) -\ttindex{co_code} -\ttindex{co_consts} -\ttindex{co_names} -\ttindex{co_filename} - -\item[Frame objects] -Frame objects represent execution frames. They may occur in traceback -objects (see below). -\obindex{frame} - -Special read-only attributes: \verb\f_back\ is to the previous -stack frame (towards the caller), or \verb\None\ if this is the bottom -stack frame; \verb\f_code\ is the code object being executed in this -frame; \verb\f_globals\ is the dictionary used to look up global -variables; \verb\f_locals\ is used for local variables; -\verb\f_lineno\ gives the line number and \verb\f_lasti\ gives the -precise instruction (this is an index into the instruction string of -the code object). -\ttindex{f_back} -\ttindex{f_code} -\ttindex{f_globals} -\ttindex{f_locals} -\ttindex{f_lineno} -\ttindex{f_lasti} - -\item[Traceback objects] \label{traceback} -Traceback objects represent a stack trace of an exception. A -traceback object is created when an exception occurs. When the search -for an exception handler unwinds the execution stack, at each unwound -level a traceback object is inserted in front of the current -traceback. When an exception handler is entered -(see also section \ref{try}), the stack trace is -made available to the program as \verb\sys.exc_traceback\. When the -program contains no suitable handler, the stack trace is written -(nicely formatted) to the standard error stream; if the interpreter is -interactive, it is also made available to the user as -\verb\sys.last_traceback\. -\obindex{traceback} -\indexii{stack}{trace} -\indexii{exception}{handler} -\indexii{execution}{stack} -\ttindex{exc_traceback} -\ttindex{last_traceback} -\ttindex{sys.exc_traceback} -\ttindex{sys.last_traceback} - -Special read-only attributes: \verb\tb_next\ is the next level in the -stack trace (towards the frame where the exception occurred), or -\verb\None\ if there is no next level; \verb\tb_frame\ points to the -execution frame of the current level; \verb\tb_lineno\ gives the line -number where the exception occurred; \verb\tb_lasti\ indicates the -precise instruction. The line number and last instruction in the -traceback may differ from the line number of its frame object if the -exception occurred in a \verb\try\ statement with no matching -\verb\except\ clause or with a \verb\finally\ clause. -\ttindex{tb_next} -\ttindex{tb_frame} -\ttindex{tb_lineno} -\ttindex{tb_lasti} -\stindex{try} - -\end{description} % Internal types - -\end{description} % Types - - -\section{Special method names} \label{specialnames} - -A class can implement certain operations that are invoked by special -syntax (such as subscription or arithmetic operations) by defining -methods with special names. For instance, if a class defines a -method named \verb\__getitem__\, and \verb\x\ is an instance of this -class, then \verb\x[i]\ is equivalent to \verb\x.__getitem__(i)\. -(The reverse is not true --- if \verb\x\ is a list object, -\verb\x.__getitem__(i)\ is not equivalent to \verb\x[i]\.) - -Except for \verb\__repr__\, \verb\__str__\ and \verb\__cmp__\, -attempts to execute an -operation raise an exception when no appropriate method is defined. -For \verb\__repr__\ and \verb\__cmp__\, the traditional -interpretations are used in this case. -For \verb\__str__\, the \verb\__repr__\ method is used. - - -\subsection{Special methods for any type} - -\begin{description} - -\item[\tt __init__(self, args...)] -Called when the instance is created. The arguments are those passed -to the class constructor expression. If a base class has an -\code{__init__} method the derived class's \code{__init__} method must -explicitly call it to ensure proper initialization of the base class -part of the instance. - -\item[\tt __del__(self)] -Called when the instance is about to be destroyed. If a base class -has an \code{__del__} method the derived class's \code{__del__} method -must explicitly call it to ensure proper deletion of the base class -part of the instance. Note that it is possible for the \code{__del__} -method to postpone destruction of the instance by creating a new -reference to it. It may then be called at a later time when this new -reference is deleted. Also note that it is not guaranteed that -\code{__del__} methods are called for objects that still exist when -the interpreter exits. - -\item[\tt __repr__(self)] -Called by the \verb\repr()\ built-in function and by conversions -(reverse quotes) to compute the string representation of an object. - -\item[\tt __str__(self)] -Called by the \verb\str()\ built-in function and by the \verb\print\ -statement compute the string representation of an object. - -\item[\tt __cmp__(self, other)] -Called by all comparison operations. Should return -1 if -\verb\self < other\, 0 if \verb\self == other\, +1 if -\verb\self > other\. If no \code{__cmp__} operation is defined, class -instances are compared by object identity (``address''). -(Implementation note: due to limitations in the interpreter, -exceptions raised by comparisons are ignored, and the objects will be -considered equal in this case.) - -\item[\tt __hash__(self)] -Called by dictionary operations and by the built-in function -\code{hash()}. Should return a 32-bit integer usable as a hash value -for dictionary operations. The only required property is that objects -which compare equal have the same hash value; it is advised to somehow -mix together (e.g. using exclusing or) the hash values for the -components of the object that also play a part in comparison of -objects. If a class does not define a \code{__cmp__} method it should -not define a \code{__hash__} operation either; if it defines -\code{__cmp__} but not \code{__hash__} its instances will not be -usable as dictionary keys. If a class defines mutable objects and -implements a \code{__cmp__} method it should not implement -\code{__hash__}, since the dictionary implementation assumes that a -key's hash value is a constant. -\obindex{dictionary} - -\end{description} - - -\subsection{Special methods for sequence and mapping types} - -\begin{description} - -\item[\tt __len__(self)] -Called to implement the built-in function \verb\len()\. Should return -the length of the object, an integer \verb\>=\ 0. Also, an object -whose \verb\__len__()\ method returns 0 is considered to be false in a -Boolean context. - -\item[\tt __getitem__(self, key)] -Called to implement evaluation of \verb\self[key]\. Note that the -special interpretation of negative keys (if the class wishes to -emulate a sequence type) is up to the \verb\__getitem__\ method. - -\item[\tt __setitem__(self, key, value)] -Called to implement assignment to \verb\self[key]\. Same note as for -\verb\__getitem__\. - -\item[\tt __delitem__(self, key)] -Called to implement deletion of \verb\self[key]\. Same note as for -\verb\__getitem__\. - -\end{description} - - -\subsection{Special methods for sequence types} - -\begin{description} - -\item[\tt __getslice__(self, i, j)] -Called to implement evaluation of \verb\self[i:j]\. Note that missing -\verb\i\ or \verb\j\ are replaced by 0 or \verb\len(self)\, -respectively, and \verb\len(self)\ has been added (once) to originally -negative \verb\i\ or \verb\j\ by the time this function is called -(unlike for \verb\__getitem__\). - -\item[\tt __setslice__(self, i, j, sequence)] -Called to implement assignment to \verb\self[i:j]\. Same notes as for -\verb\__getslice__\. - -\item[\tt __delslice__(self, i, j)] -Called to implement deletion of \verb\self[i:j]\. Same notes as for -\verb\__getslice__\. - -\end{description} - - -\subsection{Special methods for numeric types} - -\begin{description} - -\item[\tt __add__(self, other)]\itemjoin -\item[\tt __sub__(self, other)]\itemjoin -\item[\tt __mul__(self, other)]\itemjoin -\item[\tt __div__(self, other)]\itemjoin -\item[\tt __mod__(self, other)]\itemjoin -\item[\tt __divmod__(self, other)]\itemjoin -\item[\tt __pow__(self, other)]\itemjoin -\item[\tt __lshift__(self, other)]\itemjoin -\item[\tt __rshift__(self, other)]\itemjoin -\item[\tt __and__(self, other)]\itemjoin -\item[\tt __xor__(self, other)]\itemjoin -\item[\tt __or__(self, other)]\itembreak -Called to implement the binary arithmetic operations (\verb\+\, -\verb\-\, \verb\*\, \verb\/\, \verb\%\, \verb\divmod()\, \verb\pow()\, -\verb\<<\, \verb\>>\, \verb\&\, \verb\^\, \verb\|\). - -\item[\tt __neg__(self)]\itemjoin -\item[\tt __pos__(self)]\itemjoin -\item[\tt __abs__(self)]\itemjoin -\item[\tt __invert__(self)]\itembreak -Called to implement the unary arithmetic operations (\verb\-\, \verb\+\, -\verb\abs()\ and \verb\~\). - -\item[\tt __nonzero__(self)] -Called to implement boolean testing; should return 0 or 1. An -alternative name for this method is \verb\__len__\. - -\item[\tt __coerce__(self, other)] -Called to implement ``mixed-mode'' numeric arithmetic. Should either -return a tuple containing self and other converted to a common numeric -type, or None if no way of conversion is known. When the common type -would be the type of other, it is sufficient to return None, since the -interpreter will also ask the other object to attempt a coercion (but -sometimes, if the implementation of the other type cannot be changed, -it is useful to do the conversion to the other type here). - -Note that this method is not called to coerce the arguments to \verb\+\ -and \verb\*\, because these are also used to implement sequence -concatenation and repetition, respectively. Also note that, for the -same reason, in \verb\n*x\, where \verb\n\ is a built-in number and -\verb\x\ is an instance, a call to \verb\x.__mul__(n)\ is made.% -\footnote{The interpreter should really distinguish between -user-defined classes implementing sequences, mappings or numbers, but -currently it doesn't --- hence this strange exception.} - -\item[\tt __int__(self)]\itemjoin -\item[\tt __long__(self)]\itemjoin -\item[\tt __float__(self)]\itembreak -Called to implement the built-in functions \verb\int()\, \verb\long()\ -and \verb\float()\. Should return a value of the appropriate type. - -\item[\tt __oct__(self)]\itemjoin -\item[\tt __hex__(self)]\itembreak -Called to implement the built-in functions \verb\oct()\ and -\verb\hex()\. Should return a string value. - -\end{description} diff --git a/Doc/ref4.tex b/Doc/ref4.tex deleted file mode 100644 index 62db120989..0000000000 --- a/Doc/ref4.tex +++ /dev/null @@ -1,148 +0,0 @@ -\chapter{Execution model} -\index{execution model} - -\section{Code blocks, execution frames, and name spaces} \label{execframes} -\index{code block} -\indexii{execution}{frame} -\index{name space} - -A {\em code block} is a piece of Python program text that can be -executed as a unit, such as a module, a class definition or a function -body. Some code blocks (like modules) are executed only once, others -(like function bodies) may be executed many times. Code block may -textually contain other code blocks. Code blocks may invoke other -code blocks (that may or may not be textually contained in them) as -part of their execution, e.g. by invoking (calling) a function. -\index{code block} -\indexii{code}{block} - -The following are code blocks: A module is a code block. A function -body is a code block. A class definition is a code block. Each -command typed interactively is a separate code block; a script file is -a code block. The string argument passed to the built-in function -\verb\eval\ and to the \verb\exec\ statement are code blocks. -And finally, the -expression read and evaluated by the built-in function \verb\input\ is -a code block. - -A code block is executed in an execution frame. An {\em execution -frame} contains some administrative information (used for debugging), -determines where and how execution continues after the code block's -execution has completed, and (perhaps most importantly) defines two -name spaces, the local and the global name space, that affect -execution of the code block. -\indexii{execution}{frame} - -A {\em name space} is a mapping from names (identifiers) to objects. -A particular name space may be referenced by more than one execution -frame, and from other places as well. Adding a name to a name space -is called {\em binding} a name (to an object); changing the mapping of -a name is called {\em rebinding}; removing a name is {\em unbinding}. -Name spaces are functionally equivalent to dictionaries. -\index{name space} -\indexii{binding}{name} -\indexii{rebinding}{name} -\indexii{unbinding}{name} - -The {\em local name space} of an execution frame determines the default -place where names are defined and searched. The {\em global name -space} determines the place where names listed in \verb\global\ -statements are defined and searched, and where names that are not -explicitly bound in the current code block are searched. -\indexii{local}{name space} -\indexii{global}{name space} -\stindex{global} - -Whether a name is local or global in a code block is determined by -static inspection of the source text for the code block: in the -absence of \verb\global\ statements, a name that is bound anywhere in -the code block is local in the entire code block; all other names are -considered global. The \verb\global\ statement forces global -interpretation of selected names throughout the code block. The -following constructs bind names: formal parameters, \verb\import\ -statements, class and function definitions (these bind the class or -function name), and targets that are identifiers if occurring in an -assignment, \verb\for\ loop header, or \verb\except\ clause header. -(A target occurring in a \verb\del\ statement does not bind a name.) - -When a global name is not found in the global name space, it is -searched in the list of ``built-in'' names (which is actually the -global name space of the module \verb\__builtin__\). When a name is not -found at all, the \verb\NameError\ exception is raised. - -The following table lists the meaning of the local and global name -space for various types of code blocks. The name space for a -particular module is automatically created when the module is first -referenced. - -\begin{center} -\begin{tabular}{|l|l|l|l|} -\hline -Code block type & Global name space & Local name space & Notes \\ -\hline -Module & n.s. for this module & same as global & \\ -Script & n.s. for \verb\__main__\ & same as global & \\ -Interactive command & n.s. for \verb\__main__\ & same as global & \\ -Class definition & global n.s. of containing block & new n.s. & \\ -Function body & global n.s. of containing block & new n.s. & \\ -String passed to \verb\exec\ or \verb\eval\ - & global n.s. of caller & local n.s. of caller & (1) \\ -File read by \verb\execfile\ - & global n.s. of caller & local n.s. of caller & (1) \\ -Expression read by \verb\input\ - & global n.s. of caller & local n.s. of caller & \\ -\hline -\end{tabular} -\end{center} - -Notes: - -\begin{description} - -\item[n.s.] means {\em name space} - -\item[(1)] The global and local name space for these functions can be -overridden with optional extra arguments. - -\end{description} - -\section{Exceptions} - -Exceptions are a means of breaking out of the normal flow of control -of a code block in order to handle errors or other exceptional -conditions. An exception is {\em raised} at the point where the error -is detected; it may be {\em handled} by the surrounding code block or -by any code block that directly or indirectly invoked the code block -where the error occurred. -\index{exception} -\index{raise an exception} -\index{handle an exception} -\index{exception handler} -\index{errors} -\index{error handling} - -The Python interpreter raises an exception when it detects an run-time -error (such as division by zero). A Python program can also -explicitly raise an exception with the \verb\raise\ statement. -Exception handlers are specified with the \verb\try...except\ -statement. - -Python uses the ``termination'' model of error handling: an exception -handler can find out what happened and continue execution at an outer -level, but it cannot repair the cause of the error and retry the -failing operation (except by re-entering the the offending piece of -code from the top). - -When an exception is not handled at all, the interpreter terminates -execution of the program, or returns to its interactive main loop. - -Exceptions are identified by string objects. Two different string -objects with the same value identify different exceptions. - -When an exception is raised, an object (maybe \verb\None\) is passed -as the exception's ``parameter''; this object does not affect the -selection of an exception handler, but is passed to the selected -exception handler as additional information. - -See also the description of the \verb\try\ and \verb\raise\ -statements. diff --git a/Doc/ref5.tex b/Doc/ref5.tex deleted file mode 100644 index 55f523fb17..0000000000 --- a/Doc/ref5.tex +++ /dev/null @@ -1,689 +0,0 @@ -\chapter{Expressions and conditions} -\index{expression} -\index{condition} - -{\bf Note:} In this and the following chapters, extended BNF notation -will be used to describe syntax, not lexical analysis. -\index{BNF} - -This chapter explains the meaning of the elements of expressions and -conditions. Conditions are a superset of expressions, and a condition -may be used wherever an expression is required by enclosing it in -parentheses. The only places where expressions are used in the syntax -instead of conditions is in expression statements and on the -right-hand side of assignment statements; this catches some nasty bugs -like accidentally writing \verb\x == 1\ instead of \verb\x = 1\. -\indexii{assignment}{statement} - -The comma plays several roles in Python's syntax. It is usually an -operator with a lower precedence than all others, but occasionally -serves other purposes as well; e.g. it separates function arguments, -is used in list and dictionary constructors, and has special semantics -in \verb\print\ statements. -\index{comma} - -When (one alternative of) a syntax rule has the form - -\begin{verbatim} -name: othername -\end{verbatim} - -and no semantics are given, the semantics of this form of \verb\name\ -are the same as for \verb\othername\. -\index{syntax} - -\section{Arithmetic conversions} -\indexii{arithmetic}{conversion} - -When a description of an arithmetic operator below uses the phrase -``the numeric arguments are converted to a common type'', -this both means that if either argument is not a number, a -\verb\TypeError\ exception is raised, and that otherwise -the following conversions are applied: -\exindex{TypeError} -\indexii{floating point}{number} -\indexii{long}{integer} -\indexii{plain}{integer} - -\begin{itemize} -\item first, if either argument is a floating point number, - the other is converted to floating point; -\item else, if either argument is a long integer, - the other is converted to long integer; -\item otherwise, both must be plain integers and no conversion - is necessary. -\end{itemize} - -\section{Atoms} -\index{atom} - -Atoms are the most basic elements of expressions. Forms enclosed in -reverse quotes or in parentheses, brackets or braces are also -categorized syntactically as atoms. The syntax for atoms is: - -\begin{verbatim} -atom: identifier | literal | enclosure -enclosure: parenth_form | list_display | dict_display | string_conversion -\end{verbatim} - -\subsection{Identifiers (Names)} -\index{name} -\index{identifier} - -An identifier occurring as an atom is a reference to a local, global -or built-in name binding. If a name can be assigned to anywhere in a -code block, and is not mentioned in a \verb\global\ statement in that -code block, it refers to a local name throughout that code block. -Otherwise, it refers to a global name if one exists, else to a -built-in name. -\indexii{name}{binding} -\index{code block} -\stindex{global} -\indexii{built-in}{name} -\indexii{global}{name} - -When the name is bound to an object, evaluation of the atom yields -that object. When a name is not bound, an attempt to evaluate it -raises a \verb\NameError\ exception. -\exindex{NameError} - -\subsection{Literals} -\index{literal} - -Python knows string and numeric literals: - -\begin{verbatim} -literal: stringliteral | integer | longinteger | floatnumber -\end{verbatim} - -Evaluation of a literal yields an object of the given type (string, -integer, long integer, floating point number) with the given value. -The value may be approximated in the case of floating point literals. -See section \ref{literals} for details. - -All literals correspond to immutable data types, and hence the -object's identity is less important than its value. Multiple -evaluations of literals with the same value (either the same -occurrence in the program text or a different occurrence) may obtain -the same object or a different object with the same value. -\indexiii{immutable}{data}{type} - -(In the original implementation, all literals in the same code block -with the same type and value yield the same object.) - -\subsection{Parenthesized forms} -\index{parenthesized form} - -A parenthesized form is an optional condition list enclosed in -parentheses: - -\begin{verbatim} -parenth_form: "(" [condition_list] ")" -\end{verbatim} - -A parenthesized condition list yields whatever that condition list -yields. - -An empty pair of parentheses yields an empty tuple object. Since -tuples are immutable, the rules for literals apply here. -\indexii{empty}{tuple} - -(Note that tuples are not formed by the parentheses, but rather by use -of the comma operator. The exception is the empty tuple, for which -parentheses {\em are} required --- allowing unparenthesized ``nothing'' -in expressions would causes ambiguities and allow common typos to -pass uncaught.) -\index{comma} -\indexii{tuple}{display} - -\subsection{List displays} -\indexii{list}{display} - -A list display is a possibly empty series of conditions enclosed in -square brackets: - -\begin{verbatim} -list_display: "[" [condition_list] "]" -\end{verbatim} - -A list display yields a new list object. -\obindex{list} - -If it has no condition list, the list object has no items. Otherwise, -the elements of the condition list are evaluated from left to right -and inserted in the list object in that order. -\indexii{empty}{list} - -\subsection{Dictionary displays} \label{dict} -\indexii{dictionary}{display} - -A dictionary display is a possibly empty series of key/datum pairs -enclosed in curly braces: -\index{key} -\index{datum} -\index{key/datum pair} - -\begin{verbatim} -dict_display: "{" [key_datum_list] "}" -key_datum_list: key_datum ("," key_datum)* [","] -key_datum: condition ":" condition -\end{verbatim} - -A dictionary display yields a new dictionary object. -\obindex{dictionary} - -The key/datum pairs are evaluated from left to right to define the -entries of the dictionary: each key object is used as a key into the -dictionary to store the corresponding datum. - -Restrictions on the types of the key values are listed earlier in -section \ref{types}. -Clashes between duplicate keys are not detected; the last -datum (textually rightmost in the display) stored for a given key -value prevails. -\exindex{TypeError} - -\subsection{String conversions} -\indexii{string}{conversion} - -A string conversion is a condition list enclosed in reverse (or -backward) quotes: - -\begin{verbatim} -string_conversion: "`" condition_list "`" -\end{verbatim} - -A string conversion evaluates the contained condition list and -converts the resulting object into a string according to rules -specific to its type. - -If the object is a string, a number, \verb\None\, or a tuple, list or -dictionary containing only objects whose type is one of these, the -resulting string is a valid Python expression which can be passed to -the built-in function \verb\eval()\ to yield an expression with the -same value (or an approximation, if floating point numbers are -involved). - -(In particular, converting a string adds quotes around it and converts -``funny'' characters to escape sequences that are safe to print.) - -It is illegal to attempt to convert recursive objects (e.g. lists or -dictionaries that contain a reference to themselves, directly or -indirectly.) -\obindex{recursive} - -\section{Primaries} \label{primaries} -\index{primary} - -Primaries represent the most tightly bound operations of the language. -Their syntax is: - -\begin{verbatim} -primary: atom | attributeref | subscription | slicing | call -\end{verbatim} - -\subsection{Attribute references} -\indexii{attribute}{reference} - -An attribute reference is a primary followed by a period and a name: - -\begin{verbatim} -attributeref: primary "." identifier -\end{verbatim} - -The primary must evaluate to an object of a type that supports -attribute references, e.g. a module or a list. This object is then -asked to produce the attribute whose name is the identifier. If this -attribute is not available, the exception \verb\AttributeError\ is -raised. Otherwise, the type and value of the object produced is -determined by the object. Multiple evaluations of the same attribute -reference may yield different objects. -\obindex{module} -\obindex{list} - -\subsection{Subscriptions} -\index{subscription} - -A subscription selects an item of a sequence (string, tuple or list) -or mapping (dictionary) object: -\obindex{sequence} -\obindex{mapping} -\obindex{string} -\obindex{tuple} -\obindex{list} -\obindex{dictionary} -\indexii{sequence}{item} - -\begin{verbatim} -subscription: primary "[" condition "]" -\end{verbatim} - -The primary must evaluate to an object of a sequence or mapping type. - -If it is a mapping, the condition must evaluate to an object whose -value is one of the keys of the mapping, and the subscription selects -the value in the mapping that corresponds to that key. - -If it is a sequence, the condition must evaluate to a plain integer. -If this value is negative, the length of the sequence is added to it -(so that, e.g. \verb\x[-1]\ selects the last item of \verb\x\.) -The resulting value must be a nonnegative integer smaller than the -number of items in the sequence, and the subscription selects the item -whose index is that value (counting from zero). - -A string's items are characters. A character is not a separate data -type but a string of exactly one character. -\index{character} -\indexii{string}{item} - -\subsection{Slicings} -\index{slicing} -\index{slice} - -A slicing (or slice) selects a range of items in a sequence (string, -tuple or list) object: -\obindex{sequence} -\obindex{string} -\obindex{tuple} -\obindex{list} - -\begin{verbatim} -slicing: primary "[" [condition] ":" [condition] "]" -\end{verbatim} - -The primary must evaluate to a sequence object. The lower and upper -bound expressions, if present, must evaluate to plain integers; -defaults are zero and the sequence's length, respectively. If either -bound is negative, the sequence's length is added to it. The slicing -now selects all items with index $k$ such that $i <= k < j$ where $i$ -and $j$ are the specified lower and upper bounds. This may be an -empty sequence. It is not an error if $i$ or $j$ lie outside the -range of valid indexes (such items don't exist so they aren't -selected). - -\subsection{Calls} \label{calls} -\index{call} - -A call calls a callable object (e.g. a function) with a possibly empty -series of arguments: -\obindex{callable} - -\begin{verbatim} -call: primary "(" [condition_list] ")" -\end{verbatim} - -The primary must evaluate to a callable object (user-defined -functions, built-in functions, methods of built-in objects, class -objects, and methods of class instances are callable). If it is a -class, the argument list must be empty; otherwise, the arguments are -evaluated. - -A call always returns some value, possibly \verb\None\, unless it -raises an exception. How this value is computed depends on the type -of the callable object. If it is: - -\begin{description} - -\item[a user-defined function:] the code block for the function is -executed, passing it the argument list. The first thing the code -block will do is bind the formal parameters to the arguments; this is -described in section \ref{function}. When the code block executes a -\verb\return\ statement, this specifies the return value of the -function call. -\indexii{function}{call} -\indexiii{user-defined}{function}{call} -\obindex{user-defined function} -\obindex{function} - -\item[a built-in function or method:] the result is up to the -interpreter; see the library reference manual for the descriptions of -built-in functions and methods. -\indexii{function}{call} -\indexii{built-in function}{call} -\indexii{method}{call} -\indexii{built-in method}{call} -\obindex{built-in method} -\obindex{built-in function} -\obindex{method} -\obindex{function} - -\item[a class object:] a new instance of that class is returned. -\obindex{class} -\indexii{class object}{call} - -\item[a class instance method:] the corresponding user-defined -function is called, with an argument list that is one longer than the -argument list of the call: the instance becomes the first argument. -\obindex{class instance} -\obindex{instance} -\indexii{instance}{call} -\indexii{class instance}{call} - -\end{description} - -\section{Unary arithmetic operations} -\indexiii{unary}{arithmetic}{operation} -\indexiii{unary}{bit-wise}{operation} - -All unary arithmetic (and bit-wise) operations have the same priority: - -\begin{verbatim} -u_expr: primary | "-" u_expr | "+" u_expr | "~" u_expr -\end{verbatim} - -The unary \verb\"-"\ (minus) operator yields the negation of its -numeric argument. -\index{negation} -\index{minus} - -The unary \verb\"+"\ (plus) operator yields its numeric argument -unchanged. -\index{plus} - -The unary \verb\"~"\ (invert) operator yields the bit-wise inversion -of its plain or long integer argument. The bit-wise inversion of -\verb\x\ is defined as \verb\-(x+1)\. -\index{inversion} - -In all three cases, if the argument does not have the proper type, -a \verb\TypeError\ exception is raised. -\exindex{TypeError} - -\section{Binary arithmetic operations} -\indexiii{binary}{arithmetic}{operation} - -The binary arithmetic operations have the conventional priority -levels. Note that some of these operations also apply to certain -non-numeric types. There is no ``power'' operator, so there are only -two levels, one for multiplicative operators and one for additive -operators: - -\begin{verbatim} -m_expr: u_expr | m_expr "*" u_expr - | m_expr "/" u_expr | m_expr "%" u_expr -a_expr: m_expr | aexpr "+" m_expr | aexpr "-" m_expr -\end{verbatim} - -The \verb\"*"\ (multiplication) operator yields the product of its -arguments. The arguments must either both be numbers, or one argument -must be a plain integer and the other must be a sequence. In the -former case, the numbers are converted to a common type and then -multiplied together. In the latter case, sequence repetition is -performed; a negative repetition factor yields an empty sequence. -\index{multiplication} - -The \verb\"/"\ (division) operator yields the quotient of its -arguments. The numeric arguments are first converted to a common -type. Plain or long integer division yields an integer of the same -type; the result is that of mathematical division with the `floor' -function applied to the result. Division by zero raises the -\verb\ZeroDivisionError\ exception. -\exindex{ZeroDivisionError} -\index{division} - -The \verb\"%"\ (modulo) operator yields the remainder from the -division of the first argument by the second. The numeric arguments -are first converted to a common type. A zero right argument raises -the \verb\ZeroDivisionError\ exception. The arguments may be floating -point numbers, e.g. \verb\3.14 % 0.7\ equals \verb\0.34\. The modulo -operator always yields a result with the same sign as its second -operand (or zero); the absolute value of the result is strictly -smaller than the second operand. -\index{modulo} - -The integer division and modulo operators are connected by the -following identity: \verb\x == (x/y)*y + (x%y)\. Integer division and -modulo are also connected with the built-in function \verb\divmod()\: -\verb\divmod(x, y) == (x/y, x%y)\. These identities don't hold for -floating point numbers; there a similar identity holds where -\verb\x/y\ is replaced by \verb\floor(x/y)\). - -The \verb\"+"\ (addition) operator yields the sum of its arguments. -The arguments must either both be numbers, or both sequences of the -same type. In the former case, the numbers are converted to a common -type and then added together. In the latter case, the sequences are -concatenated. -\index{addition} - -The \verb\"-"\ (subtraction) operator yields the difference of its -arguments. The numeric arguments are first converted to a common -type. -\index{subtraction} - -\section{Shifting operations} -\indexii{shifting}{operation} - -The shifting operations have lower priority than the arithmetic -operations: - -\begin{verbatim} -shift_expr: a_expr | shift_expr ( "<<" | ">>" ) a_expr -\end{verbatim} - -These operators accept plain or long integers as arguments. The -arguments are converted to a common type. They shift the first -argument to the left or right by the number of bits given by the -second argument. - -A right shift by $n$ bits is defined as division by $2^n$. A left -shift by $n$ bits is defined as multiplication with $2^n$; for plain -integers there is no overflow check so this drops bits and flip the -sign if the result is not less than $2^{31}$ in absolute value. - -Negative shift counts raise a \verb\ValueError\ exception. -\exindex{ValueError} - -\section{Binary bit-wise operations} -\indexiii{binary}{bit-wise}{operation} - -Each of the three bitwise operations has a different priority level: - -\begin{verbatim} -and_expr: shift_expr | and_expr "&" shift_expr -xor_expr: and_expr | xor_expr "^" and_expr -or_expr: xor_expr | or_expr "|" xor_expr -\end{verbatim} - -The \verb\"&"\ operator yields the bitwise AND of its arguments, which -must be plain or long integers. The arguments are converted to a -common type. -\indexii{bit-wise}{and} - -The \verb\"^"\ operator yields the bitwise XOR (exclusive OR) of its -arguments, which must be plain or long integers. The arguments are -converted to a common type. -\indexii{bit-wise}{xor} -\indexii{exclusive}{or} - -The \verb\"|"\ operator yields the bitwise (inclusive) OR of its -arguments, which must be plain or long integers. The arguments are -converted to a common type. -\indexii{bit-wise}{or} -\indexii{inclusive}{or} - -\section{Comparisons} -\index{comparison} - -Contrary to C, all comparison operations in Python have the same -priority, which is lower than that of any arithmetic, shifting or -bitwise operation. Also contrary to C, expressions like -\verb\a < b < c\ have the interpretation that is conventional in -mathematics: -\index{C} - -\begin{verbatim} -comparison: or_expr (comp_operator or_expr)* -comp_operator: "<"|">"|"=="|">="|"<="|"<>"|"!="|"is" ["not"]|["not"] "in" -\end{verbatim} - -Comparisons yield integer values: 1 for true, 0 for false. - -Comparisons can be chained arbitrarily, e.g. $x < y <= z$ is -equivalent to $x < y$ \verb\and\ $y <= z$, except that $y$ is -evaluated only once (but in both cases $z$ is not evaluated at all -when $x < y$ is found to be false). -\indexii{chaining}{comparisons} - -\catcode`\_=8 -Formally, $e_0 op_1 e_1 op_2 e_2 ...e_{n-1} op_n e_n$ is equivalent to -$e_0 op_1 e_1$ \verb\and\ $e_1 op_2 e_2$ \verb\and\ ... \verb\and\ -$e_{n-1} op_n e_n$, except that each expression is evaluated at most once. - -Note that $e_0 op_1 e_1 op_2 e_2$ does not imply any kind of comparison -between $e_0$ and $e_2$, e.g. $x < y > z$ is perfectly legal. -\catcode`\_=12 - -The forms \verb\<>\ and \verb\!=\ are equivalent; for consistency with -C, \verb\!=\ is preferred; where \verb\!=\ is mentioned below -\verb\<>\ is also implied. - -The operators {\tt "<", ">", "==", ">=", "<="}, and {\tt "!="} compare -the values of two objects. The objects needn't have the same type. -If both are numbers, they are coverted to a common type. Otherwise, -objects of different types {\em always} compare unequal, and are -ordered consistently but arbitrarily. - -(This unusual definition of comparison is done to simplify the -definition of operations like sorting and the \verb\in\ and \verb\not -in\ operators.) - -Comparison of objects of the same type depends on the type: - -\begin{itemize} - -\item -Numbers are compared arithmetically. - -\item -Strings are compared lexicographically using the numeric equivalents -(the result of the built-in function \verb\ord\) of their characters. - -\item -Tuples and lists are compared lexicographically using comparison of -corresponding items. - -\item -Mappings (dictionaries) are compared through lexicographic -comparison of their sorted (key, value) lists.% -\footnote{This is expensive since it requires sorting the keys first, -but about the only sensible definition. An earlier version of Python -compared dictionaries by identity only, but this caused surprises -because people expected to be able to test a dictionary for emptiness -by comparing it to {\tt \{\}}.} - -\item -Most other types compare unequal unless they are the same object; -the choice whether one object is considered smaller or larger than -another one is made arbitrarily but consistently within one -execution of a program. - -\end{itemize} - -The operators \verb\in\ and \verb\not in\ test for sequence -membership: if $y$ is a sequence, $x ~\verb\in\~ y$ is true if and -only if there exists an index $i$ such that $x = y[i]$. -$x ~\verb\not in\~ y$ yields the inverse truth value. The exception -\verb\TypeError\ is raised when $y$ is not a sequence, or when $y$ is -a string and $x$ is not a string of length one.% -\footnote{The latter restriction is sometimes a nuisance.} -\opindex{in} -\opindex{not in} -\indexii{membership}{test} -\obindex{sequence} - -The operators \verb\is\ and \verb\is not\ test for object identity: -$x ~\verb\is\~ y$ is true if and only if $x$ and $y$ are the same -object. $x ~\verb\is not\~ y$ yields the inverse truth value. -\opindex{is} -\opindex{is not} -\indexii{identity}{test} - -\section{Boolean operations} \label{Booleans} -\indexii{Boolean}{operation} - -Boolean operations have the lowest priority of all Python operations: - -\begin{verbatim} -condition: or_test | lambda_form -or_test: and_test | or_test "or" and_test -and_test: not_test | and_test "and" not_test -not_test: comparison | "not" not_test -lambda_form: "lambda" [parameter_list]: condition -\end{verbatim} - -In the context of Boolean operations, and also when conditions are -used by control flow statements, the following values are interpreted -as false: \verb\None\, numeric zero of all types, empty sequences -(strings, tuples and lists), and empty mappings (dictionaries). All -other values are interpreted as true. - -The operator \verb\not\ yields 1 if its argument is false, 0 otherwise. -\opindex{not} - -The condition $x ~\verb\and\~ y$ first evaluates $x$; if $x$ is false, -its value is returned; otherwise, $y$ is evaluated and the resulting -value is returned. -\opindex{and} - -The condition $x ~\verb\or\~ y$ first evaluates $x$; if $x$ is true, -its value is returned; otherwise, $y$ is evaluated and the resulting -value is returned. -\opindex{or} - -(Note that \verb\and\ and \verb\or\ do not restrict the value and type -they return to 0 and 1, but rather return the last evaluated argument. -This is sometimes useful, e.g. if \verb\s\ is a string that should be -replaced by a default value if it is empty, the expression -\verb\s or 'foo'\ yields the desired value. Because \verb\not\ has to -invent a value anyway, it does not bother to return a value of the -same type as its argument, so e.g. \verb\not 'foo'\ yields \verb\0\, -not \verb\''\.) - -Lambda forms (lambda expressions) have the same syntactic position as -conditions. They are a shorthand to create anonymous functions; the -expression \verb\lambda\ {\em arguments}\verb\:\ {\em condition} -yields a function object that behaves virtually identical to one -defined with \verb\def\ {\em name}\verb\(\{\em arguments}\verb\) : -return\ {\em condition}. See section \ref{function} for the syntax of -parameter lists. Note that functions created with lambda forms cannot -contain statements. -\label{lambda} -\indexii{lambda}{expression} -\indexii{lambda}{form} -\indexii{anonmymous}{function} - -\section{Expression lists and condition lists} -\indexii{expression}{list} -\indexii{condition}{list} - -\begin{verbatim} -expr_list: or_expr ("," or_expr)* [","] -cond_list: condition ("," condition)* [","] -\end{verbatim} - -The only difference between expression lists and condition lists is -the lowest priority of operators that can be used in them without -being enclosed in parentheses; condition lists allow all operators, -while expression lists don't allow comparisons and Boolean operators -(they do allow bitwise and shift operators though). - -Expression lists are used in expression statements and assignments; -condition lists are used everywhere else where a list of -comma-separated values is required. - -An expression (condition) list containing at least one comma yields a -tuple. The length of the tuple is the number of expressions -(conditions) in the list. The expressions (conditions) are evaluated -from left to right. (Conditions lists are used syntactically is a few -places where no tuple is constructed but a list of values is needed -nevertheless.) -\obindex{tuple} - -The trailing comma is required only to create a single tuple (a.k.a. a -{\em singleton}); it is optional in all other cases. A single -expression (condition) without a trailing comma doesn't create a -tuple, but rather yields the value of that expression (condition). -\indexii{trailing}{comma} - -(To create an empty tuple, use an empty pair of parentheses: -\verb\()\.) diff --git a/Doc/ref6.tex b/Doc/ref6.tex deleted file mode 100644 index 086d49bed2..0000000000 --- a/Doc/ref6.tex +++ /dev/null @@ -1,507 +0,0 @@ -\chapter{Simple statements} -\indexii{simple}{statement} - -Simple statements are comprised within a single logical line. -Several simple statements may occur on a single line separated -by semicolons. The syntax for simple statements is: - -\begin{verbatim} -simple_stmt: expression_stmt - | assignment_stmt - | pass_stmt - | del_stmt - | print_stmt - | return_stmt - | raise_stmt - | break_stmt - | continue_stmt - | import_stmt - | global_stmt - | access_stmt - | exec_stmt -\end{verbatim} - -\section{Expression statements} -\indexii{expression}{statement} - -Expression statements are used (mostly interactively) to compute and -write a value, or (usually) to call a procedure (a function that -returns no meaningful result; in Python, procedures return the value -\verb\None\): - -\begin{verbatim} -expression_stmt: expression_list -\end{verbatim} - -An expression statement evaluates the expression list (which may be a -single expression). If the value is not \verb\None\, it is converted -to a string using the rules for string conversions (expressions in -reverse quotes), and the resulting string is written to standard -output (see section \ref{print}) on a line by itself. -\indexii{expression}{list} -\ttindex{None} -\indexii{string}{conversion} -\index{output} -\indexii{standard}{output} -\indexii{writing}{values} - -(The exception for \verb\None\ is made so that procedure calls, which -are syntactically equivalent to expressions, do not cause any output. -A tuple with only \verb\None\ items is written normally.) -\indexii{procedure}{call} - -\section{Assignment statements} -\indexii{assignment}{statement} - -Assignment statements are used to (re)bind names to values and to -modify attributes or items of mutable objects: -\indexii{binding}{name} -\indexii{rebinding}{name} -\obindex{mutable} -\indexii{attribute}{assignment} - -\begin{verbatim} -assignment_stmt: (target_list "=")+ expression_list -target_list: target ("," target)* [","] -target: identifier | "(" target_list ")" | "[" target_list "]" - | attributeref | subscription | slicing -\end{verbatim} - -(See section \ref{primaries} for the syntax definitions for the last -three symbols.) - -An assignment statement evaluates the expression list (remember that -this can be a single expression or a comma-separated list, the latter -yielding a tuple) and assigns the single resulting object to each of -the target lists, from left to right. -\indexii{expression}{list} - -Assignment is defined recursively depending on the form of the target -(list). When a target is part of a mutable object (an attribute -reference, subscription or slicing), the mutable object must -ultimately perform the assignment and decide about its validity, and -may raise an exception if the assignment is unacceptable. The rules -observed by various types and the exceptions raised are given with the -definition of the object types (see section \ref{types}). -\index{target} -\indexii{target}{list} - -Assignment of an object to a target list is recursively defined as -follows. -\indexiii{target}{list}{assignment} - -\begin{itemize} -\item -If the target list is a single target: the object is assigned to that -target. - -\item -If the target list is a comma-separated list of targets: the object -must be a tuple with the same number of items as the list contains -targets, and the items are assigned, from left to right, to the -corresponding targets. - -\end{itemize} - -Assignment of an object to a single target is recursively defined as -follows. - -\begin{itemize} % nested - -\item -If the target is an identifier (name): - -\begin{itemize} - -\item -If the name does not occur in a \verb\global\ statement in the current -code block: the name is bound to the object in the current local name -space. -\stindex{global} - -\item -Otherwise: the name is bound to the object in the current global name -space. - -\end{itemize} % nested - -The name is rebound if it was already bound. - -\item -If the target is a target list enclosed in parentheses: the object is -assigned to that target list as described above. - -\item -If the target is a target list enclosed in square brackets: the object -must be a list with the same number of items as the target list -contains targets, and its items are assigned, from left to right, to -the corresponding targets. - -\item -If the target is an attribute reference: The primary expression in the -reference is evaluated. It should yield an object with assignable -attributes; if this is not the case, \verb\TypeError\ is raised. That -object is then asked to assign the assigned object to the given -attribute; if it cannot perform the assignment, it raises an exception -(usually but not necessarily \verb\AttributeError\). -\indexii{attribute}{assignment} - -\item -If the target is a subscription: The primary expression in the -reference is evaluated. It should yield either a mutable sequence -(list) object or a mapping (dictionary) object. Next, the subscript -expression is evaluated. -\indexii{subscription}{assignment} -\obindex{mutable} - -If the primary is a mutable sequence object (a list), the subscript -must yield a plain integer. If it is negative, the sequence's length -is added to it. The resulting value must be a nonnegative integer -less than the sequence's length, and the sequence is asked to assign -the assigned object to its item with that index. If the index is out -of range, \verb\IndexError\ is raised (assignment to a subscripted -sequence cannot add new items to a list). -\obindex{sequence} -\obindex{list} - -If the primary is a mapping (dictionary) object, the subscript must -have a type compatible with the mapping's key type, and the mapping is -then asked to to create a key/datum pair which maps the subscript to -the assigned object. This can either replace an existing key/value -pair with the same key value, or insert a new key/value pair (if no -key with the same value existed). -\obindex{mapping} -\obindex{dictionary} - -\item -If the target is a slicing: The primary expression in the reference is -evaluated. It should yield a mutable sequence (list) object. The -assigned object should be a sequence object of the same type. Next, -the lower and upper bound expressions are evaluated, insofar they are -present; defaults are zero and the sequence's length. The bounds -should evaluate to (small) integers. If either bound is negative, the -sequence's length is added to it. The resulting bounds are clipped to -lie between zero and the sequence's length, inclusive. Finally, the -sequence object is asked to replace the items indicated by the slice -with the items of the assigned sequence. This may change the -sequence's length, if it allows it. -\indexii{slicing}{assignment} - -\end{itemize} - -(In the original implementation, the syntax for targets is taken -to be the same as for expressions, and invalid syntax is rejected -during the code generation phase, causing less detailed error -messages.) - -\section{The {\tt pass} statement} -\stindex{pass} - -\begin{verbatim} -pass_stmt: "pass" -\end{verbatim} - -\verb\pass\ is a null operation --- when it is executed, nothing -happens. It is useful as a placeholder when a statement is -required syntactically, but no code needs to be executed, for example: -\indexii{null}{operation} - -\begin{verbatim} -def f(arg): pass # a function that does nothing (yet) - -class C: pass # an class with no methods (yet) -\end{verbatim} - -\section{The {\tt del} statement} -\stindex{del} - -\begin{verbatim} -del_stmt: "del" target_list -\end{verbatim} - -Deletion is recursively defined very similar to the way assignment is -defined. Rather that spelling it out in full details, here are some -hints. -\indexii{deletion}{target} -\indexiii{deletion}{target}{list} - -Deletion of a target list recursively deletes each target, from left -to right. - -Deletion of a name removes the binding of that name (which must exist) -from the local or global name space, depending on whether the name -occurs in a \verb\global\ statement in the same code block. -\stindex{global} -\indexii{unbinding}{name} - -Deletion of attribute references, subscriptions and slicings -is passed to the primary object involved; deletion of a slicing -is in general equivalent to assignment of an empty slice of the -right type (but even this is determined by the sliced object). -\indexii{attribute}{deletion} - -\section{The {\tt print} statement} \label{print} -\stindex{print} - -\begin{verbatim} -print_stmt: "print" [ condition ("," condition)* [","] ] -\end{verbatim} - -\verb\print\ evaluates each condition in turn and writes the resulting -object to standard output (see below). If an object is not a string, -it is first converted to a string using the rules for string -conversions. The (resulting or original) string is then written. A -space is written before each object is (converted and) written, unless -the output system believes it is positioned at the beginning of a -line. This is the case: (1) when no characters have yet been written -to standard output; or (2) when the last character written to standard -output is \verb/\n/; or (3) when the last write operation on standard -output was not a \verb\print\ statement. (In some cases it may be -functional to write an empty string to standard output for this -reason.) -\index{output} -\indexii{writing}{values} - -A \verb/"\n"/ character is written at the end, unless the \verb\print\ -statement ends with a comma. This is the only action if the statement -contains just the keyword \verb\print\. -\indexii{trailing}{comma} -\indexii{newline}{suppression} - -Standard output is defined as the file object named \verb\stdout\ -in the built-in module \verb\sys\. If no such object exists, -or if it is not a writable file, a \verb\RuntimeError\ exception is raised. -(The original implementation attempts to write to the system's original -standard output instead, but this is not safe, and should be fixed.) -\indexii{standard}{output} -\bimodindex{sys} -\ttindex{stdout} -\exindex{RuntimeError} - -\section{The {\tt return} statement} -\stindex{return} - -\begin{verbatim} -return_stmt: "return" [condition_list] -\end{verbatim} - -\verb\return\ may only occur syntactically nested in a function -definition, not within a nested class definition. -\indexii{function}{definition} -\indexii{class}{definition} - -If a condition list is present, it is evaluated, else \verb\None\ -is substituted. - -\verb\return\ leaves the current function call with the condition -list (or \verb\None\) as return value. - -When \verb\return\ passes control out of a \verb\try\ statement -with a \verb\finally\ clause, that finally clause is executed -before really leaving the function. -\kwindex{finally} - -\section{The {\tt raise} statement} -\stindex{raise} - -\begin{verbatim} -raise_stmt: "raise" condition ["," condition] -\end{verbatim} - -\verb\raise\ evaluates its first condition, which must yield -a string object. If there is a second condition, this is evaluated, -else \verb\None\ is substituted. -\index{exception} -\indexii{raising}{exception} - -It then raises the exception identified by the first object, -with the second one (or \verb\None\) as its parameter. - -\section{The {\tt break} statement} -\stindex{break} - -\begin{verbatim} -break_stmt: "break" -\end{verbatim} - -\verb\break\ may only occur syntactically nested in a \verb\for\ -or \verb\while\ loop, not nested in a function or class definition. -\stindex{for} -\stindex{while} -\indexii{loop}{statement} - -It terminates the neares enclosing loop, skipping the optional -\verb\else\ clause if the loop has one. -\kwindex{else} - -If a \verb\for\ loop is terminated by \verb\break\, the loop control -target keeps its current value. -\indexii{loop control}{target} - -When \verb\break\ passes control out of a \verb\try\ statement -with a \verb\finally\ clause, that finally clause is executed -before really leaving the loop. -\kwindex{finally} - -\section{The {\tt continue} statement} -\stindex{continue} - -\begin{verbatim} -continue_stmt: "continue" -\end{verbatim} - -\verb\continue\ may only occur syntactically nested in a \verb\for\ or -\verb\while\ loop, not nested in a function or class definition, and -not nested in the \verb\try\ clause of a \verb\try\ statement with a -\verb\finally\ clause (it may occur nested in a \verb\except\ or -\verb\finally\ clause of a \verb\try\ statement though). -\stindex{for} -\stindex{while} -\indexii{loop}{statement} -\kwindex{finally} - -It continues with the next cycle of the nearest enclosing loop. - -\section{The {\tt import} statement} \label{import} -\stindex{import} - -\begin{verbatim} -import_stmt: "import" identifier ("," identifier)* - | "from" identifier "import" identifier ("," identifier)* - | "from" identifier "import" "*" -\end{verbatim} - -Import statements are executed in two steps: (1) find a module, and -initialize it if necessary; (2) define a name or names in the local -name space (of the scope where the \verb\import\ statement occurs). -The first form (without \verb\from\) repeats these steps for each -identifier in the list, the \verb\from\ form performs them once, with -the first identifier specifying the module name. -\indexii{importing}{module} -\indexii{name}{binding} -\kwindex{from} - -The system maintains a table of modules that have been initialized, -indexed by module name. (The current implementation makes this table -accessible as \verb\sys.modules\.) When a module name is found in -this table, step (1) is finished. If not, a search for a module -definition is started. This first looks for a built-in module -definition, and if no built-in module if the given name is found, it -searches a user-specified list of directories for a file whose name is -the module name with extension \verb\".py"\. (The current -implementation uses the list of strings \verb\sys.path\ as the search -path; it is initialized from the shell environment variable -\verb\$PYTHONPATH\, with an installation-dependent default.) -\ttindex{modules} -\ttindex{sys.modules} -\indexii{module}{name} -\indexii{built-in}{module} -\indexii{user-defined}{module} -\bimodindex{sys} -\ttindex{path} -\ttindex{sys.path} -\indexii{filename}{extension} - -If a built-in module is found, its built-in initialization code is -executed and step (1) is finished. If no matching file is found, -\verb\ImportError\ is raised. If a file is found, it is parsed, -yielding an executable code block. If a syntax error occurs, -\verb\SyntaxError\ is raised. Otherwise, an empty module of the given -name is created and inserted in the module table, and then the code -block is executed in the context of this module. Exceptions during -this execution terminate step (1). -\indexii{module}{initialization} -\exindex{SyntaxError} -\exindex{ImportError} -\index{code block} - -When step (1) finishes without raising an exception, step (2) can -begin. - -The first form of \verb\import\ statement binds the module name in the -local name space to the module object, and then goes on to import the -next identifier, if any. The \verb\from\ from does not bind the -module name: it goes through the list of identifiers, looks each one -of them up in the module found in step (1), and binds the name in the -local name space to the object thus found. If a name is not found, -\verb\ImportError\ is raised. If the list of identifiers is replaced -by a star (\verb\*\), all names defined in the module are bound, -except those beginning with an underscore(\verb\_\). -\indexii{name}{binding} -\exindex{ImportError} - -Names bound by import statements may not occur in \verb\global\ -statements in the same scope. -\stindex{global} - -The \verb\from\ form with \verb\*\ may only occur in a module scope. -\kwindex{from} -\ttindex{from ... import *} - -(The current implementation does not enforce the latter two -restrictions, but programs should not abuse this freedom, as future -implementations may enforce them or silently change the meaning of the -program.) - -\section{The {\tt global} statement} \label{global} -\stindex{global} - -\begin{verbatim} -global_stmt: "global" identifier ("," identifier)* -\end{verbatim} - -The \verb\global\ statement is a declaration which holds for the -entire current scope. It means that the listed identifiers are to be -interpreted as globals. While {\em using} global names is automatic -if they are not defined in the local scope, {\em assigning} to global -names would be impossible without \verb\global\. -\indexiii{global}{name}{binding} - -Names listed in a \verb\global\ statement must not be used in the same -scope before that \verb\global\ statement is executed. - -Names listed in a \verb\global\ statement must not be defined as formal -parameters or in a \verb\for\ loop control target, \verb\class\ -definition, function definition, or \verb\import\ statement. - -(The current implementation does not enforce the latter two -restrictions, but programs should not abuse this freedom, as future -implementations may enforce them or silently change the meaning of the -program.) - -\section{The {\tt access} statement} \label{access} -\stindex{access} - -\begin{verbatim} -access_stmt: "access" ... -\end{verbatim} - -This statement will be used in the future to control access to -instance and class variables. Currently its syntax and effects are -undefined; however the keyword \verb\access\ is a reserved word for -the parser. - -\section{The {\tt exec} statement} \label{exec} -\stindex{exec} - -\begin{verbatim} -exec_stmt: "exec" expression ["in" expression ["," expression]] -\end{verbatim} - -This statement supports dynamic execution of Python code. The first -expression should evaluate to either a string, an open file object, or -a code object. If it is a string, the string is parsed as a suite of -Python statements which is then executed (unless a syntax error -occurs). If it is an open file, the file is parsed until EOF and -executed. If it is a code object, it is simply executed. - -In all cases, if the optional parts are omitted, the code is executed -in the current scope. If only the first expression after \verb\in\ is -specified, it should be a dictionary, which will be used for both the -global and the local variables. If two expressions are given, both -must be dictionaries and they are used for the global and local -variables, respectively. - -Note: dynamic evaluation of expressions is supported by the built-in -function \verb\eval\. - diff --git a/Doc/ref7.tex b/Doc/ref7.tex deleted file mode 100644 index 670eec0a5e..0000000000 --- a/Doc/ref7.tex +++ /dev/null @@ -1,364 +0,0 @@ -\chapter{Compound statements} -\indexii{compound}{statement} - -Compound statements contain (groups of) other statements; they affect -or control the execution of those other statements in some way. In -general, compound statements span multiple lines, although in simple -incarnations a whole compound statement may be contained in one line. - -The \verb\if\, \verb\while\ and \verb\for\ statements implement -traditional control flow constructs. \verb\try\ specifies exception -handlers and/or cleanup code for a group of statements. Function and -class definitions are also syntactically compound statements. - -Compound statements consist of one or more `clauses'. A clause -consists of a header and a `suite'. The clause headers of a -particular compound statement are all at the same indentation level. -Each clause header begins with a uniquely identifying keyword and ends -with a colon. A suite is a group of statements controlled by a -clause. A suite can be one or more semicolon-separated simple -statements on the same line as the header, following the header's -colon, or it can be one or more indented statements on subsequent -lines. Only the latter form of suite can contain nested compound -statements; the following is illegal, mostly because it wouldn't be -clear to which \verb\if\ clause a following \verb\else\ clause would -belong: -\index{clause} -\index{suite} - -\begin{verbatim} -if test1: if test2: print x -\end{verbatim} - -Also note that the semicolon binds tighter than the colon in this -context, so that in the following example, either all or none of the -\verb\print\ statements are executed: - -\begin{verbatim} -if x < y < z: print x; print y; print z -\end{verbatim} - -Summarizing: - -\begin{verbatim} -compound_stmt: if_stmt | while_stmt | for_stmt - | try_stmt | funcdef | classdef -suite: stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT -statement: stmt_list NEWLINE | compound_stmt -stmt_list: simple_stmt (";" simple_stmt)* [";"] -\end{verbatim} - -Note that statements always end in a \verb\NEWLINE\ possibly followed -by a \verb\DEDENT\. -\index{NEWLINE token} -\index{DEDENT token} - -Also note that optional continuation clauses always begin with a -keyword that cannot start a statement, thus there are no ambiguities -(the `dangling \verb\else\' problem is solved in Python by requiring -nested \verb\if\ statements to be indented). -\indexii{dangling}{else} - -The formatting of the grammar rules in the following sections places -each clause on a separate line for clarity. - -\section{The {\tt if} statement} -\stindex{if} - -The \verb\if\ statement is used for conditional execution: - -\begin{verbatim} -if_stmt: "if" condition ":" suite - ("elif" condition ":" suite)* - ["else" ":" suite] -\end{verbatim} - -It selects exactly one of the suites by evaluating the conditions one -by one until one is found to be true (see section \ref{Booleans} for -the definition of true and false); then that suite is executed (and no -other part of the \verb\if\ statement is executed or evaluated). If -all conditions are false, the suite of the \verb\else\ clause, if -present, is executed. -\kwindex{elif} -\kwindex{else} - -\section{The {\tt while} statement} -\stindex{while} -\indexii{loop}{statement} - -The \verb\while\ statement is used for repeated execution as long as a -condition is true: - -\begin{verbatim} -while_stmt: "while" condition ":" suite - ["else" ":" suite] -\end{verbatim} - -This repeatedly tests the condition and, if it is true, executes the -first suite; if the condition is false (which may be the first time it -is tested) the suite of the \verb\else\ clause, if present, is -executed and the loop terminates. -\kwindex{else} - -A \verb\break\ statement executed in the first suite terminates the -loop without executing the \verb\else\ clause's suite. A -\verb\continue\ statement executed in the first suite skips the rest -of the suite and goes back to testing the condition. -\stindex{break} -\stindex{continue} - -\section{The {\tt for} statement} -\stindex{for} -\indexii{loop}{statement} - -The \verb\for\ statement is used to iterate over the elements of a -sequence (string, tuple or list): -\obindex{sequence} - -\begin{verbatim} -for_stmt: "for" target_list "in" condition_list ":" suite - ["else" ":" suite] -\end{verbatim} - -The condition list is evaluated once; it should yield a sequence. The -suite is then executed once for each item in the sequence, in the -order of ascending indices. Each item in turn is assigned to the -target list using the standard rules for assignments, and then the -suite is executed. When the items are exhausted (which is immediately -when the sequence is empty), the suite in the \verb\else\ clause, if -present, is executed, and the loop terminates. -\kwindex{in} -\kwindex{else} -\indexii{target}{list} - -A \verb\break\ statement executed in the first suite terminates the -loop without executing the \verb\else\ clause's suite. A -\verb\continue\ statement executed in the first suite skips the rest -of the suite and continues with the next item, or with the \verb\else\ -clause if there was no next item. -\stindex{break} -\stindex{continue} - -The suite may assign to the variable(s) in the target list; this does -not affect the next item assigned to it. - -The target list is not deleted when the loop is finished, but if the -sequence is empty, it will not have been assigned to at all by the -loop. - -Hint: the built-in function \verb\range()\ returns a sequence of -integers suitable to emulate the effect of Pascal's \verb\for i := a -to b do\; e.g. \verb\range(3)\ returns the list \verb\[0, 1, 2]\. -\bifuncindex{range} -\index{Pascal} - -{\bf Warning:} There is a subtlety when the sequence is being modified -by the loop (this can only occur for mutable sequences, i.e. lists). -An internal counter is used to keep track of which item is used next, -and this is incremented on each iteration. When this counter has -reached the length of the sequence the loop terminates. This means that -if the suite deletes the current (or a previous) item from the -sequence, the next item will be skipped (since it gets the index of -the current item which has already been treated). Likewise, if the -suite inserts an item in the sequence before the current item, the -current item will be treated again the next time through the loop. -This can lead to nasty bugs that can be avoided by making a temporary -copy using a slice of the whole sequence, e.g. -\index{loop!over mutable sequence} -\index{mutable sequence!loop over} - -\begin{verbatim} -for x in a[:]: - if x < 0: a.remove(x) -\end{verbatim} - -\section{The {\tt try} statement} \label{try} -\stindex{try} - -The \verb\try\ statement specifies exception handlers and/or cleanup -code for a group of statements: - -\begin{verbatim} -try_stmt: try_exc_stmt | try_fin_stmt -try_exc_stmt: "try" ":" suite - ("except" [condition ["," target]] ":" suite)+ -try_fin_stmt: "try" ":" suite - "finally" ":" suite -\end{verbatim} - -There are two forms of \verb\try\ statement: \verb\try...except\ and -\verb\try...finally\. These forms cannot be mixed. - -The \verb\try...except\ form specifies one or more exception handlers -(the \verb\except\ clauses). When no exception occurs in the -\verb\try\ clause, no exception handler is executed. When an -exception occurs in the \verb\try\ suite, a search for an exception -handler is started. This inspects the except clauses in turn until -one is found that matches the exception. A condition-less except -clause, if present, must be last; it matches any exception. For an -except clause with a condition, that condition is evaluated, and the -clause matches the exception if the resulting object is ``compatible'' -with the exception. An object is compatible with an exception if it -is either the object that identifies the exception or it is a tuple -containing an item that is compatible with the exception. Note that -the object identities must match, i.e. it must be the same object, not -just an object with the same value. -\kwindex{except} - -If no except clause matches the exception, the search for an exception -handler continues in the surrounding code and on the invocation stack. - -If the evaluation of a condition in the header of an except clause -raises an exception, the original search for a handler is cancelled -and a search starts for the new exception in the surrounding code and -on the call stack (it is treated as if the entire \verb\try\ statement -raised the exception). - -When a matching except clause is found, the exception's parameter is -assigned to the target specified in that except clause, if present, -and the except clause's suite is executed. When the end of this suite -is reached, execution continues normally after the entire try -statement. (This means that if two nested handlers exist for the same -exception, and the exception occurs in the try clause of the inner -handler, the outer handler will not handle the exception.) - -Before an except clause's suite is executed, details about the -exception are assigned to three variables in the \verb\sys\ module: -\verb\sys.exc_type\ receives the object identifying the exception; -\verb\sys.exc_value\ receives the exception's parameter; -\verb\sys.exc_traceback\ receives a traceback object (see section -\ref{traceback}) identifying the point in the program where the -exception occurred. -\bimodindex{sys} -\ttindex{exc_type} -\ttindex{exc_value} -\ttindex{exc_traceback} -\obindex{traceback} - -The \verb\try...finally\ form specifies a `cleanup' handler. The -\verb\try\ clause is executed. When no exception occurs, the -\verb\finally\ clause is executed. When an exception occurs in the -\verb\try\ clause, the exception is temporarily saved, the -\verb\finally\ clause is executed, and then the saved exception is -re-raised. If the \verb\finally\ clause raises another exception or -executes a \verb\return\, \verb\break\ or \verb\continue\ statement, -the saved exception is lost. -\kwindex{finally} - -When a \verb\return\ or \verb\break\ statement is executed in the -\verb\try\ suite of a \verb\try...finally\ statement, the -\verb\finally\ clause is also executed `on the way out'. A -\verb\continue\ statement is illegal in the \verb\try\ clause. (The -reason is a problem with the current implementation --- this -restriction may be lifted in the future). -\stindex{return} -\stindex{break} -\stindex{continue} - -\section{Function definitions} \label{function} -\indexii{function}{definition} - -A function definition defines a user-defined function object (see -section \ref{types}): -\obindex{user-defined function} -\obindex{function} - -\begin{verbatim} -funcdef: "def" funcname "(" [parameter_list] ")" ":" suite -parameter_list: (parameter ",")* ("*" identifier | parameter [","]) -sublist: parameter ("," parameter)* [","] -parameter: identifier | "(" sublist ")" -funcname: identifier -\end{verbatim} - -A function definition is an executable statement. Its execution binds -the function name in the current local name space to a function object -(a wrapper around the executable code for the function). This -function object contains a reference to the current global name space -as the global name space to be used when the function is called. -\indexii{function}{name} -\indexii{name}{binding} - -The function definition does not execute the function body; this gets -executed only when the function is called. - -Function call semantics are described in section \ref{calls}. When a -user-defined function is called, the arguments (a.k.a. actual -parameters) are bound to the (formal) parameters, as follows: -\indexii{function}{call} -\indexiii{user-defined}{function}{call} -\index{parameter} -\index{argument} -\indexii{parameter}{formal} -\indexii{parameter}{actual} - -It is also possible to create anonymous functions (functions not bound -to a name), for immediate use in expressions. This uses lambda forms, -described in section \ref{lambda}. - -\begin{itemize} - -\item -If there are no formal parameters, there must be no arguments. - -\item -If the formal parameter list does not end in a star followed by an -identifier, there must be exactly as many arguments as there are -parameters in the formal parameter list (at the top level); the -arguments are assigned to the formal parameters one by one. Note that -the presence or absence of a trailing comma at the top level in either -the formal or the actual parameter list makes no difference. The -assignment to a formal parameter is performed as if the parameter -occurs on the left hand side of an assignment statement whose right -hand side's value is that of the argument. - -\item -If the formal parameter list ends in a star followed by an identifier, -preceded by zero or more comma-followed parameters, there must be at -least as many arguments as there are parameters preceding the star. -Call this number {\em N}. The first {\em N} arguments are assigned to -the corresponding formal parameters in the way descibed above. A -tuple containing the remaining arguments, if any, is then assigned to -the identifier following the star. This variable will always be a -tuple: if there are no extra arguments, its value is \verb\()\, if -there is just one extra argument, it is a singleton tuple. -\indexii{variable length}{parameter list} - -\end{itemize} - -Note that the `variable length parameter list' feature only works at -the top level of the parameter list; individual parameters use a model -corresponding more closely to that of ordinary assignment. While the -latter model is generally preferable, because of the greater type -safety it offers (wrong-sized tuples aren't silently mistreated), -variable length parameter lists are a sufficiently accepted practice -in most programming languages that a compromise has been worked out. -(And anyway, assignment has no equivalent for empty argument lists.) - -\section{Class definitions} \label{class} -\indexii{class}{definition} - -A class definition defines a class object (see section \ref{types}): -\obindex{class} - -\begin{verbatim} -classdef: "class" classname [inheritance] ":" suite -inheritance: "(" [condition_list] ")" -classname: identifier -\end{verbatim} - -A class definition is an executable statement. It first evaluates the -inheritance list, if present. Each item in the inheritance list -should evaluate to a class object. The class's suite is then executed -in a new execution frame (see section \ref{execframes}), using a newly -created local name space and the original global name space. -(Usually, the suite contains only function definitions.) When the -class's suite finishes execution, its execution frame is discarded but -its local name space is saved. A class object is then created using -the inheritance list for the base classes and the saved local name -space for the attribute dictionary. The class name is bound to this -class object in the original local name space. -\index{inheritance} -\indexii{class}{name} -\indexii{name}{binding} -\indexii{execution}{frame} diff --git a/Doc/ref8.tex b/Doc/ref8.tex deleted file mode 100644 index aeb65bf721..0000000000 --- a/Doc/ref8.tex +++ /dev/null @@ -1,104 +0,0 @@ -\chapter{Top-level components} - -The Python interpreter can get its input from a number of sources: -from a script passed to it as standard input or as program argument, -typed in interactively, from a module source file, etc. This chapter -gives the syntax used in these cases. -\index{interpreter} - -\section{Complete Python programs} -\index{program} - -While a language specification need not prescribe how the language -interpreter is invoked, it is useful to have a notion of a complete -Python program. A complete Python program is executed in a minimally -initialized environment: all built-in and standard modules are -available, but none have been initialized, except for \verb\sys\ -(various system services), \verb\__builtin__\ (built-in functions, -exceptions and \verb\None\) and \verb\__main__\. The latter is used -to provide the local and global name space for execution of the -complete program. -\bimodindex{sys} -\bimodindex{__main__} -\bimodindex{__builtin__} - -The syntax for a complete Python program is that for file input, -described in the next section. - -The interpreter may also be invoked in interactive mode; in this case, -it does not read and execute a complete program but reads and executes -one statement (possibly compound) at a time. The initial environment -is identical to that of a complete program; each statement is executed -in the name space of \verb\__main__\. -\index{interactive mode} - -Under {\UNIX}, a complete program can be passed to the interpreter in -three forms: with the {\bf -c} {\it string} command line option, as a -file passed as the first command line argument, or as standard input. -If the file or standard input is a tty device, the interpreter enters -interactive mode; otherwise, it executes the file as a complete -program. -\index{UNIX} -\index{command line} -\index{standard input} - -\section{File input} - -All input read from non-interactive files has the same form: - -\begin{verbatim} -file_input: (NEWLINE | statement)* -\end{verbatim} - -This syntax is used in the following situations: - -\begin{itemize} - -\item when parsing a complete Python program (from a file or from a string); - -\item when parsing a module; - -\item when parsing a string passed to the \verb\exec\ statement; - -\end{itemize} - -\section{Interactive input} - -Input in interactive mode is parsed using the following grammar: - -\begin{verbatim} -interactive_input: [stmt_list] NEWLINE | compound_stmt NEWLINE -\end{verbatim} - -Note that a (top-level) compound statement must be followed by a blank -line in interactive mode; this is needed to help the parser detect the -end of the input. - -\section{Expression input} -\index{input} - -There are two forms of expression input. Both ignore leading -whitespace. - -The string argument to \verb\eval()\ must have the following form: -\bifuncindex{eval} - -\begin{verbatim} -eval_input: condition_list NEWLINE* -\end{verbatim} - -The input line read by \verb\input()\ must have the following form: -\bifuncindex{input} - -\begin{verbatim} -input_input: condition_list NEWLINE -\end{verbatim} - -Note: to read `raw' input line without interpretation, you can use the -built-in function \verb\raw_input()\ or the \verb\readline()\ method -of file objects. -\obindex{file} -\index{input!raw} -\index{raw input} -\bifuncindex{raw_index} -\ttindex{readline} diff --git a/Doc/templates/module.tex b/Doc/templates/module.tex deleted file mode 100644 index 7465af8720..0000000000 --- a/Doc/templates/module.tex +++ /dev/null @@ -1,40 +0,0 @@ -% Template for library sections. -% Replace text in ALL CAPS by your own text. -% Comments starting with %** give additional directions. - -%** Choose one of the following two section headings: -\section{Built-in module {\tt YOUR-MODULE-NAME}} % If written in C -\section{Standard module {\tt YOUR-MODULE-NAME}} % If written in Python - -PUT A SHORT INTRODUCTION AND DESCRIPTION OF THE MODULE HERE. - -%** change this sentence to taste: -The module defines the following variables and functions: - -\begin{description} - -\renewcommand{\indexsubitem}{(in module YOUR-MODULE-NAME)} - - -%** You can mix exceptions, variables and functions below; often it is a -%** good idea to alphabetize them all. - - -%** repeat the following for each exception: -\excitem{NAME} -DESCRIPTION OF THE EXCEPTION GOES HERE. - - -%** repeat the following for each variable (or constant): -\dataitem{NAME} -DESCRIPTION OF THE VARIABLE/CONSTANT GOES HERE. - - -%** repeat the following for each function: -\funcitem{NAME}{PARAMETERS} % Don't include the parentheses -DESCRIPTION OF THE FUNCTION GOES HERE. - - -\end{description} - -ADDITIONAL HINTS FOR USING THE MODULE MAY GO HERE. diff --git a/Doc/texipost.dat b/Doc/texipost.dat deleted file mode 100644 index 7897e44b09..0000000000 --- a/Doc/texipost.dat +++ /dev/null @@ -1,23 +0,0 @@ -@node Function Index, , , -@unnumbered Function Index - -@printindex fn - -@node Variable Index, , , -@unnumbered Variable Index - -@printindex vr - -@node Module Index, , , -@unnumbered Module Index - -@printindex pg - -@node Concept Index, , , -@unnumbered Concept Index - -@printindex cp - -@summarycontents -@contents -@bye diff --git a/Doc/texipre.dat b/Doc/texipre.dat deleted file mode 100644 index c531077e45..0000000000 --- a/Doc/texipre.dat +++ /dev/null @@ -1,86 +0,0 @@ -\input texinfo @c -*-texinfo-*- -@c %**start of header -@setfilename python-lib.info -@settitle Python library reference -@setchapternewpage odd -@footnotestyle end -@c %**end of header - -@ifinfo -This file describes the built-in types, exceptions and functions and the -standard modules that come with the Python system. It assumes basic -knowledge about the Python language. For an informal introduction to -the language, see the Python Tutorial. The Python Reference Manual -gives a more formal definition of the language. (These manuals are not -yet available in INFO or Texinfo format.) - -Copyright (C) 1991, 1992, 1993 by Stichting Mathematisch Centrum, -Amsterdam, The Netherlands. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the names of Stichting Mathematisch -Centrum or CWI not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior permission. - -STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO -THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE -FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -@end ifinfo - -@titlepage -@title Python library reference -@author Guido van Rossum - -@c The following two commands start the copyright page. -@page -@vskip 0pt plus 1filll -Copyright @copyright{} 1991, 1992, 1993 by Stichting Mathematisch Centrum, -Amsterdam, The Netherlands. - -@center All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the names of Stichting Mathematisch -Centrum or CWI not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior permission. - -STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO -THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE -FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -@end titlepage - - -@node Top, Overview, (dir), (dir) -@top The Python library - -@ifinfo -This file describes the built-in types, exceptions and functions and the -standard modules that come with the Python system. It assumes basic -knowledge about the Python language. For an informal introduction to -the language, see the @cite{Python Tutorial}. The @cite{Python -Reference Manual} gives a more formal definition of the language. -(These manuals are not yet available in INFO or Texinfo format.) - -This version corresponds roughly to Python version 1.0 (yet to be released). - -@end ifinfo - -@c placeholder for the master menu -- patched by texinfo-all-menus-update -@menu -@end menu diff --git a/Doc/text2latex.py b/Doc/text2latex.py deleted file mode 100644 index 93d0587d30..0000000000 --- a/Doc/text2latex.py +++ /dev/null @@ -1,55 +0,0 @@ -import os -import sys -import regex -import regsub -import string -import getopt - -def main(): - process(sys.stdin, sys.stdout) - -dashes = regex.compile('^-+[ \t]*$') -equals = regex.compile('^=+[ \t]*$') -stars = regex.compile('^\*+[ \t]*$') -blank = regex.compile('^[ \t]*$') -indented = regex.compile('^\( *\t\| \)[ \t]*[^ \t]') - -def process(fi, fo): - inverbatim = 0 - line = '\n' - nextline = fi.readline() - while nextline: - prevline = line - line = nextline - nextline = fi.readline() - fmt = None - if dashes.match(nextline) >= 0: - fmt = '\\subsection{%s}\n' - elif equals.match(nextline) >= 0: - fmt = '\\section{%s}\n' - elif stars.match(nextline) >= 0: - fmt = '\\chapter{%s}\n' - if fmt: - nextline = '\n' - line = fmt % string.strip(line) - if '(' in line: - line = regsub.gsub('[a-zA-Z0-9_]+()', - '{\\\\tt \\0}', line) - elif inverbatim: - if blank.match(line) >= 0 and \ - indented.match(nextline) < 0: - inverbatim = 0 - fo.write('\\end{verbatim}\n') - else: - if indented.match(line) >= 0 and \ - blank.match(prevline) >= 0: - inverbatim = 1 - fo.write('\\begin{verbatim}\n') - if inverbatim: - line = string.expandtabs(line, 4) - elif not fmt and '(' in line: - line = regsub.gsub('[a-zA-Z0-9_]+()', - '\\\\code{\\0}', line) - fo.write(line) - -main() diff --git a/Doc/tools/fix.el b/Doc/tools/fix.el deleted file mode 100644 index 25086e4359..0000000000 --- a/Doc/tools/fix.el +++ /dev/null @@ -1,6 +0,0 @@ -; load the new texinfo package (2.xx) if not installed by default -; (setq load-path -; (cons "/ufs/jh/lib/emacs/texinfo-2.14" load-path)) -(find-file "lib.texi") -(texinfo-all-menus-update t) -(texinfo-all-menus-update t) diff --git a/Doc/tools/fix_hack b/Doc/tools/fix_hack deleted file mode 100755 index 8c977291bb..0000000000 --- a/Doc/tools/fix_hack +++ /dev/null @@ -1 +0,0 @@ -sed -e 's/{\\ptt[ ]*\\char[ ]*'"'"'137}/_/g' <"$1" > "@$1" && mv "@$1" $1 diff --git a/Doc/tools/partparse.py b/Doc/tools/partparse.py deleted file mode 100644 index 757fc02bc7..0000000000 --- a/Doc/tools/partparse.py +++ /dev/null @@ -1,2129 +0,0 @@ -# -# partparse.py: parse a by-Guido-written-and-by-Jan-Hein-edited LaTeX file, -# and generate texinfo source. -# -# This is *not* a good example of good programming practices. In fact, this -# file could use a complete rewrite, in order to become faster, more -# easy extensible and maintainable. -# -# However, I added some comments on a few places for the pityful person who -# would ever need to take a look into this file. -# -# Have I been clear enough?? -# -# -jh - - -import sys, string, regex, getopt, os - -# Different parse modes for phase 1 -MODE_REGULAR = 0 -MODE_VERBATIM = 1 -MODE_CS_SCAN = 2 -MODE_COMMENT = 3 -MODE_MATH = 4 -MODE_DMATH = 5 -MODE_GOBBLEWHITE = 6 - -the_modes = MODE_REGULAR, MODE_VERBATIM, MODE_CS_SCAN, MODE_COMMENT, \ - MODE_MATH, MODE_DMATH, MODE_GOBBLEWHITE - -# Show the neighbourhood of the scanned buffer -def epsilon(buf, where): - wmt, wpt = where - 10, where + 10 - if wmt < 0: - wmt = 0 - if wpt > len(buf): - wpt = len(buf) - return ' Context ' + `buf[wmt:where]` + '.' + `buf[where:wpt]` + '.' - -# Should return the line number. never worked -def lin(): - global lineno - return ' Line ' + `lineno` + '.' - -# Displays the recursion level. -def lv(lvl): - return ' Level ' + `lvl` + '.' - -# Combine the three previous functions. Used often. -def lle(lvl, buf, where): - return lv(lvl) + lin() + epsilon(buf, where) - - -# This class is only needed for _symbolic_ representation of the parse mode. -class Mode: - def init(self, arg): - if arg not in the_modes: - raise ValueError, 'mode not in the_modes' - self.mode = arg - return self - - def __cmp__(self, other): - if type(self) != type(other): - other = mode(other) - return cmp(self.mode, other.mode) - - def __repr__(self): - if self.mode == MODE_REGULAR: - return 'MODE_REGULAR' - elif self.mode == MODE_VERBATIM: - return 'MODE_VERBATIM' - elif self.mode == MODE_CS_SCAN: - return 'MODE_CS_SCAN' - elif self.mode == MODE_COMMENT: - return 'MODE_COMMENT' - elif self.mode == MODE_MATH: - return 'MODE_MATH' - elif self.mode == MODE_DMATH: - return 'MODE_DMATH' - elif self.mode == MODE_GOBBLEWHITE: - return 'MODE_GOBBLEWHITE' - else: - raise ValueError, 'mode not in the_modes' - -# just a wrapper around a class initialisation -def mode(arg): - return Mode().init(arg) - - -# After phase 1, the text consists of chunks, with a certain type -# this type will be assigned to the chtype member of the chunk -# the where-field contains the file position where this is found -# and the data field contains (1): a tuple describing start- end end -# positions of the substring (can be used as slice for the buf-variable), -# (2) just a string, mostly generated by the changeit routine, -# or (3) a list, describing a (recursive) subgroup of chunks -PLAIN = 0 # ASSUME PLAINTEXT, data = the text -GROUP = 1 # GROUP ({}), data = [chunk, chunk,..] -CSNAME = 2 # CONTROL SEQ TOKEN, data = the command -COMMENT = 3 # data is the actual comment -DMATH = 4 # DISPLAYMATH, data = [chunk, chunk,..] -MATH = 5 # MATH, see DISPLAYMATH -OTHER = 6 # CHAR WITH CATCODE OTHER, data = char -ACTIVE = 7 # ACTIVE CHAR -GOBBLEDWHITE = 8 # Gobbled LWSP, after CSNAME -ENDLINE = 9 # END-OF-LINE, data = '\n' -DENDLINE = 10 # DOUBLE EOL, data='\n', indicates \par -ENV = 11 # LaTeX-environment - # data =(envname,[ch,ch,ch,.]) -CSLINE = 12 # for texi: next chunk will be one group - # of args. Will be set all on 1 line -IGNORE = 13 # IGNORE this data -ENDENV = 14 # TEMP END OF GROUP INDICATOR -IF = 15 # IF-directive - # data = (flag,negate,[ch, ch, ch,...]) -the_types = PLAIN, GROUP, CSNAME, COMMENT, DMATH, MATH, OTHER, ACTIVE, \ - GOBBLEDWHITE, ENDLINE, DENDLINE, ENV, CSLINE, IGNORE, ENDENV, IF - -# class, just to display symbolic name -class ChunkType: - def init(self, chunk_type): - if chunk_type not in the_types: - raise 'ValueError', 'chunk_type not in the_types' - self.chunk_type = chunk_type - return self - - def __cmp__(self, other): - if type(self) != type(other): - other = chunk_type(other) - return cmp(self.chunk_type, other.chunk_type) - - def __repr__(self): - if self.chunk_type == PLAIN: - return 'PLAIN' - elif self.chunk_type == GROUP: - return 'GROUP' - elif self.chunk_type == CSNAME: - return 'CSNAME' - elif self.chunk_type == COMMENT: - return 'COMMENT' - elif self.chunk_type == DMATH: - return 'DMATH' - elif self.chunk_type == MATH: - return 'MATH' - elif self.chunk_type == OTHER: - return 'OTHER' - elif self.chunk_type == ACTIVE: - return 'ACTIVE' - elif self.chunk_type == GOBBLEDWHITE: - return 'GOBBLEDWHITE' - elif self.chunk_type == DENDLINE: - return 'DENDLINE' - elif self.chunk_type == ENDLINE: - return 'ENDLINE' - elif self.chunk_type == ENV: - return 'ENV' - elif self.chunk_type == CSLINE: - return 'CSLINE' - elif self.chunk_type == IGNORE: - return 'IGNORE' - elif self.chunk_type == ENDENV: - return 'ENDENV' - elif self.chunk_type == IF: - return 'IF' - else: - raise ValueError, 'chunk_type not in the_types' - -# ...and the wrapper -def chunk_type(type): - return ChunkType().init(type) - -# store a type object of the ChunkType-class-instance... -chunk_type_type = type(chunk_type(0)) - -# this class contains a part of the parsed buffer -class Chunk: - def init(self, chtype, where, data): - if type(chtype) != chunk_type_type: - chtype = chunk_type(chtype) - self.chtype = chtype - if type(where) != type(0): - raise TypeError, '\'where\' is not a number' - self.where = where - self.data = data - ##print 'CHUNK', self - return self - - def __repr__(self): - return 'chunk' + `self.chtype, self.where, self.data` - -# and the wrapper -def chunk(chtype, where, data): - return Chunk().init(chtype, where, data) - - - -error = 'partparse.error' - -# -# TeX's catcodes... -# -CC_ESCAPE = 0 -CC_LBRACE = 1 -CC_RBRACE = 2 -CC_MATHSHIFT = 3 -CC_ALIGNMENT = 4 -CC_ENDLINE = 5 -CC_PARAMETER = 6 -CC_SUPERSCRIPT = 7 -CC_SUBSCRIPT = 8 -CC_IGNORE = 9 -CC_WHITE = 10 -CC_LETTER = 11 -CC_OTHER = 12 -CC_ACTIVE = 13 -CC_COMMENT = 14 -CC_INVALID = 15 - -# and the names -cc_names = [\ - 'CC_ESCAPE', \ - 'CC_LBRACE', \ - 'CC_RBRACE', \ - 'CC_MATHSHIFT', \ - 'CC_ALIGNMENT', \ - 'CC_ENDLINE', \ - 'CC_PARAMETER', \ - 'CC_SUPERSCRIPT', \ - 'CC_SUBSCRIPT', \ - 'CC_IGNORE', \ - 'CC_WHITE', \ - 'CC_LETTER', \ - 'CC_OTHER', \ - 'CC_ACTIVE', \ - 'CC_COMMENT', \ - 'CC_INVALID', \ - ] - -# Show a list of catcode-name-symbols -def pcl(codelist): - result = '' - for i in codelist: - result = result + cc_names[i] + ', ' - return '[' + result[:-2] + ']' - -# the name of the catcode (ACTIVE, OTHER, etc.) -def pc(code): - return cc_names[code] - - -# Which catcodes make the parser stop parsing regular plaintext -regular_stopcodes = [CC_ESCAPE, CC_LBRACE, CC_RBRACE, CC_MATHSHIFT, \ - CC_ALIGNMENT, CC_PARAMETER, CC_SUPERSCRIPT, CC_SUBSCRIPT, \ - CC_IGNORE, CC_ACTIVE, CC_COMMENT, CC_INVALID, CC_ENDLINE] - -# same for scanning a control sequence name -csname_scancodes = [CC_LETTER] - -# same for gobbling LWSP -white_scancodes = [CC_WHITE] -##white_scancodes = [CC_WHITE, CC_ENDLINE] - -# make a list of all catcode id's, except for catcode ``other'' -all_but_other_codes = range(16) -del all_but_other_codes[CC_OTHER] -##print all_but_other_codes - -# when does a comment end -comment_stopcodes = [CC_ENDLINE] - -# gather all characters together, specified by a list of catcodes -def code2string(cc, codelist): - ##print 'code2string: codelist = ' + pcl(codelist), - result = '' - for category in codelist: - if cc[category]: - result = result + cc[category] - ##print 'result = ' + `result` - return result - -# automatically generate all characters of catcode other, being the -# complement set in the ASCII range (128 characters) -def make_other_codes(cc): - otherchars = range(256) # could be made 256, no problem - for category in all_but_other_codes: - if cc[category]: - for c in cc[category]: - otherchars[ord(c)] = None - result = '' - for i in otherchars: - if i != None: - result = result + chr(i) - return result - -# catcode dump (which characters have which catcodes). -def dump_cc(name, cc): - ##print '\t' + name - ##print '=' * (8+len(name)) - if len(cc) != 16: - raise TypeError, 'cc not good cat class' -## for i in range(16): -## print pc(i) + '\t' + `cc[i]` - - -# In the beginning,.... -epoch_cc = [None] * 16 -##dump_cc('epoch_cc', epoch_cc) - - -# INITEX -initex_cc = epoch_cc[:] -initex_cc[CC_ESCAPE] = '\\' -initex_cc[CC_ENDLINE], initex_cc[CC_IGNORE], initex_cc[CC_WHITE] = \ - '\n', '\0', ' ' -initex_cc[CC_LETTER] = string.uppercase + string.lowercase -initex_cc[CC_COMMENT], initex_cc[CC_INVALID] = '%', '\x7F' -#initex_cc[CC_OTHER] = make_other_codes(initex_cc) I don't need them, anyway -##dump_cc('initex_cc', initex_cc) - - -# LPLAIN: LaTeX catcode setting (see lplain.tex) -lplain_cc = initex_cc[:] -lplain_cc[CC_LBRACE], lplain_cc[CC_RBRACE] = '{', '}' -lplain_cc[CC_MATHSHIFT] = '$' -lplain_cc[CC_ALIGNMENT] = '&' -lplain_cc[CC_PARAMETER] = '#' -lplain_cc[CC_SUPERSCRIPT] = '^\x0B' # '^' and C-k -lplain_cc[CC_SUBSCRIPT] = '_\x01' # '_' and C-a -lplain_cc[CC_WHITE] = lplain_cc[CC_WHITE] + '\t' -lplain_cc[CC_ACTIVE] = '~\x0C' # '~' and C-l -lplain_cc[CC_OTHER] = make_other_codes(lplain_cc) -##dump_cc('lplain_cc', lplain_cc) - - -# Guido's LaTeX environment catcoded '_' as ``other'' -# my own purpose catlist -my_cc = lplain_cc[:] -my_cc[CC_SUBSCRIPT] = my_cc[CC_SUBSCRIPT][1:] # remove '_' here -my_cc[CC_OTHER] = my_cc[CC_OTHER] + '_' # add it to OTHER list -dump_cc('my_cc', my_cc) - - - -# needed for un_re, my equivalent for regexp-quote in Emacs -re_meaning = '\\[]^$' - -def un_re(str): - result = '' - for i in str: - if i in re_meaning: - result = result + '\\' - result = result + i - return result - -# NOTE the negate ('^') operator in *some* of the regexps below -def make_rc_regular(cc): - # problems here if '[]' are included!! - return regex.compile('[' + code2string(cc, regular_stopcodes) + ']') - -def make_rc_cs_scan(cc): - return regex.compile('[^' + code2string(cc, csname_scancodes) + ']') - -def make_rc_comment(cc): - return regex.compile('[' + code2string(cc, comment_stopcodes) + ']') - -def make_rc_endwhite(cc): - return regex.compile('[^' + code2string(cc, white_scancodes) + ']') - - - -# regular: normal mode: -rc_regular = make_rc_regular(my_cc) - -# scan: scan a command sequence e.g. `newlength' or `mbox' or `;', `,' or `$' -rc_cs_scan = make_rc_cs_scan(my_cc) -rc_comment = make_rc_comment(my_cc) -rc_endwhite = make_rc_endwhite(my_cc) - - -# parseit (BUF, PARSEMODE=mode(MODE_REGULAR), START=0, RECURSION-LEVEL=0) -# RECURSION-LEVEL will is incremented on entry. -# result contains the list of chunks returned -# together with this list, the buffer position is returned - -# RECURSION-LEVEL will be set to zero *again*, when recursively a -# {,D}MATH-mode scan has been enetered. -# This has been done in order to better check for environment-mismatches - -def parseit(buf, *rest): - global lineno - - if len(rest) == 3: - parsemode, start, lvl = rest - elif len(rest) == 2: - parsemode, start, lvl = rest + (0, ) - elif len(rest) == 1: - parsemode, start, lvl = rest + (0, 0) - elif len(rest) == 0: - parsemode, start, lvl = mode(MODE_REGULAR), 0, 0 - else: - raise TypeError, 'usage: parseit(buf[, parsemode[, start[, level]]])' - result = [] - end = len(buf) - if lvl == 0 and parsemode == mode(MODE_REGULAR): - lineno = 1 - lvl = lvl + 1 - - ##print 'parseit(' + epsilon(buf, start) + ', ' + `parsemode` + ', ' + `start` + ', ' + `lvl` + ')' - - # - # some of the more regular modes... - # - - if parsemode in (mode(MODE_REGULAR), mode(MODE_DMATH), mode(MODE_MATH)): - cstate = [] - newpos = start - curpmode = parsemode - while 1: - where = newpos - #print '\tnew round: ' + epsilon(buf, where) - if where == end: - if lvl > 1 or curpmode != mode(MODE_REGULAR): - # not the way we started... - raise EOFError, 'premature end of file.' + lle(lvl, buf, where) - # the real ending of lvl-1 parse - return end, result - - pos = rc_regular.search(buf, where) - - if pos < 0: - pos = end - - if pos != where: - newpos, c = pos, chunk(PLAIN, where, (where, pos)) - result.append(c) - continue - - - # - # ok, pos == where and pos != end - # - foundchar = buf[where] - if foundchar in my_cc[CC_LBRACE]: - # recursive subgroup parse... - newpos, data = parseit(buf, curpmode, where+1, lvl) - result.append(chunk(GROUP, where, data)) - - elif foundchar in my_cc[CC_RBRACE]: - if lvl <= 1: - raise error, 'ENDGROUP while in base level.' + lle(lvl, buf, where) - if lvl == 1 and mode != mode(MODE_REGULAR): - raise error, 'endgroup while in math mode. +lin() + epsilon(buf, where)' - return where + 1, result - - elif foundchar in my_cc[CC_ESCAPE]: - # - # call the routine that actually deals with - # this problem. If do_ret is None, than - # return the value of do_ret - # - # Note that handle_cs might call this routine - # recursively again... - # - do_ret, newpos = handlecs(buf, where, \ - curpmode, lvl, result, end) - if do_ret != None: - return do_ret - - elif foundchar in my_cc[CC_COMMENT]: - newpos, data = parseit(buf, \ - mode(MODE_COMMENT), where+1, lvl) - result.append(chunk(COMMENT, where, data)) - - elif foundchar in my_cc[CC_MATHSHIFT]: - # note that recursive calls to math-mode - # scanning are called with recursion-level 0 - # again, in order to check for bad mathend - # - if where + 1 != end and \ - buf[where + 1] in \ - my_cc[CC_MATHSHIFT]: - # - # double mathshift, e.g. '$$' - # - if curpmode == mode(MODE_REGULAR): - newpos, data = parseit(buf, \ - mode(MODE_DMATH), \ - where+2, 0) - result.append(chunk(DMATH, \ - where, data)) - elif curpmode == mode(MODE_MATH): - raise error, 'wrong math delimiiter' + lin() + epsilon(buf, where) - elif lvl != 1: - raise error, 'bad mathend.' + \ - lle(lvl, buf, where) - else: - return where + 2, result - else: - # - # single math shift, e.g. '$' - # - if curpmode == mode(MODE_REGULAR): - newpos, data = parseit(buf, \ - mode(MODE_MATH), \ - where+1, 0) - result.append(chunk(MATH, \ - where, data)) - elif curpmode == mode(MODE_DMATH): - raise error, 'wrong math delimiiter' + lin() + epsilon(buf, where) - elif lvl != 1: - raise error, 'bad mathend.' + \ - lv(lvl, buf, where) - else: - return where + 1, result - - elif foundchar in my_cc[CC_IGNORE]: - print 'warning: ignored char', `foundchar` - newpos = where + 1 - - elif foundchar in my_cc[CC_ACTIVE]: - result.append(chunk(ACTIVE, where, foundchar)) - newpos = where + 1 - - elif foundchar in my_cc[CC_INVALID]: - raise error, 'invalid char ' + `foundchar` - newpos = where + 1 - - elif foundchar in my_cc[CC_ENDLINE]: - # - # after an end of line, eat the rest of - # whitespace on the beginning of the next line - # this is what LaTeX more or less does - # - # also, try to indicate double newlines (\par) - # - lineno = lineno + 1 - savedwhere = where - newpos, dummy = parseit(buf, mode(MODE_GOBBLEWHITE), where + 1, lvl) - if newpos != end and buf[newpos] in \ - my_cc[CC_ENDLINE]: - result.append(chunk(DENDLINE, \ - savedwhere, foundchar)) - else: - result.append(chunk(ENDLINE, \ - savedwhere, foundchar)) - else: - result.append(chunk(OTHER, where, foundchar)) - newpos = where + 1 - - elif parsemode == mode(MODE_CS_SCAN): - # - # scan for a control sequence token. `\ape', `\nut' or `\%' - # - if start == end: - raise EOFError, 'can\'t find end of csname' - pos = rc_cs_scan.search(buf, start) - if pos < 0: - pos = end - if pos == start: - # first non-letter right where we started the search - # ---> the control sequence name consists of one single - # character. Also: don't eat white space... - if buf[pos] in my_cc[CC_ENDLINE]: - lineno = lineno + 1 - pos = pos + 1 - return pos, (start, pos) - else: - spos = pos - if buf[pos] == '\n': - lineno = lineno + 1 - spos = pos + 1 - pos2, dummy = parseit(buf, \ - mode(MODE_GOBBLEWHITE), spos, lvl) - return pos2, (start, pos) - - elif parsemode == mode(MODE_GOBBLEWHITE): - if start == end: - return start, '' - pos = rc_endwhite.search(buf, start) - if pos < 0: - pos = start - return pos, (start, pos) - - elif parsemode == mode(MODE_COMMENT): - pos = rc_comment.search(buf, start) - lineno = lineno + 1 - if pos < 0: - print 'no newline perhaps?' - raise EOFError, 'can\'t find end of comment' - pos = pos + 1 - pos2, dummy = parseit(buf, mode(MODE_GOBBLEWHITE), pos, lvl) - return pos2, (start, pos) - - - else: - raise error, 'Unknown mode (' + `parsemode` + ')' - - -#moreresult = cswitch(buf[x1:x2], buf, newpos, parsemode, lvl) - -#boxcommands = 'mbox', 'fbox' -#defcommands = 'def', 'newcommand' - -endverbstr = '\\end{verbatim}' - -re_endverb = regex.compile(un_re(endverbstr)) - -# -# handlecs: helper function for parseit, for the special thing we might -# wanna do after certain command control sequences -# returns: None or return_data, newpos -# -# in the latter case, the calling function is instructed to immediately -# return with the data in return_data -# -def handlecs(buf, where, curpmode, lvl, result, end): - global lineno - - # get the control sequence name... - newpos, data = parseit(buf, mode(MODE_CS_SCAN), where+1, lvl) - saveddata = data - - if s(buf, data) in ('begin', 'end'): - # skip the expected '{' and get the LaTeX-envname '}' - newpos, data = parseit(buf, mode(MODE_REGULAR), newpos+1, lvl) - if len(data) != 1: - raise error, 'expected 1 chunk of data.' + \ - lle(lvl, buf, where) - - # yucky, we've got an environment - envname = s(buf, data[0].data) - ##print 'FOUND ' + s(buf, saveddata) + '. Name ' + `envname` + '.' + lv(lvl) - if s(buf, saveddata) == 'begin' and envname == 'verbatim': - # verbatim deserves special treatment - pos = re_endverb.search(buf, newpos) - if pos < 0: - raise error, `endverbstr` + ' not found.' + lle(lvl, buf, where) - result.append(chunk(ENV, where, (envname, [chunk(PLAIN, newpos, (newpos, pos))]))) - newpos = pos + len(endverbstr) - - elif s(buf, saveddata) == 'begin': - # start parsing recursively... If that parse returns - # from an '\end{...}', then should the last item of - # the returned data be a string containing the ended - # environment - newpos, data = parseit(buf, curpmode, newpos, lvl) - if not data or type(data[-1]) != type(''): - raise error, 'missing \'end\'' + lle(lvl, buf, where) + epsilon(buf, newpos) - retenv = data[-1] - del data[-1] - if retenv != envname: - #[`retenv`, `envname`] - raise error, 'environments do not match.' + \ - lle(lvl, buf, where) + \ - epsilon(buf, newpos) - result.append(chunk(ENV, where, (retenv, data))) - else: - # 'end'... append the environment name, as just - # pointed out, and order parsit to return... - result.append(envname) - ##print 'POINT of return: ' + epsilon(buf, newpos) - # the tuple will be returned by parseit - return (newpos, result), newpos - - # end of \begin ... \end handling - - elif s(buf, data)[0:2] == 'if': - # another scary monster: the 'if' directive - flag = s(buf, data)[2:] - - # recursively call parseit, just like environment above.. - # the last item of data should contain the if-termination - # e.g., 'else' of 'fi' - newpos, data = parseit(buf, curpmode, newpos, lvl) - if not data or data[-1] not in ('else', 'fi'): - raise error, 'wrong if... termination' + \ - lle(lvl, buf, where) + epsilon(buf, newpos) - - ifterm = data[-1] - del data[-1] - # 0 means dont_negate flag - result.append(chunk(IF, where, (flag, 0, data))) - if ifterm == 'else': - # do the whole thing again, there is only one way - # to end this one, by 'fi' - newpos, data = parseit(buf, curpmode, newpos, lvl) - if not data or data[-1] not in ('fi', ): - raise error, 'wrong if...else... termination' \ - + lle(lvl, buf, where) \ - + epsilon(buf, newpos) - - ifterm = data[-1] - del data[-1] - result.append(chunk(IF, where, (flag, 1, data))) - #done implicitely: return None, newpos - - elif s(buf, data) in ('else', 'fi'): - result.append(s(buf, data)) - # order calling party to return tuple - return (newpos, result), newpos - - # end of \if, \else, ... \fi handling - - elif s(buf, saveddata) == 'verb': - x2 = saveddata[1] - result.append(chunk(CSNAME, where, data)) - if x2 == end: - raise error, 'premature end of command.' + lle(lvl, buf, where) - delimchar = buf[x2] - ##print 'VERB: delimchar ' + `delimchar` - pos = regex.compile(un_re(delimchar)).search(buf, x2 + 1) - if pos < 0: - raise error, 'end of \'verb\' argument (' + \ - `delimchar` + ') not found.' + \ - lle(lvl, buf, where) - result.append(chunk(GROUP, x2, [chunk(PLAIN, x2+1, (x2+1, pos))])) - newpos = pos + 1 - else: - result.append(chunk(CSNAME, where, data)) - return None, newpos - -# this is just a function to get the string value if the possible data-tuple -def s(buf, data): - if type(data) == type(''): - return data - if len(data) != 2 or not (type(data[0]) == type(data[1]) == type(0)): - raise TypeError, 'expected tuple of 2 integers' - x1, x2 = data - return buf[x1:x2] - - -##length, data1, i = getnextarg(length, buf, pp, i + 1) - -# make a deep-copy of some chunks -def crcopy(r): - result = [] - for x in r: - result.append(chunkcopy(x)) - return result - - - -# copy a chunk, would better be a method of class Chunk... -def chunkcopy(ch): - if ch.chtype == chunk_type(GROUP): - listc = ch.data[:] - for i in range(len(listc)): - listc[i] = chunkcopy(listc[i]) - return chunk(GROUP, ch.where, listc) - else: - return chunk(ch.chtype, ch.where, ch.data) - - -# get next argument for TeX-macro, flatten a group (insert between) -# or return Command Sequence token, or give back one character -def getnextarg(length, buf, pp, item): - - ##wobj = Wobj().init() - ##dumpit(buf, wobj.write, pp[item:min(length, item + 5)]) - ##print 'GETNEXTARG, (len, item) =', `length, item` + ' ---> ' + wobj.data + ' <---' - - while item < length and pp[item].chtype == chunk_type(ENDLINE): - del pp[item] - length = length - 1 - if item >= length: - raise error, 'no next arg.' + epsilon(buf, pp[-1].where) - if pp[item].chtype == chunk_type(GROUP): - newpp = pp[item].data - del pp[item] - length = length - 1 - changeit(buf, newpp) - length = length + len(newpp) - pp[item:item] = newpp - item = item + len(newpp) - if len(newpp) < 10: - wobj = Wobj().init() - dumpit(buf, wobj.write, newpp) - ##print 'GETNEXTARG: inserted ' + `wobj.data` - return length, item - elif pp[item].chtype == chunk_type(PLAIN): - #grab one char - print 'WARNING: grabbing one char' - if len(s(buf, pp[item].data)) > 1: - pp.insert(item, chunk(PLAIN, pp[item].where, s(buf, pp[item].data)[:1])) - item, length = item+1, length+1 - pp[item].data = s(buf, pp[item].data)[1:] - else: - item = item+1 - return length, item - else: - try: - str = `s(buf, ch.data)` - except TypeError: - str = `ch.data` - if len(str) > 400: - str = str[:400] + '...' - print 'GETNEXTARG:', ch.chtype, 'not handled, data ' + str - return length, item - - -# this one is needed to find the end of LaTeX's optional argument, like -# item[...] -re_endopt = regex.compile(']') - -# get a LaTeX-optional argument, you know, the square braces '[' and ']' -def getoptarg(length, buf, pp, item): - - wobj = Wobj().init() - dumpit(buf, wobj.write, pp[item:min(length, item + 5)]) - ##print 'GETOPTARG, (len, item) =', `length, item` + ' ---> ' + wobj.data + ' <---' - - if item >= length or \ - pp[item].chtype != chunk_type(PLAIN) or \ - s(buf, pp[item].data)[0] != '[': - return length, item - - pp[item].data = s(buf, pp[item].data)[1:] - if len(pp[item].data) == 0: - del pp[item] - length = length-1 - - while 1: - if item == length: - raise error, 'No end of optional arg found' - if pp[item].chtype == chunk_type(PLAIN): - text = s(buf, pp[item].data) - pos = re_endopt.search(text) - if pos >= 0: - pp[item].data = text[:pos] - if pos == 0: - del pp[item] - length = length-1 - else: - item=item+1 - text = text[pos+1:] - - while text and text[0] in ' \t': - text = text[1:] - - if text: - pp.insert(item, chunk(PLAIN, 0, text)) - length = length + 1 - return length, item - - item = item+1 - - -# Wobj just add write-requests to the ``data'' attribute -class Wobj: - def init(self): - self.data = '' - return self - def write(self, data): - self.data = self.data + data - -# ignore these commands -ignoredcommands = ('bcode', 'ecode') -# map commands like these to themselves as plaintext -wordsselves = ('UNIX', 'ABC', 'C', 'ASCII', 'EOF') -# \{ --> {, \} --> }, etc -themselves = ('{', '}', '.', '@') + wordsselves -# these ones also themselves (see argargs macro in myformat.sty) -inargsselves = (',', '[', ']', '(', ')') -# this is how *I* would show the difference between emph and strong -# code 1 means: fold to uppercase -markcmds = {'code': ('', ''), 'var': 1, 'emph': ('_', '_'), \ - 'strong': ('*', '*')} - -# recognise patter {\FONTCHANGE-CMD TEXT} to \MAPPED-FC-CMD{TEXT} -fontchanges = {'rm': 'r', 'it': 'i', 'em': 'emph', 'bf': 'b', 'tt': 't'} - -# transparent for these commands -for_texi = ('emph', 'var', 'strong', 'code', 'kbd', 'key', 'dfn', 'samp', \ - 'r', 'i', 't') - - -# try to remove macros and return flat text -def flattext(buf, pp): - pp = crcopy(pp) - ##print '---> FLATTEXT ' + `pp` - wobj = Wobj().init() - - i, length = 0, len(pp) - while 1: - if len(pp) != length: - raise 'FATAL', 'inconsistent length' - if i >= length: - break - ch = pp[i] - i = i+1 - if ch.chtype == chunk_type(PLAIN): - pass - elif ch.chtype == chunk_type(CSNAME): - if s(buf, ch.data) in themselves or hist.inargs and s(buf, ch.data) in inargsselves: - ch.chtype = chunk_type(PLAIN) - elif s(buf, ch.data) == 'e': - ch.chtype = chunk_type(PLAIN) - ch.data = '\\' - elif len(s(buf, ch.data)) == 1 \ - and s(buf, ch.data) in onlylatexspecial: - ch.chtype = chunk_type(PLAIN) - # if it is followed by an empty group, - # remove that group, it was needed for - # a true space - if i < length \ - and pp[i].chtype==chunk_type(GROUP) \ - and len(pp[i].data) == 0: - del pp[i] - length = length-1 - - elif s(buf, ch.data) in markcmds.keys(): - length, newi = getnextarg(length, buf, pp, i) - str = flattext(buf, pp[i:newi]) - del pp[i:newi] - length = length - (newi - i) - ch.chtype = chunk_type(PLAIN) - markcmd = s(buf, ch.data) - x = markcmds[markcmd] - if type(x) == type(()): - pre, after = x - str = pre+str+after - elif x == 1: - str = string.upper(str) - else: - raise 'FATAL', 'corrupt markcmds' - ch.data = str - else: - if s(buf, ch.data) not in ignoredcommands: - print 'WARNING: deleting command ' + `s(buf, ch.data)` - print 'PP' + `pp[i-1]` - del pp[i-1] - i, length = i-1, length-1 - elif ch.chtype == chunk_type(GROUP): - length, newi = getnextarg(length, buf, pp, i-1) - i = i-1 -## str = flattext(buf, crcopy(pp[i-1:newi])) -## del pp[i:newi] -## length = length - (newi - i) -## ch.chtype = chunk_type(PLAIN) -## ch.data = str - else: - pass - - dumpit(buf, wobj.write, pp) - ##print 'FLATTEXT: RETURNING ' + `wobj.data` - return wobj.data - -# try to generate node names (a bit shorter than the chapter title) -# note that the \nodename command (see elsewhere) overules these efforts -def invent_node_names(text): - words = string.split(text) - - ##print 'WORDS ' + `words` - - if len(words) == 2 \ - and string.lower(words[0]) == 'built-in' \ - and string.lower(words[1]) not in ('modules', 'functions'): - return words[1] - if len(words) == 3 and string.lower(words[1]) == 'module': - return words[2] - if len(words) == 3 and string.lower(words[1]) == 'object': - return string.join(words[0:2]) - if len(words) > 4 and string.lower(string.join(words[-4:])) == \ - 'methods and data attributes': - return string.join(words[:2]) - return text - -re_commas_etc = regex.compile('[,`\'@{}]') - -re_whitespace = regex.compile('[ \t]*') - - -##nodenamecmd = next_command_p(length, buf, pp, newi, 'nodename') - -# look if the next non-white stuff is also a command, resulting in skipping -# double endlines (DENDLINE) too, and thus omitting \par's -# Sometimes this is too much, maybe consider DENDLINE's as stop -def next_command_p(length, buf, pp, i, cmdname): - - while 1: - if i >= len(pp): - break - ch = pp[i] - i = i+1 - if ch.chtype == chunk_type(ENDLINE): - continue - if ch.chtype == chunk_type(DENDLINE): - continue - if ch.chtype == chunk_type(PLAIN): - if re_whitespace.search(s(buf, ch.data)) == 0 and \ - re_whitespace.match(s(buf, ch.data)) == len(s(buf, ch.data)): - continue - return -1 - if ch.chtype == chunk_type(CSNAME): - if s(buf, ch.data) == cmdname: - return i # _after_ the command - return -1 - return -1 - - -# things that are special to LaTeX, but not to texi.. -onlylatexspecial = '_~^$#&%' - -class Struct: pass - -hist = Struct() -out = Struct() - -def startchange(): - global hist, out - - hist.inenv = [] - hist.nodenames = [] - hist.cindex = [] - hist.inargs = 0 - hist.enumeratenesting, hist.itemizenesting = 0, 0 - - out.doublenodes = [] - out.doublecindeces = [] - - -spacech = [chunk(PLAIN, 0, ' ')] -commach = [chunk(PLAIN, 0, ', ')] -cindexch = [chunk(CSLINE, 0, 'cindex')] - -# the standard variation in symbols for itemize -itemizesymbols = ['bullet', 'minus', 'dots'] - -# same for enumerate -enumeratesymbols = ['1', 'A', 'a'] - -## -## \begin{ {func,data,exc}desc }{name}... -## the resulting texi-code is dependent on the contents of indexsubitem -## - -# indexsubitem: `['XXX', 'function'] -# funcdesc: -# deffn {`idxsi`} NAME (FUNCARGS) - -# indexsubitem: `['XXX', 'method']` -# funcdesc: -# defmethod {`idxsi[0]`} NAME (FUNCARGS) - -# indexsubitem: `['in', 'module', 'MODNAME']' -# datadesc: -# defcv data {`idxsi[1:]`} NAME -# excdesc: -# defcv exception {`idxsi[1:]`} NAME -# funcdesc: -# deffn {function of `idxsi[1:]`} NAME (FUNCARGS) - -# indexsubitem: `['OBJECT', 'attribute']' -# datadesc -# defcv attribute {`OBJECT`} NAME - - -## this routine will be called on \begin{funcdesc}{NAME}{ARGS} -## or \funcline{NAME}{ARGS} -## -def do_funcdesc(length, buf, pp, i): - startpoint = i-1 - ch = pp[startpoint] - wh = ch.where - length, newi = getnextarg(length, buf, pp, i) - funcname = chunk(GROUP, wh, pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - save = hist.inargs - hist.inargs = 1 - length, newi = getnextarg(length, buf, pp, i) - hist.inargs = save - del save - the_args = [chunk(PLAIN, wh, '()'[0])] + \ - pp[i:newi] + \ - [chunk(PLAIN, wh, '()'[1])] - del pp[i:newi] - length = length - (newi-i) - - idxsi = hist.indexsubitem # words - command = '' - cat_class = '' - if idxsi and idxsi[-1] == 'method': - command = 'defmethod' - cat_class = string.join(idxsi[:-1]) - elif len(idxsi) == 2 and idxsi[1] == 'function': - command = 'deffn' - cat_class = string.join(idxsi) - elif len(idxsi) == 3 and idxsi[:2] == ['in', 'module']: - command = 'deffn' - cat_class = 'function of ' + string.join(idxsi[1:]) - - if not command: - raise error, 'don\'t know what to do with indexsubitem ' + `idxsi` - - ch.chtype = chunk_type(CSLINE) - ch.data = command - - cslinearg = [chunk(GROUP, wh, [chunk(PLAIN, wh, cat_class)])] - cslinearg.append(chunk(PLAIN, wh, ' ')) - cslinearg.append(funcname) - cslinearg.append(chunk(PLAIN, wh, ' ')) - l = len(cslinearg) - cslinearg[l:l] = the_args - - pp.insert(i, chunk(GROUP, wh, cslinearg)) - i, length = i+1, length+1 - hist.command = command - return length, i - - -## this routine will be called on \begin{excdesc}{NAME} -## or \excline{NAME} -## -def do_excdesc(length, buf, pp, i): - startpoint = i-1 - ch = pp[startpoint] - wh = ch.where - length, newi = getnextarg(length, buf, pp, i) - excname = chunk(GROUP, wh, pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - - idxsi = hist.indexsubitem # words - command = '' - cat_class = '' - class_class = '' - if len(idxsi) == 2 and idxsi[1] == 'exception': - command = 'defvr' - cat_class = string.join(idxsi) - elif len(idxsi) == 3 and idxsi[:2] == ['in', 'module']: - command = 'defcv' - cat_class = 'exception' - class_class = string.join(idxsi[1:]) - elif len(idxsi) == 4 and idxsi[:3] == ['exception', 'in', 'module']: - command = 'defcv' - cat_class = 'exception' - class_class = string.join(idxsi[2:]) - - - if not command: - raise error, 'don\'t know what to do with indexsubitem ' + `idxsi` - - ch.chtype = chunk_type(CSLINE) - ch.data = command - - cslinearg = [chunk(GROUP, wh, [chunk(PLAIN, wh, cat_class)])] - cslinearg.append(chunk(PLAIN, wh, ' ')) - if class_class: - cslinearg.append(chunk(GROUP, wh, [chunk(PLAIN, wh, class_class)])) - cslinearg.append(chunk(PLAIN, wh, ' ')) - cslinearg.append(excname) - - pp.insert(i, chunk(GROUP, wh, cslinearg)) - i, length = i+1, length+1 - hist.command = command - return length, i - -## same for datadesc or dataline... -def do_datadesc(length, buf, pp, i): - startpoint = i-1 - ch = pp[startpoint] - wh = ch.where - length, newi = getnextarg(length, buf, pp, i) - dataname = chunk(GROUP, wh, pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - - idxsi = hist.indexsubitem # words - command = '' - cat_class = '' - class_class = '' - if len(idxsi) == 2 and idxsi[1] == 'attribute': - command = 'defcv' - cat_class = 'attribute' - class_class = idxsi[0] - elif len(idxsi) == 3 and idxsi[:2] == ['in', 'module']: - command = 'defcv' - cat_class = 'data' - class_class = string.join(idxsi[1:]) - elif len(idxsi) == 4 and idxsi[:3] == ['data', 'in', 'module']: - command = 'defcv' - cat_class = 'data' - class_class = string.join(idxsi[2:]) - - - if not command: - raise error, 'don\'t know what to do with indexsubitem ' + `idxsi` - - ch.chtype = chunk_type(CSLINE) - ch.data = command - - cslinearg = [chunk(GROUP, wh, [chunk(PLAIN, wh, cat_class)])] - cslinearg.append(chunk(PLAIN, wh, ' ')) - if class_class: - cslinearg.append(chunk(GROUP, wh, [chunk(PLAIN, wh, class_class)])) - cslinearg.append(chunk(PLAIN, wh, ' ')) - cslinearg.append(dataname) - - pp.insert(i, chunk(GROUP, wh, cslinearg)) - i, length = i+1, length+1 - hist.command = command - return length, i - - -# regular indices: those that are not set in tt font by default.... -regindices = ('cindex', ) - -# remove illegal characters from node names -def rm_commas_etc(text): - result = '' - changed = 0 - while 1: - pos = re_commas_etc.search(text) - if pos >= 0: - changed = 1 - result = result + text[:pos] - text = text[pos+1:] - else: - result = result + text - break - if changed: - print 'Warning: nodename changhed to ' + `result` - - return result - -# boolean flags -flags = {'texi': 1} - - -## -## changeit: the actual routine, that changes the contents of the parsed -## chunks -## - -def changeit(buf, pp): - global onlylatexspecial, hist, out - - i, length = 0, len(pp) - while 1: - # sanity check: length should always equal len(pp) - if len(pp) != length: - raise 'FATAL', 'inconsistent length. thought ' + `length` + ', but should really be ' + `len(pp)` - if i >= length: - break - ch = pp[i] - i = i + 1 - - if type(ch) == type(''): - #normally, only chunks are present in pp, - # but in some cases, some extra info - # has been inserted, e.g., the \end{...} clauses - raise 'FATAL', 'got string, probably too many ' + `end` - - if ch.chtype == chunk_type(GROUP): - # check for {\em ...} constructs - if ch.data and \ - ch.data[0].chtype == chunk_type(CSNAME) and \ - s(buf, ch.data[0].data) in fontchanges.keys(): - k = s(buf, ch.data[0].data) - del ch.data[0] - pp.insert(i-1, chunk(CSNAME, ch.where, fontchanges[k])) - length, i = length+1, i+1 - - # recursively parse the contents of the group - changeit(buf, ch.data) - - elif ch.chtype == chunk_type(IF): - # \if... - flag, negate, data = ch.data - ##print 'IF: flag, negate = ' + `flag, negate` - if flag not in flags.keys(): - raise error, 'unknown flag ' + `flag` - - value = flags[flag] - if negate: - value = (not value) - del pp[i-1] - length, i = length-1, i-1 - if value: - pp[i:i] = data - length = length + len(data) - - - elif ch.chtype == chunk_type(ENV): - # \begin{...} .... - envname, data = ch.data - - #push this environment name on stack - hist.inenv.insert(0, envname) - - #append an endenv chunk after grouped data - data.append(chunk(ENDENV, ch.where, envname)) - ##[`data`] - - #delete this object - del pp[i-1] - i, length = i-1, length-1 - - #insert found data - pp[i:i] = data - length = length + len(data) - - if envname == 'verbatim': - pp[i:i] = [chunk(CSLINE, ch.where, 'example'), \ - chunk(GROUP, ch.where, [])] - length, i = length+2, i+2 - - elif envname == 'itemize': - if hist.itemizenesting > len(itemizesymbols): - raise error, 'too deep itemize nesting' - ingroupch = [chunk(CSNAME, ch.where,\ - itemizesymbols[hist.itemizenesting])] - hist.itemizenesting = hist.itemizenesting + 1 - pp[i:i] = [chunk(CSLINE, ch.where, 'itemize'),\ - chunk(GROUP, ch.where, ingroupch)] - length, i = length+2, i+2 - - elif envname == 'enumerate': - if hist.enumeratenesting > len(enumeratesymbols): - raise error, 'too deep enumerate nesting' - ingroupch = [chunk(PLAIN, ch.where,\ - enumeratesymbols[hist.enumeratenesting])] - hist.enumeratenesting = hist.enumeratenesting + 1 - pp[i:i] = [chunk(CSLINE, ch.where, 'enumerate'),\ - chunk(GROUP, ch.where, ingroupch)] - length, i = length+2, i+2 - - elif envname == 'description': - ingroupch = [chunk(CSNAME, ch.where, 'b')] - pp[i:i] = [chunk(CSLINE, ch.where, 'table'), \ - chunk(GROUP, ch.where, ingroupch)] - length, i = length+2, i+2 - - elif envname == 'tableiii': - wh = ch.where - newcode = [] - - #delete tabular format description - # e.g., {|l|c|l|} - length, newi = getnextarg(length, buf, pp, i) - del pp[i:newi] - length = length - (newi-i) - - newcode.append(chunk(CSLINE, wh, 'table')) - ingroupch = [chunk(CSNAME, wh, 'asis')] - newcode.append(chunk(GROUP, wh, ingroupch)) - newcode.append(chunk(CSLINE, wh, 'item')) - - #get the name of macro for @item - # e.g., {code} - length, newi = getnextarg(length, buf, pp, i) - - if newi-i != 1: - raise error, 'Sorry, expected 1 chunk argument' - if pp[i].chtype != chunk_type(PLAIN): - raise error, 'Sorry, expected plain text argument' - hist.itemargmacro = s(buf, pp[i].data) - del pp[i:newi] - length = length - (newi-i) - - for count in range(3): - length, newi = getnextarg(length, buf, pp, i) - emphgroup = [\ - chunk(CSNAME, wh, 'emph'), \ - chunk(GROUP, 0, pp[i:newi])] - del pp[i:newi] - length = length - (newi-i) - if count == 0: - itemarg = emphgroup - elif count == 2: - itembody = itembody + \ - [chunk(PLAIN, wh, ' --- ')] + \ - emphgroup - else: - itembody = emphgroup - newcode.append(chunk(GROUP, wh, itemarg)) - newcode = newcode + itembody + [chunk(DENDLINE, wh, '\n')] - pp[i:i] = newcode - l = len(newcode) - length, i = length+l, i+l - del newcode, l - - if length != len(pp): - raise 'STILL, SOMETHING wrong', `i` - - - elif envname == 'funcdesc': - pp.insert(i, chunk(PLAIN, ch.where, '')) - i, length = i+1, length+1 - length, i = do_funcdesc(length, buf, pp, i) - - elif envname == 'excdesc': - pp.insert(i, chunk(PLAIN, ch.where, '')) - i, length = i+1, length+1 - length, i = do_excdesc(length, buf, pp, i) - - elif envname == 'datadesc': - pp.insert(i, chunk(PLAIN, ch.where, '')) - i, length = i+1, length+1 - length, i = do_datadesc(length, buf, pp, i) - - else: - print 'WARNING: don\'t know what to do with env ' + `envname` - - elif ch.chtype == chunk_type(ENDENV): - envname = ch.data - if envname != hist.inenv[0]: - raise error, '\'end\' does not match. Name ' + `envname` + ', expected ' + `hist.inenv[0]` - del hist.inenv[0] - del pp[i-1] - i, length = i-1, length-1 - - if envname == 'verbatim': - pp[i:i] = [\ - chunk(CSLINE, ch.where, 'end'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, 'example')])] - i, length = i+2, length+2 - elif envname == 'itemize': - hist.itemizenesting = hist.itemizenesting - 1 - pp[i:i] = [\ - chunk(CSLINE, ch.where, 'end'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, 'itemize')])] - i, length = i+2, length+2 - elif envname == 'enumerate': - hist.enumeratenesting = hist.enumeratenesting-1 - pp[i:i] = [\ - chunk(CSLINE, ch.where, 'end'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, 'enumerate')])] - i, length = i+2, length+2 - elif envname == 'description': - pp[i:i] = [\ - chunk(CSLINE, ch.where, 'end'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, 'table')])] - i, length = i+2, length+2 - elif envname == 'tableiii': - pp[i:i] = [\ - chunk(CSLINE, ch.where, 'end'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, 'table')])] - i, length = i+2, length + 2 - pp.insert(i, chunk(DENDLINE, ch.where, '\n')) - i, length = i+1, length+1 - - elif envname in ('funcdesc', 'excdesc', 'datadesc'): - pp[i:i] = [\ - chunk(CSLINE, ch.where, 'end'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, hist.command)])] - i, length = i+2, length+2 - else: - print 'WARNING: ending env ' + `envname` + 'has no actions' - - elif ch.chtype == chunk_type(CSNAME): - # control name transformations - if s(buf, ch.data) in ignoredcommands: - del pp[i-1] - i, length = i-1, length-1 - elif s(buf, ch.data) == '@' and \ - i != length and \ - pp[i].chtype == chunk_type(PLAIN) and \ - s(buf, pp[i].data)[0] == '.': - # \@. --> \. --> @. - ch.data = '.' - del pp[i] - length = length-1 - elif s(buf, ch.data) == '\\': - # \\ --> \* --> @* - ch.data = '*' - elif len(s(buf, ch.data)) == 1 and \ - s(buf, ch.data) in onlylatexspecial: - ch.chtype = chunk_type(PLAIN) - # check if such a command is followed by - # an empty group: e.g., `\%{}'. If so, remove - # this empty group too - if i < length and \ - pp[i].chtype == chunk_type(GROUP) \ - and len(pp[i].data) == 0: - del pp[i] - length = length-1 - - elif hist.inargs and s(buf, ch.data) in inargsselves: - # This is the special processing of the - # arguments of the \begin{funcdesc}... or - # \funcline... arguments - # \, --> , \[ --> [, \] --> ] - ch.chtype = chunk_type(PLAIN) - - elif s(buf, ch.data) == 'renewcommand': - # \renewcommand{\indexsubitem}.... - i, length = i-1, length-1 - del pp[i] - length, newi = getnextarg(length, buf, pp, i) - if newi-i == 1 \ - and i < length \ - and pp[i].chtype == chunk_type(CSNAME) \ - and s(buf, pp[i].data) == 'indexsubitem': - del pp[i:newi] - length = length - (newi-i) - length, newi = getnextarg(length, buf, pp, i) - text = flattext(buf, pp[i:newi]) - if text[0] != '(' or text[-1] != ')': - raise error, 'expected indexsubitme enclosed in braces' - words = string.split(text[1:-1]) - hist.indexsubitem = words - del text, words - else: - print 'WARNING: renewcommand with unsupported arg removed' - del pp[i:newi] - length = length - (newi-i) - - elif s(buf, ch.data) == 'item': - ch.chtype = chunk_type(CSLINE) - length, newi = getoptarg(length, buf, pp, i) - ingroupch = pp[i:newi] - del pp[i:newi] - length = length - (newi-i) - pp.insert(i, chunk(GROUP, ch.where, ingroupch)) - i, length = i+1, length+1 - - elif s(buf, ch.data) == 'ttindex': - idxsi = hist.indexsubitem - - cat_class = '' - if len(idxsi) >= 2 and idxsi[1] in \ - ('method', 'function'): - command = 'findex' - elif len(idxsi) >= 2 and idxsi[1] in \ - ('exception', 'object'): - command = 'vindex' - else: - print 'WARNING: can\'t categorize ' + `idxsi` + ' for \'ttindex\' command' - command = 'cindex' - - if not cat_class: - cat_class = '('+string.join(idxsi)+')' - - ch.chtype = chunk_type(CSLINE) - ch.data = command - - length, newi = getnextarg(length, buf, pp, i) - arg = pp[i:newi] - del pp[i:newi] - length = length - (newi-i) - - cat_arg = [chunk(PLAIN, ch.where, cat_class)] - - # determine what should be set in roman, and - # what in tt-font - if command in regindices: - - arg = [chunk(CSNAME, ch.where, 't'), \ - chunk(GROUP, ch.where, arg)] - else: - cat_arg = [chunk(CSNAME, ch.where, 'r'), \ - chunk(GROUP, ch.where, cat_arg)] - - ingroupch = arg + \ - [chunk(PLAIN, ch.where, ' ')] + \ - cat_arg - - pp.insert(i, chunk(GROUP, ch.where, ingroupch)) - length, i = length+1, i+1 - - - elif s(buf, ch.data) == 'ldots': - # \ldots --> \dots{} --> @dots{} - ch.data = 'dots' - if i == length \ - or pp[i].chtype != chunk_type(GROUP) \ - or pp[i].data != []: - pp.insert(i, chunk(GROUP, ch.where, [])) - i, length = i+1, length+1 - elif s(buf, ch.data) in wordsselves: - # \UNIX --> UNIX - ch.chtype = chunk_type(PLAIN) - if i != length \ - and pp[i].chtype == chunk_type(GROUP) \ - and pp[i].data == []: - del pp[i] - length = length-1 - elif s(buf, ch.data) in for_texi: - pass - - elif s(buf, ch.data) == 'e': - # \e --> \ - ch.data = '\\' - ch.chtype = chunk_type(PLAIN) - elif s(buf, ch.data) == 'lineiii': - # This is the most tricky one - # \lineiii{a1}{a2}[{a3}] --> - # @item @{a1} - # a2 [ -- a3] - # - ##print 'LINEIIIIII!!!!!!!' -## wobj = Wobj().init() -## dumpit(buf, wobj.write, pp[i-1:i+5]) -## print '--->' + wobj.data + '<----' - if not hist.inenv: - raise error, \ - 'no environment for lineiii' - if hist.inenv[0] != 'tableiii': - raise error, \ - 'wrong command (' + \ - `'lineiii'` + \ - ') in wrong environment (' \ - + `hist.inenv[0]` + ')' - ch.chtype = chunk_type(CSLINE) - ch.data = 'item' - length, newi = getnextarg(length, buf, pp, i) - ingroupch = [chunk(CSNAME, 0, \ - hist.itemargmacro), \ - chunk(GROUP, 0, pp[i:newi])] - del pp[i:newi] - length = length - (newi-i) -## print 'ITEM ARG: --->', -## wobj = Wobj().init() -## dumpit(buf, wobj.write, ingroupch) -## print wobj.data, '<---' - pp.insert(i, chunk(GROUP, ch.where, ingroupch)) - grouppos = i - i, length = i+1, length+1 - length, i = getnextarg(length, buf, pp, i) - length, newi = getnextarg(length, buf, pp, i) - if newi > i: - # we have a 3rd arg - pp.insert(i, chunk(PLAIN, ch.where, ' --- ')) - i = newi + 1 - length = length + 1 -## pp[grouppos].data = pp[grouppos].data \ -## + [chunk(PLAIN, ch.where, ' ')] \ -## + pp[i:newi] -## del pp[i:newi] -## length = length - (newi-i) - if length != len(pp): - raise 'IN LINEIII IS THE ERR', `i` - - elif s(buf, ch.data) in ('chapter', 'section', 'subsection', 'subsubsection'): - #\xxxsection{A} ----> - # @node A, , , - # @xxxsection A - ## also: remove commas and quotes - ch.chtype = chunk_type(CSLINE) - length, newi = getnextarg(length, buf, pp, i) - afternodenamecmd = next_command_p(length, buf, pp, newi, 'nodename') - if afternodenamecmd < 0: - cp1 = crcopy(pp[i:newi]) - pp[i:newi] = [\ - chunk(GROUP, ch.where, \ - pp[i:newi])] - length, newi = length - (newi-i) + 1, \ - i+1 - text = flattext(buf, cp1) - text = invent_node_names(text) - else: - length, endarg = getnextarg(length, buf, pp, afternodenamecmd) - cp1 = crcopy(pp[afternodenamecmd:endarg]) - del pp[newi:endarg] - length = length - (endarg-newi) - - pp[i:newi] = [\ - chunk(GROUP, ch.where, \ - pp[i:newi])] - length, newi = length - (newi-i) + 1, \ - i + 1 - text = flattext(buf, cp1) - if text[-1] == '.': - text = text[:-1] -## print 'FLATTEXT:', `text` - if text in hist.nodenames: - print 'WARNING: node name ' + `text` + ' already used' - out.doublenodes.append(text) - else: - hist.nodenames.append(text) - text = rm_commas_etc(text) - pp[i-1:i-1] = [\ - chunk(CSLINE, ch.where, 'node'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, text+', , ,')\ - ])] - i, length = newi+2, length+2 - - elif s(buf,ch.data) == 'funcline': - # fold it to a very short environment - pp[i-1:i-1] = [\ - chunk(CSLINE, ch.where, 'end'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, hist.command)])] - i, length = i+2, length+2 - length, i = do_funcdesc(length, buf, pp, i) - - elif s(buf,ch.data) == 'dataline': - pp[i-1:i-1] = [\ - chunk(CSLINE, ch.where, 'end'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, hist.command)])] - i, length = i+2, length+2 - length, i = do_datadesc(length, buf, pp, i) - - elif s(buf,ch.data) == 'excline': - pp[i-1:i-1] = [\ - chunk(CSLINE, ch.where, 'end'), \ - chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, hist.command)])] - i, length = i+2, length+2 - length, i = do_excdesc(length, buf, pp, i) - - - elif s(buf, ch.data) == 'index': - #\index{A} ---> - # @cindex A - ch.chtype = chunk_type(CSLINE) - ch.data = 'cindex' - length, newi = getnextarg(length, buf, pp, i) - - ingroupch = pp[i:newi] - del pp[i:newi] - length = length - (newi-i) - pp.insert(i, chunk(GROUP, ch.where, ingroupch)) - length, i = length+1, i+1 - - elif s(buf, ch.data) == 'bifuncindex': - ch.chtype = chunk_type(CSLINE) - ch.data = 'findex' - length, newi = getnextarg(length, buf, pp, i) - ingroupch = pp[i:newi] - del pp[i:newi] - length = length - (newi-i) - - ingroupch.append(chunk(PLAIN, ch.where, ' ')) - ingroupch.append(chunk(CSNAME, ch.where, 'r')) - ingroupch.append(chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, \ - '(built-in function)')])) - - pp.insert(i, chunk(GROUP, ch.where, ingroupch)) - length, i = length+1, i+1 - - - elif s(buf, ch.data) == 'opindex': - ch.chtype = chunk_type(CSLINE) - ch.data = 'findex' - length, newi = getnextarg(length, buf, pp, i) - ingroupch = pp[i:newi] - del pp[i:newi] - length = length - (newi-i) - - ingroupch.append(chunk(PLAIN, ch.where, ' ')) - ingroupch.append(chunk(CSNAME, ch.where, 'r')) - ingroupch.append(chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, \ - '(operator)')])) - - pp.insert(i, chunk(GROUP, ch.where, ingroupch)) - length, i = length+1, i+1 - - - elif s(buf, ch.data) == 'bimodindex': - ch.chtype = chunk_type(CSLINE) - ch.data = 'pindex' - length, newi = getnextarg(length, buf, pp, i) - ingroupch = pp[i:newi] - del pp[i:newi] - length = length - (newi-i) - - ingroupch.append(chunk(PLAIN, ch.where, ' ')) - ingroupch.append(chunk(CSNAME, ch.where, 'r')) - ingroupch.append(chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, \ - '(built-in)')])) - - pp.insert(i, chunk(GROUP, ch.where, ingroupch)) - length, i = length+1, i+1 - - elif s(buf, ch.data) == 'sectcode': - ch.data = 'code' - - - elif s(buf, ch.data) == 'stmodindex': - ch.chtype = chunk_type(CSLINE) - # use the program index as module index - ch.data = 'pindex' - length, newi = getnextarg(length, buf, pp, i) - ingroupch = pp[i:newi] - del pp[i:newi] - length = length - (newi-i) - - ingroupch.append(chunk(PLAIN, ch.where, ' ')) - ingroupch.append(chunk(CSNAME, ch.where, 'r')) - ingroupch.append(chunk(GROUP, ch.where, [\ - chunk(PLAIN, ch.where, \ - '(standard)')])) - - pp.insert(i, chunk(GROUP, ch.where, ingroupch)) - length, i = length+1, i+1 - - - elif s(buf, ch.data) == 'stindex': - # XXX must actually go to newindex st - wh = ch.where - ch.chtype = chunk_type(CSLINE) - ch.data = 'cindex' - length, newi = getnextarg(length, buf, pp, i) - ingroupch = [chunk(CSNAME, wh, 'code'), \ - chunk(GROUP, wh, pp[i:newi])] - - del pp[i:newi] - length = length - (newi-i) - - t = ingroupch[:] - t.append(chunk(PLAIN, wh, ' statement')) - - pp.insert(i, chunk(GROUP, wh, t)) - i, length = i+1, length+1 - - pp.insert(i, chunk(CSLINE, wh, 'cindex')) - i, length = i+1, length+1 - - t = ingroupch[:] - t.insert(0, chunk(PLAIN, wh, 'statement, ')) - - pp.insert(i, chunk(GROUP, wh, t)) - i, length = i+1, length+1 - - - elif s(buf, ch.data) == 'indexii': - #\indexii{A}{B} ---> - # @cindex A B - # @cindex B, A - length, newi = getnextarg(length, buf, pp, i) - cp11 = pp[i:newi] - cp21 = crcopy(pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - length, newi = getnextarg(length, buf, pp, i) - cp12 = pp[i:newi] - cp22 = crcopy(pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - - ch.chtype = chunk_type(CSLINE) - ch.data = 'cindex' - pp.insert(i, chunk(GROUP, ch.where, cp11 + [\ - chunk(PLAIN, ch.where, ' ')] + cp12)) - i, length = i+1, length+1 - pp[i:i] = [chunk(CSLINE, ch.where, 'cindex'), \ - chunk(GROUP, ch.where, cp22 + [\ - chunk(PLAIN, ch.where, ', ')]+ cp21)] - i, length = i+2, length+2 - - elif s(buf, ch.data) == 'indexiii': - length, newi = getnextarg(length, buf, pp, i) - cp11 = pp[i:newi] - cp21 = crcopy(pp[i:newi]) - cp31 = crcopy(pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - length, newi = getnextarg(length, buf, pp, i) - cp12 = pp[i:newi] - cp22 = crcopy(pp[i:newi]) - cp32 = crcopy(pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - length, newi = getnextarg(length, buf, pp, i) - cp13 = pp[i:newi] - cp23 = crcopy(pp[i:newi]) - cp33 = crcopy(pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - - ch.chtype = chunk_type(CSLINE) - ch.data = 'cindex' - pp.insert(i, chunk(GROUP, ch.where, cp11 + [\ - chunk(PLAIN, ch.where, ' ')] + cp12 \ - + [chunk(PLAIN, ch.where, ' ')] \ - + cp13)) - i, length = i+1, length+1 - pp[i:i] = [chunk(CSLINE, ch.where, 'cindex'), \ - chunk(GROUP, ch.where, cp22 + [\ - chunk(PLAIN, ch.where, ' ')]+ cp23\ - + [chunk(PLAIN, ch.where, ', ')] +\ - cp21)] - i, length = i+2, length+2 - pp[i:i] = [chunk(CSLINE, ch.where, 'cindex'), \ - chunk(GROUP, ch.where, cp33 + [\ - chunk(PLAIN, ch.where, ', ')]+ cp31\ - + [chunk(PLAIN, ch.where, ' ')] +\ - cp32)] - i, length = i+2, length+2 - - - elif s(buf, ch.data) == 'indexiv': - length, newi = getnextarg(length, buf, pp, i) - cp11 = pp[i:newi] - cp21 = crcopy(pp[i:newi]) - cp31 = crcopy(pp[i:newi]) - cp41 = crcopy(pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - length, newi = getnextarg(length, buf, pp, i) - cp12 = pp[i:newi] - cp22 = crcopy(pp[i:newi]) - cp32 = crcopy(pp[i:newi]) - cp42 = crcopy(pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - length, newi = getnextarg(length, buf, pp, i) - cp13 = pp[i:newi] - cp23 = crcopy(pp[i:newi]) - cp33 = crcopy(pp[i:newi]) - cp43 = crcopy(pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - length, newi = getnextarg(length, buf, pp, i) - cp14 = pp[i:newi] - cp24 = crcopy(pp[i:newi]) - cp34 = crcopy(pp[i:newi]) - cp44 = crcopy(pp[i:newi]) - del pp[i:newi] - length = length - (newi-i) - - ch.chtype = chunk_type(CSLINE) - ch.data = 'cindex' - ingroupch = cp11 + \ - spacech + cp12 + \ - spacech + cp13 + \ - spacech + cp14 - pp.insert(i, chunk(GROUP, ch.where, ingroupch)) - i, length = i+1, length+1 - ingroupch = cp22 + \ - spacech + cp23 + \ - spacech + cp24 + \ - commach + cp21 - pp[i:i] = cindexch + [\ - chunk(GROUP, ch.where, ingroupch)] - i, length = i+2, length+2 - ingroupch = cp33 + \ - spacech + cp34 + \ - commach + cp31 + \ - spacech + cp32 - pp[i:i] = cindexch + [\ - chunk(GROUP, ch.where, ingroupch)] - i, length = i+2, length+2 - ingroupch = cp44 + \ - commach + cp41 + \ - spacech + cp42 + \ - spacech + cp43 - pp[i:i] = cindexch + [\ - chunk(GROUP, ch.where, ingroupch)] - i, length = i+2, length+2 - - - - else: - print 'don\'t know what to do with keyword ' + `s(buf, ch.data)` - - - -re_atsign = regex.compile('[@{}]') -re_newline = regex.compile('\n') - -def dumpit(buf, wm, pp): - - global out - - i, length = 0, len(pp) - - addspace = 0 - - while 1: - if len(pp) != length: - raise 'FATAL', 'inconsistent length' - if i == length: - break - ch = pp[i] - i = i + 1 - - if addspace: - dospace = 1 - addspace = 0 - else: - dospace = 0 - - if ch.chtype == chunk_type(CSNAME): - wm('@' + s(buf, ch.data)) - if s(buf, ch.data) == 'node' and \ - pp[i].chtype == chunk_type(PLAIN) and \ - s(buf, pp[i].data) in out.doublenodes: - ##XXX doesnt work yet?? - wm(' ZZZ-' + zfill(`i`, 4)) - if s(buf, ch.data)[0] in string.letters: - addspace = 1 - elif ch.chtype == chunk_type(PLAIN): - if dospace and s(buf, ch.data) not in (' ', '\t'): - wm(' ') - text = s(buf, ch.data) - while 1: - pos = re_atsign.search(text) - if pos < 0: - break - wm(text[:pos] + '@' + text[pos]) - text = text[pos+1:] - wm(text) - elif ch.chtype == chunk_type(GROUP): - wm('{') - dumpit(buf, wm, ch.data) - wm('}') - elif ch.chtype == chunk_type(DENDLINE): - wm('\n\n') - while i != length and pp[i].chtype in \ - (chunk_type(DENDLINE), chunk_type(ENDLINE)): - i = i + 1 - elif ch.chtype == chunk_type(OTHER): - wm(s(buf, ch.data)) - elif ch.chtype == chunk_type(ACTIVE): - wm(s(buf, ch.data)) - elif ch.chtype == chunk_type(ENDLINE): - wm('\n') - elif ch.chtype == chunk_type(CSLINE): - if i >= 2 and pp[i-2].chtype not in \ - (chunk_type(ENDLINE), chunk_type(DENDLINE)) \ - and (pp[i-2].chtype != chunk_type(PLAIN) \ - or s(buf, pp[i-2].data)[-1] != '\n'): - - wm('\n') - wm('@' + s(buf, ch.data)) - if i == length: - raise error, 'CSLINE expected another chunk' - if pp[i].chtype != chunk_type(GROUP): - raise error, 'CSLINE expected GROUP' - if type(pp[i].data) != type([]): - raise error, 'GROUP chould contain []-data' - - wobj = Wobj().init() - dumpit(buf, wobj.write, pp[i].data) - i = i + 1 - text = wobj.data - del wobj - if text: - wm(' ') - while 1: - pos = re_newline.search(text) - if pos < 0: - break - print 'WARNING: found newline in csline arg' - wm(text[:pos] + ' ') - text = text[pos+1:] - wm(text) - if i >= length or \ - pp[i].chtype not in (chunk_type(CSLINE), \ - chunk_type(ENDLINE), chunk_type(DENDLINE)) \ - and (pp[i].chtype != chunk_type(PLAIN) \ - or s(buf, pp[i].data)[0] != '\n'): - wm('\n') - - elif ch.chtype == chunk_type(COMMENT): -## print 'COMMENT: previous chunk =', pp[i-2] - if pp[i-2].chtype == chunk_type(PLAIN): - print 'PLAINTEXT =', `s(buf, pp[i-2].data)` - if s(buf, ch.data) and \ - regex.match('^[ \t]*$', s(buf, ch.data)) < 0: - if i >= 2 and pp[i-2].chtype not in \ - (chunk_type(ENDLINE), chunk_type(DENDLINE)) \ - and not (pp[i-2].chtype == chunk_type(PLAIN) \ - and regex.match('\\(.\\|\n\\)*[ \t]*\n$', s(buf, pp[i-2].data)) >= 0): - print 'ADDING NEWLINE' - wm('\n') - wm('@c ' + s(buf, ch.data)) - elif ch.chtype == chunk_type(IGNORE): - pass - else: - try: - str = `s(buf, ch.data)` - except TypeError: - str = `ch.data` - if len(str) > 400: - str = str[:400] + '...' - print 'warning:', ch.chtype, 'not handled, data ' + str - - - -def main(): - outfile = None - headerfile = 'texipre.dat' - trailerfile = 'texipost.dat' - - try: - opts, args = getopt.getopt(sys.argv[1:], 'o:h:t:') - except getopt.error: - args = [] - - if not args: - print 'usage: partparse [-o outfile] [-h headerfile]', - print '[-t trailerfile] file ...' - sys.exit(2) - - for opt, arg in opts: - if opt == '-o': outfile = arg - if opt == '-h': headerfile = arg - if opt == '-t': trailerfile = arg - - if not outfile: - root, ext = os.path.splitext(args[0]) - outfile = root + '.texi' - - if outfile in args: - print 'will not overwrite input file', outfile - sys.exit(2) - - outf = open(outfile, 'w') - outf.write(open(headerfile, 'r').read()) - - for file in args: - if len(args) > 1: print '='*20, file, '='*20 - buf = open(file, 'r').read() - w, pp = parseit(buf) - startchange() - changeit(buf, pp) - dumpit(buf, outf.write, pp) - - outf.write(open(trailerfile, 'r').read()) - - outf.close() - -main() diff --git a/Doc/tools/text2latex.py b/Doc/tools/text2latex.py deleted file mode 100644 index 93d0587d30..0000000000 --- a/Doc/tools/text2latex.py +++ /dev/null @@ -1,55 +0,0 @@ -import os -import sys -import regex -import regsub -import string -import getopt - -def main(): - process(sys.stdin, sys.stdout) - -dashes = regex.compile('^-+[ \t]*$') -equals = regex.compile('^=+[ \t]*$') -stars = regex.compile('^\*+[ \t]*$') -blank = regex.compile('^[ \t]*$') -indented = regex.compile('^\( *\t\| \)[ \t]*[^ \t]') - -def process(fi, fo): - inverbatim = 0 - line = '\n' - nextline = fi.readline() - while nextline: - prevline = line - line = nextline - nextline = fi.readline() - fmt = None - if dashes.match(nextline) >= 0: - fmt = '\\subsection{%s}\n' - elif equals.match(nextline) >= 0: - fmt = '\\section{%s}\n' - elif stars.match(nextline) >= 0: - fmt = '\\chapter{%s}\n' - if fmt: - nextline = '\n' - line = fmt % string.strip(line) - if '(' in line: - line = regsub.gsub('[a-zA-Z0-9_]+()', - '{\\\\tt \\0}', line) - elif inverbatim: - if blank.match(line) >= 0 and \ - indented.match(nextline) < 0: - inverbatim = 0 - fo.write('\\end{verbatim}\n') - else: - if indented.match(line) >= 0 and \ - blank.match(prevline) >= 0: - inverbatim = 1 - fo.write('\\begin{verbatim}\n') - if inverbatim: - line = string.expandtabs(line, 4) - elif not fmt and '(' in line: - line = regsub.gsub('[a-zA-Z0-9_]+()', - '\\\\code{\\0}', line) - fo.write(line) - -main() diff --git a/Doc/tut.tex b/Doc/tut.tex deleted file mode 100644 index 532748876a..0000000000 --- a/Doc/tut.tex +++ /dev/null @@ -1,2565 +0,0 @@ -\documentstyle[twoside,11pt,myformat]{report} - -\title{\bf - Python Tutorial -} - -\author{ - Guido van Rossum \\ - Dept. CST, CWI, P.O. Box 94079 \\ - 1090 GB Amsterdam, The Netherlands \\ - E-mail: {\tt guido@cwi.nl} -} - -\date{19 November 1993 \\ Release 0.9.9.++} % XXX update before release! - -\begin{document} - -\pagenumbering{roman} - -\maketitle - -\begin{abstract} - -\noindent -Python is a simple, yet powerful programming language that bridges the -gap between C and shell programming, and is thus ideally suited for -``throw-away programming'' -and rapid prototyping. Its syntax is put -together from constructs borrowed from a variety of other languages; -most prominent are influences from ABC, C, Modula-3 and Icon. - -The Python interpreter is easily extended with new functions and data -types implemented in C. Python is also suitable as an extension -language for highly customizable C applications such as editors or -window managers. - -Python is available for various operating systems, amongst which -several flavors of {\UNIX}, Amoeba, the Apple Macintosh O.S., -and MS-DOS. - -This tutorial introduces the reader informally to the basic concepts -and features of the Python language and system. It helps to have a -Python interpreter handy for hands-on experience, but as the examples -are self-contained, the tutorial can be read off-line as well. - -For a description of standard objects and modules, see the {\em Python -Library Reference} document. The {\em Python Reference Manual} gives -a more formal definition of the language. - -\end{abstract} - -\pagebreak -{ -\parskip = 0mm -\tableofcontents -} - -\pagebreak - -\pagenumbering{arabic} - - -\chapter{Whetting Your Appetite} - -If you ever wrote a large shell script, you probably know this -feeling: you'd love to add yet another feature, but it's already so -slow, and so big, and so complicated; or the feature involves a system -call or other funcion that is only accessible from C \ldots Usually -the problem at hand isn't serious enough to warrant rewriting the -script in C; perhaps because the problem requires variable-length -strings or other data types (like sorted lists of file names) that are -easy in the shell but lots of work to implement in C; or perhaps just -because you're not sufficiently familiar with C. - -In such cases, Python may be just the language for you. Python is -simple to use, but it is a real programming language, offering much -more structure and support for large programs than the shell has. On -the other hand, it also offers much more error checking than C, and, -being a {\em very-high-level language}, it has high-level data types -built in, such as flexible arrays and dictionaries that would cost you -days to implement efficiently in C. Because of its more general data -types Python is applicable to a much larger problem domain than {\em -Awk} or even {\em Perl}, yet many things are at least as easy in -Python as in those languages. - -Python allows you to split up your program in modules that can be -reused in other Python programs. It comes with a large collection of -standard modules that you can use as the basis of your programs --- or -as examples to start learning to program in Python. There are also -built-in modules that provide things like file I/O, system calls, -sockets, and even a generic interface to window systems (STDWIN). - -Python is an interpreted language, which can save you considerable time -during program development because no compilation and linking is -necessary. The interpreter can be used interactively, which makes it -easy to experiment with features of the language, to write throw-away -programs, or to test functions during bottom-up program development. -It is also a handy desk calculator. - -Python allows writing very compact and readable programs. Programs -written in Python are typically much shorter than equivalent C -programs, for several reasons: -\begin{itemize} -\item -the high-level data types allow you to express complex operations in a -single statement; -\item -statement grouping is done by indentation instead of begin/end -brackets; -\item -no variable or argument declarations are necessary. -\end{itemize} - -Python is {\em extensible}: if you know how to program in C it is easy -to add a new built-in -function or -module to the interpreter, either to -perform critical operations at maximum speed, or to link Python -programs to libraries that may only be available in binary form (such -as a vendor-specific graphics library). Once you are really hooked, -you can link the Python interpreter into an application written in C -and use it as an extension or command language for that application. - -By the way, the language is named after the BBC show ``Monty -Python's Flying Circus'' and has nothing to do with nasty reptiles... - -\section{Where From Here} - -Now that you are all excited about Python, you'll want to examine it -in some more detail. Since the best way to learn a language is -using it, you are invited here to do so. - -In the next chapter, the mechanics of using the interpreter are -explained. This is rather mundane information, but essential for -trying out the examples shown later. - -The rest of the tutorial introduces various features of the Python -language and system though examples, beginning with simple -expressions, statements and data types, through functions and modules, -and finally touching upon advanced concepts like exceptions. - -When you're through with the turtorial (or just getting bored), you -should read the Library Reference, which gives complete (though terse) -reference material about built-in and standard types, functions and -modules that can save you a lot of time when writing Python programs. - - -\chapter{Using the Python Interpreter} - -\section{Invoking the Interpreter} - -The Python interpreter is usually installed as {\tt /usr/local/bin/python} -on those machines where it is available; putting {\tt /usr/local/bin} in -your {\UNIX} shell's search path makes it possible to start it by -typing the command - -\bcode\begin{verbatim} -python -\end{verbatim}\ecode -% -to the shell. Since the choice of the directory where the interpreter -lives is an installation option, other places are possible; check with -your local Python guru or system administrator. (E.g., {\tt -/usr/local/python} is a popular alternative location.) - -The interpreter operates somewhat like the {\UNIX} shell: when called -with standard input connected to a tty device, it reads and executes -commands interactively; when called with a file name argument or with -a file as standard input, it reads and executes a {\em script} from -that file. - -A third way of starting the interpreter is -``{\tt python -c command [arg] ...}'', which -executes the statement(s) in {\tt command}, analogous to the shell's -{\tt -c} option. Since Python statements often contain spaces or other -characters that are special to the shell, it is best to quote {\tt -command} in its entirety with double quotes. - -Note that there is a difference between ``{\tt python file}'' and -``{\tt python $<$file}''. In the latter case, input requests from the -program, such as calls to {\tt input()} and {\tt raw_input()}, are -satisfied from {\em file}. Since this file has already been read -until the end by the parser before the program starts executing, the -program will encounter EOF immediately. In the former case (which is -usually what you want) they are satisfied from whatever file or device -is connected to standard input of the Python interpreter. - -When a script file is used, it is sometimes useful to be able to run -the script and enter interactive mode afterwards. This can be done by -passing {\tt -i} before the script. (This does not work if the script -is read from standard input, for the same reason as explained in the -previous paragraph.) - -\subsection{Argument Passing} - -When known to the interpreter, the script name and additional -arguments thereafter are passed to the script in the variable {\tt -sys.argv}, which is a list of strings. Its length is at least one; -when no script and no arguments are given, {\tt sys.argv[0]} is an -empty string. When the script name is given as {\tt '-'} (meaning -standard input), {\tt sys.argv[0]} is set to {\tt '-'}. When {\tt -c -command} is used, {\tt sys.argv[0]} is set to {\tt '-c'}. Options -found after {\tt -c command} are not consumed by the Python -interpreter's option processing but left in {\tt sys.argv} for the -command to handle. - -\subsection{Interactive Mode} - -When commands are read from a tty, the interpreter is said to be in -{\em interactive\ mode}. In this mode it prompts for the next command -with the {\em primary\ prompt}, usually three greater-than signs ({\tt ->>>}); for continuation lines it prompts with the {\em secondary\ -prompt}, by default three dots ({\tt ...}). Typing an EOF (Control-D) -at the primary prompt causes the interpreter to exit with a zero exit -status. - -The interpreter prints a welcome message stating its version number -and a copyright notice before printing the first prompt, e.g.: - -\bcode\begin{verbatim} -python -Python 0.9.9 (Apr 2 1993). -Copyright 1990, 1991, 1992, 1993 Stichting Mathematisch Centrum, Amsterdam ->>> -\end{verbatim}\ecode - -\section{The Interpreter and its Environment} - -\subsection{Error Handling} - -When an error occurs, the interpreter prints an error -message and a stack trace. In interactive mode, it then returns to -the primary prompt; when input came from a file, it exits with a -nonzero exit status after printing -the stack trace. (Exceptions handled by an {\tt except} clause in a -{\tt try} statement are not errors in this context.) Some errors are -unconditionally fatal and cause an exit with a nonzero exit; this -applies to internal inconsistencies and some cases of running out of -memory. All error messages are written to the standard error stream; -normal output from the executed commands is written to standard -output. - -Typing the interrupt character (usually Control-C or DEL) to the -primary or secondary prompt cancels the input and returns to the -primary prompt.% -\footnote{ - A problem with the GNU Readline package may prevent this. -} -Typing an interrupt while a command is executing raises the {\tt -KeyboardInterrupt} exception, which may be handled by a {\tt try} -statement. - -\subsection{The Module Search Path} - -When a module named {\tt foo} is imported, the interpreter searches -for a file named {\tt foo.py} in the list of directories specified by -the environment variable {\tt PYTHONPATH}. It has the same syntax as -the {\UNIX} shell variable {\tt PATH}, i.e., a list of colon-separated -directory names. When {\tt PYTHONPATH} is not set, or when the file -is not found there, the search continues in an installation-dependent -default path, usually {\tt .:/usr/local/lib/python}. - -Actually, modules are searched in the list of directories given by the -variable {\tt sys.path} which is initialized from {\tt PYTHONPATH} and -the installation-dependent default. This allows Python programs that -know what they're doing to modify or replace the module search path. -See the section on Standard Modules later. - -\subsection{``Compiled'' Python files} - -As an important speed-up of the start-up time for short programs that -use a lot of standard modules, if a file called {\tt foo.pyc} exists -in the directory where {\tt foo.py} is found, this is assumed to -contain an already-``compiled'' version of the module {\tt foo}. The -modification time of the version of {\tt foo.py} used to create {\tt -foo.pyc} is recorded in {\tt foo.pyc}, and the file is ignored if -these don't match. - -Whenever {\tt foo.py} is successfully compiled, an attempt is made to -write the compiled version to {\tt foo.pyc}. It is not an error if -this attempt fails; if for any reason the file is not written -completely, the resulting {\tt foo.pyc} file will be recognized as -invalid and thus ignored later. - -\subsection{Executable Python scripts} - -On BSD'ish {\UNIX} systems, Python scripts can be made directly -executable, like shell scripts, by putting the line - -\bcode\begin{verbatim} -#! /usr/local/bin/python -\end{verbatim}\ecode -% -(assuming that's the name of the interpreter) at the beginning of the -script and giving the file an executable mode. The {\tt \#!} must be -the first two characters of the file. - -\subsection{The Interactive Startup File} - -When you use Python interactively, it is frequently handy to have some -standard commands executed every time the interpreter is started. You -can do this by setting an environment variable named {\tt -PYTHONSTARTUP} to the name of a file containing your start-up -commands. This is similar to the {\tt /profile} feature of the UNIX -shells. - -This file is only read in interactive sessions, not when Python reads -commands from a script, and not when {\tt /dev/tty} is given as the -explicit source of commands (which otherwise behaves like an -interactive session). It is executed in the same name space where -interactive commands are executed, so that objects that it defines or -imports can be used without qualification in the interactive session. -You can also change the prompts {\tt sys.ps1} and {\tt sys.ps2} in -this file. - -If you want to read an additional start-up file from the current -directory, you can program this in the global start-up file, e.g. -\verb\execfile('.pythonrc')\. If you want to use the startup file -in a script, you must write this explicitly in the script, e.g. -\verb\import os;\ \verb\execfile(os.environ['PYTHONSTARTUP'])\. - -\section{Interactive Input Editing and History Substitution} - -Some versions of the Python interpreter support editing of the current -input line and history substitution, similar to facilities found in -the Korn shell and the GNU Bash shell. This is implemented using the -{\em GNU\ Readline} library, which supports Emacs-style and vi-style -editing. This library has its own documentation which I won't -duplicate here; however, the basics are easily explained. - -Perhaps the quickest check to see whether command line editing is -supported is typing Control-P to the first Python prompt you get. If -it beeps, you have command line editing. If nothing appears to -happen, or if \verb/^P/ is echoed, you can skip the rest of this -section. - -\subsection{Line Editing} - -If supported, input line editing is active whenever the interpreter -prints a primary or secondary prompt. The current line can be edited -using the conventional Emacs control characters. The most important -of these are: C-A (Control-A) moves the cursor to the beginning of the -line, C-E to the end, C-B moves it one position to the left, C-F to -the right. Backspace erases the character to the left of the cursor, -C-D the character to its right. C-K kills (erases) the rest of the -line to the right of the cursor, C-Y yanks back the last killed -string. C-underscore undoes the last change you made; it can be -repeated for cumulative effect. - -\subsection{History Substitution} - -History substitution works as follows. All non-empty input lines -issued are saved in a history buffer, and when a new prompt is given -you are positioned on a new line at the bottom of this buffer. C-P -moves one line up (back) in the history buffer, C-N moves one down. -Any line in the history buffer can be edited; an asterisk appears in -front of the prompt to mark a line as modified. Pressing the Return -key passes the current line to the interpreter. C-R starts an -incremental reverse search; C-S starts a forward search. - -\subsection{Key Bindings} - -The key bindings and some other parameters of the Readline library can -be customized by placing commands in an initialization file called -{\tt \$HOME/.inputrc}. Key bindings have the form - -\bcode\begin{verbatim} -key-name: function-name -\end{verbatim}\ecode -% -or - -\bcode\begin{verbatim} -"string": function-name -\end{verbatim}\ecode -% -and options can be set with - -\bcode\begin{verbatim} -set option-name value -\end{verbatim}\ecode -% -For example: - -\bcode\begin{verbatim} -# I prefer vi-style editing: -set editing-mode vi -# Edit using a single line: -set horizontal-scroll-mode On -# Rebind some keys: -Meta-h: backward-kill-word -"\C-u": universal-argument -"\C-x\C-r": re-read-init-file -\end{verbatim}\ecode -% -Note that the default binding for TAB in Python is to insert a TAB -instead of Readline's default filename completion function. If you -insist, you can override this by putting - -\bcode\begin{verbatim} -TAB: complete -\end{verbatim}\ecode -% -in your {\tt \$HOME/.inputrc}. (Of course, this makes it hard to type -indented continuation lines...) - -\subsection{Commentary} - -This facility is an enormous step forward compared to previous -versions of the interpreter; however, some wishes are left: It would -be nice if the proper indentation were suggested on continuation lines -(the parser knows if an indent token is required next). The -completion mechanism might use the interpreter's symbol table. A -command to check (or even suggest) matching parentheses, quotes etc. -would also be useful. - - -\chapter{An Informal Introduction to Python} - -In the following examples, input and output are distinguished by the -presence or absence of prompts ({\tt >>>} and {\tt ...}): to repeat -the example, you must type everything after the prompt, when the -prompt appears; lines that do not begin with a prompt are output from -the interpreter.% -\footnote{ - I'd prefer to use different fonts to distinguish input - from output, but the amount of LaTeX hacking that would require - is currently beyond my ability. -} -Note that a secondary prompt on a line by itself in an example means -you must type a blank line; this is used to end a multi-line command. - -\section{Using Python as a Calculator} - -Let's try some simple Python commands. Start the interpreter and wait -for the primary prompt, {\tt >>>}. (It shouldn't take long.) - -\subsection{Numbers} - -The interpreter acts as a simple calculator: you can type an -expression at it and it will write the value. Expression syntax is -straightforward: the operators {\tt +}, {\tt -}, {\tt *} and {\tt /} -work just like in most other languages (e.g., Pascal or C); parentheses -can be used for grouping. For example: - -\bcode\begin{verbatim} ->>> # This is a comment ->>> 2+2 -4 ->>> ->>> (50-5*6)/4 -5 ->>> # Division truncates towards zero: ->>> 7/3 -2 ->>> -\end{verbatim}\ecode -% -Like in C, the equal sign ({\tt =}) is used to assign a value to a -variable. The value of an assignment is not written: - -\bcode\begin{verbatim} ->>> width = 20 ->>> height = 5*9 ->>> width * height -900 ->>> -\end{verbatim}\ecode -% -A value can be assigned to several variables simultaneously: - -\bcode\begin{verbatim} ->>> # Zero x, y and z ->>> x = y = z = 0 ->>> -\end{verbatim}\ecode -% -There is full support for floating point; operators with mixed type -operands convert the integer operand to floating point: - -\bcode\begin{verbatim} ->>> 4 * 2.5 / 3.3 -3.0303030303 ->>> 7.0 / 2 -3.5 ->>> -\end{verbatim}\ecode - -\subsection{Strings} - -Besides numbers, Python can also manipulate strings, enclosed in -single quotes: - -\bcode\begin{verbatim} ->>> 'foo bar' -'foo bar' ->>> 'doesn\'t' -'doesn\'t' ->>> -\end{verbatim}\ecode -% -Strings are written the same way as they are typed for input: inside -quotes and with quotes and other funny characters escaped by -backslashes, to show the precise value. (The {\tt print} statement, -described later, can be used to write strings without quotes or -escapes.) - -Strings can be concatenated (glued together) with the {\tt +} -operator, and repeated with {\tt *}: - -\bcode\begin{verbatim} ->>> word = 'Help' + 'A' ->>> word -'HelpA' ->>> '<' + word*5 + '>' -'' ->>> -\end{verbatim}\ecode -% -Strings can be subscripted (indexed); like in C, the first character of -a string has subscript (index) 0. - -There is no separate character type; a character is simply a string of -size one. Like in Icon, substrings can be specified with the {\em -slice} notation: two indices separated by a colon. - -\bcode\begin{verbatim} ->>> word[4] -'A' ->>> word[0:2] -'He' ->>> word[2:4] -'lp' ->>> -\end{verbatim}\ecode -% -Slice indices have useful defaults; an omitted first index defaults to -zero, an omitted second index defaults to the size of the string being -sliced. - -\bcode\begin{verbatim} ->>> word[:2] # The first two characters -'He' ->>> word[2:] # All but the first two characters -'lpA' ->>> -\end{verbatim}\ecode -% -Here's a useful invariant of slice operations: \verb\s[:i] + s[i:]\ -equals \verb\s\. - -\bcode\begin{verbatim} ->>> word[:2] + word[2:] -'HelpA' ->>> word[:3] + word[3:] -'HelpA' ->>> -\end{verbatim}\ecode -% -Degenerate slice indices are handled gracefully: an index that is too -large is replaced by the string size, an upper bound smaller than the -lower bound returns an empty string. - -\bcode\begin{verbatim} ->>> word[1:100] -'elpA' ->>> word[10:] -'' ->>> word[2:1] -'' ->>> -\end{verbatim}\ecode -% -Indices may be negative numbers, to start counting from the right. -For example: - -\bcode\begin{verbatim} ->>> word[-1] # The last character -'A' ->>> word[-2] # The last-but-one character -'p' ->>> word[-2:] # The last two characters -'pA' ->>> word[:-2] # All but the last two characters -'Hel' ->>> -\end{verbatim}\ecode -% -But note that -0 is really the same as 0, so it does not count from -the right! - -\bcode\begin{verbatim} ->>> word[-0] # (since -0 equals 0) -'H' ->>> -\end{verbatim}\ecode -% -Out-of-range negative slice indices are truncated, but don't try this -for single-element (non-slice) indices: - -\bcode\begin{verbatim} ->>> word[-100:] -'HelpA' ->>> word[-10] # error -Unhandled exception: IndexError: string index out of range ->>> -\end{verbatim}\ecode -% -The best way to remember how slices work is to think of the indices as -pointing {\em between} characters, with the left edge of the first -character numbered 0. Then the right edge of the last character of a -string of {\tt n} characters has index {\tt n}, for example: - -\bcode\begin{verbatim} - +---+---+---+---+---+ - | H | e | l | p | A | - +---+---+---+---+---+ - 0 1 2 3 4 5 --5 -4 -3 -2 -1 -\end{verbatim}\ecode -% -The first row of numbers gives the position of the indices 0...5 in -the string; the second row gives the corresponding negative indices. -The slice from \verb\i\ to \verb\j\ consists of all characters between -the edges labeled \verb\i\ and \verb\j\, respectively. - -For nonnegative indices, the length of a slice is the difference of -the indices, if both are within bounds, e.g., the length of -\verb\word[1:3]\ is 2. - -The built-in function {\tt len()} returns the length of a string: - -\bcode\begin{verbatim} ->>> s = 'supercalifragilisticexpialidocious' ->>> len(s) -34 ->>> -\end{verbatim}\ecode - -\subsection{Lists} - -Python knows a number of {\em compound} data types, used to group -together other values. The most versatile is the {\em list}, which -can be written as a list of comma-separated values (items) between -square brackets. List items need not all have the same type. - -\bcode\begin{verbatim} ->>> a = ['foo', 'bar', 100, 1234] ->>> a -['foo', 'bar', 100, 1234] ->>> -\end{verbatim}\ecode -% -Like string indices, list indices start at 0, and lists can be sliced, -concatenated and so on: - -\bcode\begin{verbatim} ->>> a[0] -'foo' ->>> a[3] -1234 ->>> a[-2] -100 ->>> a[1:-1] -['bar', 100] ->>> a[:2] + ['bletch', 2*2] -['foo', 'bar', 'bletch', 4] ->>> 3*a[:3] + ['Boe!'] -['foo', 'bar', 100, 'foo', 'bar', 100, 'foo', 'bar', 100, 'Boe!'] ->>> -\end{verbatim}\ecode -% -Unlike strings, which are {\em immutable}, it is possible to change -individual elements of a list: - -\bcode\begin{verbatim} ->>> a -['foo', 'bar', 100, 1234] ->>> a[2] = a[2] + 23 ->>> a -['foo', 'bar', 123, 1234] ->>> -\end{verbatim}\ecode -% -Assignment to slices is also possible, and this can even change the size -of the list: - -\bcode\begin{verbatim} ->>> # Replace some items: ->>> a[0:2] = [1, 12] ->>> a -[1, 12, 123, 1234] ->>> # Remove some: ->>> a[0:2] = [] ->>> a -[123, 1234] ->>> # Insert some: ->>> a[1:1] = ['bletch', 'xyzzy'] ->>> a -[123, 'bletch', 'xyzzy', 1234] ->>> a[:0] = a # Insert (a copy of) itself at the beginning ->>> a -[123, 'bletch', 'xyzzy', 1234, 123, 'bletch', 'xyzzy', 1234] ->>> -\end{verbatim}\ecode -% -The built-in function {\tt len()} also applies to lists: - -\bcode\begin{verbatim} ->>> len(a) -8 ->>> -\end{verbatim}\ecode -% -It is possible to nest lists (create lists containing other lists), -for example: - -\bcode\begin{verbatim} ->>> q = [2, 3] ->>> p = [1, q, 4] ->>> len(p) -3 ->>> p[1] -[2, 3] ->>> p[1][0] -2 ->>> p[1].append('xtra') # See section 5.1 ->>> p -[1, [2, 3, 'xtra'], 4] ->>> q -[2, 3, 'xtra'] ->>> -\end{verbatim}\ecode -% -Note that in the last example, {\tt p[1]} and {\tt q} really refer to -the same object! We'll come back to {\em object semantics} later. - -\section{First Steps Towards Programming} - -Of course, we can use Python for more complicated tasks than adding -two and two together. For instance, we can write an initial -subsequence of the {\em Fibonacci} series as follows: - -\bcode\begin{verbatim} ->>> # Fibonacci series: ->>> # the sum of two elements defines the next ->>> a, b = 0, 1 ->>> while b < 10: -... print b -... a, b = b, a+b -... -1 -1 -2 -3 -5 -8 ->>> -\end{verbatim}\ecode -% -This example introduces several new features. - -\begin{itemize} - -\item -The first line contains a {\em multiple assignment}: the variables -{\tt a} and {\tt b} simultaneously get the new values 0 and 1. On the -last line this is used again, demonstrating that the expressions on -the right-hand side are all evaluated first before any of the -assignments take place. - -\item -The {\tt while} loop executes as long as the condition (here: {\tt b < -100}) remains true. In Python, like in C, any non-zero integer value is -true; zero is false. The condition may also be a string or list value, -in fact any sequence; anything with a non-zero length is true, empty -sequences are false. The test used in the example is a simple -comparison. The standard comparison operators are written the same as -in C: {\tt <}, {\tt >}, {\tt ==}, {\tt <=}, {\tt >=} and {\tt !=}. - -\item -The {\em body} of the loop is {\em indented}: indentation is Python's -way of grouping statements. Python does not (yet!) provide an -intelligent input line editing facility, so you have to type a tab or -space(s) for each indented line. In practice you will prepare more -complicated input for Python with a text editor; most text editors have -an auto-indent facility. When a compound statement is entered -interactively, it must be followed by a blank line to indicate -completion (since the parser cannot guess when you have typed the last -line). - -\item -The {\tt print} statement writes the value of the expression(s) it is -given. It differs from just writing the expression you want to write -(as we did earlier in the calculator examples) in the way it handles -multiple expressions and strings. Strings are written without quotes, -and a space is inserted between items, so you can format things nicely, -like this: - -\bcode\begin{verbatim} ->>> i = 256*256 ->>> print 'The value of i is', i -The value of i is 65536 ->>> -\end{verbatim}\ecode -% -A trailing comma avoids the newline after the output: - -\bcode\begin{verbatim} ->>> a, b = 0, 1 ->>> while b < 1000: -... print b, -... a, b = b, a+b -... -1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 ->>> -\end{verbatim}\ecode -% -Note that the interpreter inserts a newline before it prints the next -prompt if the last line was not completed. - -\end{itemize} - - -\chapter{More Control Flow Tools} - -Besides the {\tt while} statement just introduced, Python knows the -usual control flow statements known from other languages, with some -twists. - -\section{If Statements} - -Perhaps the most well-known statement type is the {\tt if} statement. -For example: - -\bcode\begin{verbatim} ->>> if x < 0: -... x = 0 -... print 'Negative changed to zero' -... elif x == 0: -... print 'Zero' -... elif x == 1: -... print 'Single' -... else: -... print 'More' -... -\end{verbatim}\ecode -% -There can be zero or more {\tt elif} parts, and the {\tt else} part is -optional. The keyword `{\tt elif}' is short for `{\tt else if}', and is -useful to avoid excessive indentation. An {\tt if...elif...elif...} -sequence is a substitute for the {\em switch} or {\em case} statements -found in other languages. - -\section{For Statements} - -The {\tt for} statement in Python differs a bit from what you may be -used to in C or Pascal. Rather than always iterating over an -arithmetic progression of numbers (like in Pascal), or leaving the user -completely free in the iteration test and step (as C), Python's {\tt -for} statement iterates over the items of any sequence (e.g., a list -or a string), in the order that they appear in the sequence. For -example (no pun intended): - -\bcode\begin{verbatim} ->>> # Measure some strings: ->>> a = ['cat', 'window', 'defenestrate'] ->>> for x in a: -... print x, len(x) -... -cat 3 -window 6 -defenestrate 12 ->>> -\end{verbatim}\ecode -% -It is not safe to modify the sequence being iterated over in the loop -(this can only happen for mutable sequence types, i.e., lists). If -you need to modify the list you are iterating over, e.g., duplicate -selected items, you must iterate over a copy. The slice notation -makes this particularly convenient: - -\bcode\begin{verbatim} ->>> for x in a[:]: # make a slice copy of the entire list -... if len(x) > 6: a.insert(0, x) -... ->>> a -['defenestrate', 'cat', 'window', 'defenestrate'] ->>> -\end{verbatim}\ecode - -\section{The {\tt range()} Function} - -If you do need to iterate over a sequence of numbers, the built-in -function {\tt range()} comes in handy. It generates lists containing -arithmetic progressions, e.g.: - -\bcode\begin{verbatim} ->>> range(10) -[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ->>> -\end{verbatim}\ecode -% -The given end point is never part of the generated list; {\tt range(10)} -generates a list of 10 values, exactly the legal indices for items of a -sequence of length 10. It is possible to let the range start at another -number, or to specify a different increment (even negative): - -\bcode\begin{verbatim} ->>> range(5, 10) -[5, 6, 7, 8, 9] ->>> range(0, 10, 3) -[0, 3, 6, 9] ->>> range(-10, -100, -30) -[-10, -40, -70] ->>> -\end{verbatim}\ecode -% -To iterate over the indices of a sequence, combine {\tt range()} and -{\tt len()} as follows: - -\bcode\begin{verbatim} ->>> a = ['Mary', 'had', 'a', 'little', 'lamb'] ->>> for i in range(len(a)): -... print i, a[i] -... -0 Mary -1 had -2 a -3 little -4 lamb ->>> -\end{verbatim}\ecode - -\section{Break and Continue Statements, and Else Clauses on Loops} - -The {\tt break} statement, like in C, breaks out of the smallest -enclosing {\tt for} or {\tt while} loop. - -The {\tt continue} statement, also borrowed from C, continues with the -next iteration of the loop. - -Loop statements may have an {\tt else} clause; it is executed when the -loop terminates through exhaustion of the list (with {\tt for}) or when -the condition becomes false (with {\tt while}), but not when the loop is -terminated by a {\tt break} statement. This is exemplified by the -following loop, which searches for a list item of value 0: - -\bcode\begin{verbatim} ->>> for n in range(2, 10): -... for x in range(2, n): -... if n % x == 0: -... print n, 'equals', x, '*', n/x -... break -... else: -... print n, 'is a prime number' -... -2 is a prime number -3 is a prime number -4 equals 2 * 2 -5 is a prime number -6 equals 2 * 3 -7 is a prime number -8 equals 2 * 4 -9 equals 3 * 3 ->>> -\end{verbatim}\ecode - -\section{Pass Statements} - -The {\tt pass} statement does nothing. -It can be used when a statement is required syntactically but the -program requires no action. -For example: - -\bcode\begin{verbatim} ->>> while 1: -... pass # Busy-wait for keyboard interrupt -... -\end{verbatim}\ecode - -\section{Defining Functions} - -We can create a function that writes the Fibonacci series to an -arbitrary boundary: - -\bcode\begin{verbatim} ->>> def fib(n): # write Fibonacci series up to n -... a, b = 0, 1 -... while b <= n: -... print b, -... a, b = b, a+b -... ->>> # Now call the function we just defined: ->>> fib(2000) -1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 ->>> -\end{verbatim}\ecode -% -The keyword {\tt def} introduces a function {\em definition}. It must -be followed by the function name and the parenthesized list of formal -parameters. The statements that form the body of the function starts at -the next line, indented by a tab stop. - -The {\em execution} of a function introduces a new symbol table used -for the local variables of the function. More precisely, all variable -assignments in a function store the value in the local symbol table; -whereas - variable references first look in the local symbol table, then -in the global symbol table, and then in the table of built-in names. -Thus, -global variables cannot be directly assigned to from within a -function, although they may be referenced. - -The actual parameters (arguments) to a function call are introduced in -the local symbol table of the called function when it is called; thus, -arguments are passed using {\em call\ by\ value}.% -\footnote{ - Actually, {\em call by object reference} would be a better - description, since if a mutable object is passed, the caller - will see any changes the callee makes to it (e.g., items - inserted into a list). -} -When a function calls another function, a new local symbol table is -created for that call. - -A function definition introduces the function name in the -current -symbol table. The value -of the function name -has a type that is recognized by the interpreter as a user-defined -function. This value can be assigned to another name which can then -also be used as a function. This serves as a general renaming -mechanism: - -\bcode\begin{verbatim} ->>> fib - ->>> f = fib ->>> f(100) -1 1 2 3 5 8 13 21 34 55 89 ->>> -\end{verbatim}\ecode -% -You might object that {\tt fib} is not a function but a procedure. In -Python, like in C, procedures are just functions that don't return a -value. In fact, technically speaking, procedures do return a value, -albeit a rather boring one. This value is called {\tt None} (it's a -built-in name). Writing the value {\tt None} is normally suppressed by -the interpreter if it would be the only value written. You can see it -if you really want to: - -\bcode\begin{verbatim} ->>> print fib(0) -None ->>> -\end{verbatim}\ecode -% -It is simple to write a function that returns a list of the numbers of -the Fibonacci series, instead of printing it: - -\bcode\begin{verbatim} ->>> def fib2(n): # return Fibonacci series up to n -... result = [] -... a, b = 0, 1 -... while b <= n: -... result.append(b) # see below -... a, b = b, a+b -... return result -... ->>> f100 = fib2(100) # call it ->>> f100 # write the result -[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] ->>> -\end{verbatim}\ecode -% -This example, as usual, demonstrates some new Python features: - -\begin{itemize} - -\item -The {\tt return} statement returns with a value from a function. {\tt -return} without an expression argument is used to return from the middle -of a procedure (falling off the end also returns from a proceduce), in -which case the {\tt None} value is returned. - -\item -The statement {\tt result.append(b)} calls a {\em method} of the list -object {\tt result}. A method is a function that `belongs' to an -object and is named {\tt obj.methodname}, where {\tt obj} is some -object (this may be an expression), and {\tt methodname} is the name -of a method that is defined by the object's type. Different types -define different methods. Methods of different types may have the -same name without causing ambiguity. (It is possible to define your -own object types and methods, using {\em classes}. This is an -advanced feature that is not discussed in this tutorial.) -The method {\tt append} shown in the example, is defined for -list objects; it adds a new element at the end of the list. In this -example -it is equivalent to {\tt result = result + [b]}, but more efficient. - -\end{itemize} - - -\chapter{Odds and Ends} - -This chapter describes some things you've learned about already in -more detail, and adds some new things as well. - -\section{More on Lists} - -The list data type has some more methods. Here are all of the methods -of lists objects: - -\begin{description} - -\item[{\tt insert(i, x)}] -Insert an item at a given position. The first argument is the index of -the element before which to insert, so {\tt a.insert(0, x)} inserts at -the front of the list, and {\tt a.insert(len(a), x)} is equivalent to -{\tt a.append(x)}. - -\item[{\tt append(x)}] -Equivalent to {\tt a.insert(len(a), x)}. - -\item[{\tt index(x)}] -Return the index in the list of the first item whose value is {\tt x}. -It is an error if there is no such item. - -\item[{\tt remove(x)}] -Remove the first item from the list whose value is {\tt x}. -It is an error if there is no such item. - -\item[{\tt sort()}] -Sort the items of the list, in place. - -\item[{\tt reverse()}] -Reverse the elements of the list, in place. - -\end{description} - -An example that uses all list methods: - -\bcode\begin{verbatim} ->>> a = [66.6, 333, 333, 1, 1234.5] ->>> a.insert(2, -1) ->>> a.append(333) ->>> a -[66.6, 333, -1, 333, 1, 1234.5, 333] ->>> a.index(333) -1 ->>> a.remove(333) ->>> a -[66.6, -1, 333, 1, 1234.5, 333] ->>> a.reverse() ->>> a -[333, 1234.5, 1, 333, -1, 66.6] ->>> a.sort() ->>> a -[-1, 1, 66.6, 333, 333, 1234.5] ->>> -\end{verbatim}\ecode - -\section{The {\tt del} statement} - -There is a way to remove an item from a list given its index instead -of its value: the {\tt del} statement. This can also be used to -remove slices from a list (which we did earlier by assignment of an -empty list to the slice). For example: - -\bcode\begin{verbatim} ->>> a -[-1, 1, 66.6, 333, 333, 1234.5] ->>> del a[0] ->>> a -[1, 66.6, 333, 333, 1234.5] ->>> del a[2:4] ->>> a -[1, 66.6, 1234.5] ->>> -\end{verbatim}\ecode -% -{\tt del} can also be used to delete entire variables: - -\bcode\begin{verbatim} ->>> del a ->>> -\end{verbatim}\ecode -% -Referencing the name {\tt a} hereafter is an error (at least until -another value is assigned to it). We'll find other uses for {\tt del} -later. - -\section{Tuples and Sequences} - -We saw that lists and strings have many common properties, e.g., -indexinging and slicing operations. They are two examples of {\em -sequence} data types. Since Python is an evolving language, other -sequence data types may be added. There is also another standard -sequence data type: the {\em tuple}. - -A tuple consists of a number of values separated by commas, for -instance: - -\bcode\begin{verbatim} ->>> t = 12345, 54321, 'hello!' ->>> t[0] -12345 ->>> t -(12345, 54321, 'hello!') ->>> # Tuples may be nested: ->>> u = t, (1, 2, 3, 4, 5) ->>> u -((12345, 54321, 'hello!'), (1, 2, 3, 4, 5)) ->>> -\end{verbatim}\ecode -% -As you see, on output tuples are alway enclosed in parentheses, so -that nested tuples are interpreted correctly; they may be input with -or without surrounding parentheses, although often parentheses are -necessary anyway (if the tuple is part of a larger expression). - -Tuples have many uses, e.g., (x, y) coordinate pairs, employee records -from a database, etc. Tuples, like strings, are immutable: it is not -possible to assign to the individual items of a tuple (you can -simulate much of the same effect with slicing and concatenation, -though). - -A special problem is the construction of tuples containing 0 or 1 -items: the syntax has some extra quirks to accomodate these. Empty -tuples are constructed by an empty pair of parentheses; a tuple with -one item is constructed by following a value with a comma -(it is not sufficient to enclose a single value in parentheses). -Ugly, but effective. For example: - -\bcode\begin{verbatim} ->>> empty = () ->>> singleton = 'hello', # <-- note trailing comma ->>> len(empty) -0 ->>> len(singleton) -1 ->>> singleton -('hello',) ->>> -\end{verbatim}\ecode -% -The statement {\tt t = 12345, 54321, 'hello!'} is an example of {\em -tuple packing}: the values {\tt 12345}, {\tt 54321} and {\tt 'hello!'} -are packed together in a tuple. The reverse operation is also -possible, e.g.: - -\bcode\begin{verbatim} ->>> x, y, z = t ->>> -\end{verbatim}\ecode -% -This is called, appropriately enough, {\em tuple unpacking}. Tuple -unpacking requires that the list of variables on the left has the same -number of elements as the length of the tuple. Note that multiple -assignment is really just a combination of tuple packing and tuple -unpacking! - -Occasionally, the corresponding operation on lists is useful: {\em list -unpacking}. This is supported by enclosing the list of variables in -square brackets: - -\bcode\begin{verbatim} ->>> a = ['foo', 'bar', 100, 1234] ->>> [a1, a2, a3, a4] = a ->>> -\end{verbatim}\ecode - -\section{Dictionaries} - -Another useful data type built into Python is the {\em dictionary}. -Dictionaries are sometimes found in other languages as ``associative -memories'' or ``associative arrays''. Unlike sequences, which are -indexed by a range of numbers, dictionaries are indexed by {\em keys}, -which are strings. It is best to think of a dictionary as an unordered set of -{\em key:value} pairs, with the requirement that the keys are unique -(within one dictionary). -A pair of braces creates an empty dictionary: \verb/{}/. -Placing a comma-separated list of key:value pairs within the -braces adds initial key:value pairs to the dictionary; this is also the -way dictionaries are written on output. - -The main operations on a dictionary are storing a value with some key -and extracting the value given the key. It is also possible to delete -a key:value pair -with {\tt del}. -If you store using a key that is already in use, the old value -associated with that key is forgotten. It is an error to extract a -value using a non-existant key. - -The {\tt keys()} method of a dictionary object returns a list of all the -keys used in the dictionary, in random order (if you want it sorted, -just apply the {\tt sort()} method to the list of keys). To check -whether a single key is in the dictionary, use the \verb/has_key()/ -method of the dictionary. - -Here is a small example using a dictionary: - -\bcode\begin{verbatim} ->>> tel = {'jack': 4098, 'sape': 4139} ->>> tel['guido'] = 4127 ->>> tel -{'sape': 4139, 'guido': 4127, 'jack': 4098} ->>> tel['jack'] -4098 ->>> del tel['sape'] ->>> tel['irv'] = 4127 ->>> tel -{'guido': 4127, 'irv': 4127, 'jack': 4098} ->>> tel.keys() -['guido', 'irv', 'jack'] ->>> tel.has_key('guido') -1 ->>> -\end{verbatim}\ecode - -\section{More on Conditions} - -The conditions used in {\tt while} and {\tt if} statements above can -contain other operators besides comparisons. - -The comparison operators {\tt in} and {\tt not in} check whether a value -occurs (does not occur) in a sequence. The operators {\tt is} and {\tt -is not} compare whether two objects are really the same object; this -only matters for mutable objects like lists. All comparison operators -have the same priority, which is lower than that of all numerical -operators. - -Comparisons can be chained: e.g., {\tt a < b = c} tests whether {\tt a} -is less than {\tt b} and moreover {\tt b} equals {\tt c}. - -Comparisons may be combined by the Boolean operators {\tt and} and {\tt -or}, and the outcome of a comparison (or of any other Boolean -expression) may be negated with {\tt not}. These all have lower -priorities than comparison operators again; between them, {\tt not} has -the highest priority, and {\tt or} the lowest, so that -{\tt A and not B or C} is equivalent to {\tt (A and (not B)) or C}. Of -course, parentheses can be used to express the desired composition. - -The Boolean operators {\tt and} and {\tt or} are so-called {\em -shortcut} operators: their arguments are evaluated from left to right, -and evaluation stops as soon as the outcome is determined. E.g., if -{\tt A} and {\tt C} are true but {\tt B} is false, {\tt A and B and C} -does not evaluate the expression C. In general, the return value of a -shortcut operator, when used as a general value and not as a Boolean, is -the last evaluated argument. - -It is possible to assign the result of a comparison or other Boolean -expression to a variable, but you must enclose the entire Boolean -expression in parentheses. This is necessary because otherwise an -assignment like \verb/a = b = c/ would be ambiguous: does it assign the -value of {\tt c} to {\tt a} and {\tt b}, or does it compare {\tt b} to -{\tt c} and assign the outcome (0 or 1) to {\tt a}? As it is, the first -meaning is what you get, and to get the latter you have to write -\verb/a = (b = c)/. (In Python, unlike C, assignment cannot occur -inside expressions.) - -\section{Comparing Sequences and Other Types} - -Sequence objects may be compared to other objects with the same -sequence type. The comparison uses {\em lexicographical} ordering: -first the first two items are compared, and if they differ this -determines the outcome of the comparison; if they are equal, the next -two items are compared, and so on, until either sequence is exhausted. -If two items to be compared are themselves sequences of the same type, -the lexiographical comparison is carried out recursively. If all -items of two sequences compare equal, the sequences are considered -equal. If one sequence is an initial subsequence of the other, the -shorted sequence is the smaller one. Lexicographical ordering for -strings uses the ASCII ordering for individual characters. Some -examples of comparisons between sequences with the same types: - -\bcode\begin{verbatim} -(1, 2, 3) < (1, 2, 4) -[1, 2, 3] < [1, 2, 4] -'ABC' < 'C' < 'Pascal' < 'Python' -(1, 2, 3, 4) < (1, 2, 4) -(1, 2) < (1, 2, -1) -(1, 2, 3) = (1.0, 2.0, 3.0) -(1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4) -\end{verbatim}\ecode -% -Note that comparing objects of different types is legal. The outcome -is deterministic but arbitrary: the types are ordered by their name. -Thus, a list is always smaller than a string, a string is always -smaller than a tuple, etc. Mixed numeric types are compared according -to their numeric value, so 0 equals 0.0, etc.% -\footnote{ - The rules for comparing objects of different types should - not be relied upon; they may change in a future version of - the language. -} - - -\chapter{Modules} - -If you quit from the Python interpreter and enter it again, the -definitions you have made (functions and variables) are lost. -Therefore, if you want to write a somewhat longer program, you are -better off using a text editor to prepare the input for the interpreter -and run it with that file as input instead. This is known as creating a -{\em script}. As your program gets longer, you may want to split it -into several files for easier maintenance. You may also want to use a -handy function that you've written in several programs without copying -its definition into each program. - -To support this, Python has a way to put definitions in a file and use -them in a script or in an interactive instance of the interpreter. -Such a file is called a {\em module}; definitions from a module can be -{\em imported} into other modules or into the {\em main} module (the -collection of variables that you have access to in a script -executed at the top level -and in calculator mode). - -A module is a file containing Python definitions and statements. The -file name is the module name with the suffix {\tt .py} appended. For -instance, use your favorite text editor to create a file called {\tt -fibo.py} in the current directory with the following contents: - -\bcode\begin{verbatim} -# Fibonacci numbers module - -def fib(n): # write Fibonacci series up to n - a, b = 0, 1 - while b <= n: - print b, - a, b = b, a+b - -def fib2(n): # return Fibonacci series up to n - result = [] - a, b = 0, 1 - while b <= n: - result.append(b) - a, b = b, a+b - return result -\end{verbatim}\ecode -% -Now enter the Python interpreter and import this module with the -following command: - -\bcode\begin{verbatim} ->>> import fibo ->>> -\end{verbatim}\ecode -% -This does not enter the names of the functions defined in -{\tt fibo} -directly in the current symbol table; it only enters the module name -{\tt fibo} -there. -Using the module name you can access the functions: - -\bcode\begin{verbatim} ->>> fibo.fib(1000) -1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 ->>> fibo.fib2(100) -[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] ->>> -\end{verbatim}\ecode -% -If you intend to use a function often you can assign it to a local name: - -\bcode\begin{verbatim} ->>> fib = fibo.fib ->>> fib(500) -1 1 2 3 5 8 13 21 34 55 89 144 233 377 ->>> -\end{verbatim}\ecode - -\section{More on Modules} - -A module can contain executable statements as well as function -definitions. -These statements are intended to initialize the module. -They are executed only the -{\em first} -time the module is imported somewhere.% -\footnote{ - In fact function definitions are also `statements' that are - `executed'; the execution enters the function name in the - module's global symbol table. -} - -Each module has its own private symbol table, which is used as the -global symbol table by all functions defined in the module. -Thus, the author of a module can use global variables in the module -without worrying about accidental clashes with a user's global -variables. -On the other hand, if you know what you are doing you can touch a -module's global variables with the same notation used to refer to its -functions, -{\tt modname.itemname}. - -Modules can import other modules. -It is customary but not required to place all -{\tt import} -statements at the beginning of a module (or script, for that matter). -The imported module names are placed in the importing module's global -symbol table. - -There is a variant of the -{\tt import} -statement that imports names from a module directly into the importing -module's symbol table. -For example: - -\bcode\begin{verbatim} ->>> from fibo import fib, fib2 ->>> fib(500) -1 1 2 3 5 8 13 21 34 55 89 144 233 377 ->>> -\end{verbatim}\ecode -% -This does not introduce the module name from which the imports are taken -in the local symbol table (so in the example, {\tt fibo} is not -defined). - -There is even a variant to import all names that a module defines: - -\bcode\begin{verbatim} ->>> from fibo import * ->>> fib(500) -1 1 2 3 5 8 13 21 34 55 89 144 233 377 ->>> -\end{verbatim}\ecode -% -This imports all names except those beginning with an underscore -({\tt _}). - -\section{Standard Modules} - -Python comes with a library of standard modules, described in a separate -document (Python Library Reference). Some modules are built into the -interpreter; these provide access to operations that are not part of the -core of the language but are nevertheless built in, either for -efficiency or to provide access to operating system primitives such as -system calls. The set of such modules is a configuration option; e.g., -the {\tt amoeba} module is only provided on systems that somehow support -Amoeba primitives. One particular module deserves some attention: {\tt -sys}, which is built into every Python interpreter. The variables {\tt -sys.ps1} and {\tt sys.ps2} define the strings used as primary and -secondary prompts: - -\bcode\begin{verbatim} ->>> import sys ->>> sys.ps1 -'>>> ' ->>> sys.ps2 -'... ' ->>> sys.ps1 = 'C> ' -C> print 'Yuck!' -Yuck! -C> -\end{verbatim}\ecode -% -These two variables are only defined if the interpreter is in -interactive mode. - -The variable -{\tt sys.path} -is a list of strings that determine the interpreter's search path for -modules. -It is initialized to a default path taken from the environment variable -{\tt PYTHONPATH}, -or from a built-in default if -{\tt PYTHONPATH} -is not set. -You can modify it using standard list operations, e.g.: - -\bcode\begin{verbatim} ->>> import sys ->>> sys.path.append('/ufs/guido/lib/python') ->>> -\end{verbatim}\ecode - -\section{The {\tt dir()} function} - -The built-in function {\tt dir} is used to find out which names a module -defines. It returns a sorted list of strings: - -\bcode\begin{verbatim} ->>> import fibo, sys ->>> dir(fibo) -['fib', 'fib2'] ->>> dir(sys) -['argv', 'exit', 'modules', 'path', 'ps1', 'ps2', 'stderr', 'stdin', 'stdout'] ->>> -\end{verbatim}\ecode -% -Without arguments, {\tt dir()} lists the names you have defined currently: - -\bcode\begin{verbatim} ->>> a = [1, 2, 3, 4, 5] ->>> import fibo, sys ->>> fib = fibo.fib ->>> dir() -['a', 'fib', 'fibo', 'sys'] ->>> -\end{verbatim}\ecode -% -Note that it lists all types of names: variables, modules, functions, etc. - -{\tt dir()} does not list the names of built-in functions and variables. -If you want a list of those, they are defined in the standard module -{\tt __builtin__}: - -\bcode\begin{verbatim} ->>> import __builtin__ ->>> dir(__builtin__) -['AccessError', 'AttributeError', 'ConflictError', 'EOFError', 'IOError', 'I -mportError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'MemoryError', ' -NameError', 'None', 'OverflowError', 'RuntimeError', 'SyntaxError', 'SystemE -rror', 'SystemExit', 'TypeError', 'ValueError', 'ZeroDivisionError', 'abs', -'apply', 'chr', 'cmp', 'coerce', 'compile', 'dir', 'divmod', 'eval', 'execfi -le', 'float', 'getattr', 'hasattr', 'hash', 'hex', 'id', 'input', 'int', 'le -n', 'long', 'max', 'min', 'oct', 'open', 'ord', 'pow', 'range', 'raw_input', - 'reload', 'repr', 'round', 'setattr', 'str', 'type'] ->>> -\end{verbatim}\ecode - - -\chapter{Output Formatting} - -So far we've encountered two ways of writing values: {\em expression -statements} and the {\tt print} statement. (A third way is using the -{\tt write} method of file objects; the standard output file can be -referenced as {\tt sys.stdout}. See the Library Reference for more -information on this.) - -Often you'll want more control over the formatting of your output than -simply printing space-separated values. The key to nice formatting in -Python is to do all the string handling yourself; using string slicing -and concatenation operations you can create any lay-out you can imagine. -The standard module {\tt string} contains some useful operations for -padding strings to a given column width; these will be discussed shortly. - -One question remains, of course: how do you convert values to strings? -Luckily, Python has a way to convert any value to a string: just write -the value between reverse quotes (\verb/``/). Some examples: - -\bcode\begin{verbatim} ->>> x = 10 * 3.14 ->>> y = 200*200 ->>> s = 'The value of x is ' + `x` + ', and y is ' + `y` + '...' ->>> print s -The value of x is 31.4, and y is 40000... ->>> # Reverse quotes work on other types besides numbers: ->>> p = [x, y] ->>> ps = `p` ->>> ps -'[31.4, 40000]' ->>> # Converting a string adds string quotes and backslashes: ->>> hello = 'hello, world\n' ->>> hellos = `hello` ->>> print hellos -'hello, world\012' ->>> # The argument of reverse quotes may be a tuple: ->>> `x, y, ('foo', 'bar')` -'(31.4, 40000, (\'foo\', \'bar\'))' ->>> -\end{verbatim}\ecode -% -Here is how you write a table of squares and cubes: - -\bcode\begin{verbatim} ->>> import string ->>> for x in range(1, 11): -... print string.rjust(`x`, 2), string.rjust(`x*x`, 3), -... # Note trailing comma on previous line -... print string.rjust(`x*x*x`, 4) -... - 1 1 1 - 2 4 8 - 3 9 27 - 4 16 64 - 5 25 125 - 6 36 216 - 7 49 343 - 8 64 512 - 9 81 729 -10 100 1000 ->>> -\end{verbatim}\ecode -% -(Note that one space between each column was added by the way {\tt print} -works: it always adds spaces between its arguments.) - -This example demonstrates the function {\tt string.rjust()}, which -right-justifies a string in a field of a given width by padding it with -spaces on the left. There are similar functions {\tt string.ljust()} -and {\tt string.center()}. These functions do not write anything, they -just return a new string. If the input string is too long, they don't -truncate it, but return it unchanged; this will mess up your column -lay-out but that's usually better than the alternative, which would be -lying about a value. (If you really want truncation you can always add -a slice operation, as in {\tt string.ljust(x,~n)[0:n]}.) - -There is another function, {\tt string.zfill}, which pads a numeric -string on the left with zeros. It understands about plus and minus -signs:% -\footnote{ - Better facilities for formatting floating point numbers are - lacking at this moment. -} - -\bcode\begin{verbatim} ->>> string.zfill('12', 5) -'00012' ->>> string.zfill('-3.14', 7) -'-003.14' ->>> string.zfill('3.14159265359', 5) -'3.14159265359' ->>> -\end{verbatim}\ecode - - -\chapter{Errors and Exceptions} - -Until now error messages haven't been more than mentioned, but if you -have tried out the examples you have probably seen some. There are -(at least) two distinguishable kinds of errors: {\em syntax\ errors} -and {\em exceptions}. - -\section{Syntax Errors} - -Syntax errors, also known as parsing errors, are perhaps the most common -kind of complaint you get while you are still learning Python: - -\bcode\begin{verbatim} ->>> while 1 print 'Hello world' -Parsing error: file , line 1: -while 1 print 'Hello world' - ^ -Unhandled exception: run-time error: syntax error ->>> -\end{verbatim}\ecode -% -The parser repeats the offending line and displays a little `arrow' -pointing at the earliest point in the line where the error was detected. -The error is caused by (or at least detected at) the token -{\em preceding} -the arrow: in the example, the error is detected at the keyword -{\tt print}, since a colon ({\tt :}) is missing before it. -File name and line number are printed so you know where to look in case -the input came from a script. - -\section{Exceptions} - -Even if a statement or expression is syntactically correct, it may -cause an error when an attempt is made to execute it. -Errors detected during execution are called {\em exceptions} and are -not unconditionally fatal: you will soon learn how to handle them in -Python programs. Most exceptions are not handled by programs, -however, and result in error messages as shown here: - -\bcode\small\begin{verbatim} ->>> 10 * (1/0) -Traceback (innermost last): - File "", line 1 -ZeroDivisionError: integer division or modulo ->>> 4 + foo*3 -Stack backtrace (innermost last): - File "", line 1 -NameError: foo ->>> '2' + 2 -Stack backtrace (innermost last): - File "", line 1 -TypeError: illegal argument type for built-in operation ->>> -\end{verbatim}\ecode -% -The last line of the error message indicates what happened. -Exceptions come in different types, and the type is printed as part of -the message: the types in the example are -{\tt ZeroDivisionError}, -{\tt NameError} -and -{\tt TypeError}. -The string printed as the exception type is the name of the built-in -name for the exception that occurred. This is true for all built-in -exceptions, but need not be true for user-defined exceptions (although -it is a useful convention). -Standard exception names are built-in identifiers (not reserved -keywords). - -The rest of the line is a detail whose interpretation depends on the -exception type; its meaning is dependent on the exception type. - -The preceding part of the error message shows the context where the -exception happened, in the form of a stack backtrace. -In general it contains a stack backtrace listing source lines; however, -it will not display lines read from standard input. - -The Python library reference manual lists the built-in exceptions and -their meanings. - -\section{Handling Exceptions} - -It is possible to write programs that handle selected exceptions. -Look at the following example, which prints a table of inverses of -some floating point numbers: - -\bcode\begin{verbatim} ->>> numbers = [0.3333, 2.5, 0, 10] ->>> for x in numbers: -... print x, -... try: -... print 1.0 / x -... except ZeroDivisionError: -... print '*** has no inverse ***' -... -0.3333 3.00030003 -2.5 0.4 -0 *** has no inverse *** -10 0.1 ->>> -\end{verbatim}\ecode -% -The {\tt try} statement works as follows. -\begin{itemize} -\item -First, the -{\em try\ clause} -(the statement(s) between the {\tt try} and {\tt except} keywords) is -executed. -\item -If no exception occurs, the -{\em except\ clause} -is skipped and execution of the {\tt try} statement is finished. -\item -If an exception occurs during execution of the try clause, -the rest of the clause is skipped. Then if -its type matches the exception named after the {\tt except} keyword, -the rest of the try clause is skipped, the except clause is executed, -and then execution continues after the {\tt try} statement. -\item -If an exception occurs which does not match the exception named in the -except clause, it is passed on to outer try statements; if no handler is -found, it is an -{\em unhandled\ exception} -and execution stops with a message as shown above. -\end{itemize} -A {\tt try} statement may have more than one except clause, to specify -handlers for different exceptions. -At most one handler will be executed. -Handlers only handle exceptions that occur in the corresponding try -clause, not in other handlers of the same {\tt try} statement. -An except clause may name multiple exceptions as a parenthesized list, -e.g.: - -\bcode\begin{verbatim} -... except (RuntimeError, TypeError, NameError): -... pass -\end{verbatim}\ecode -% -The last except clause may omit the exception name(s), to serve as a -wildcard. -Use this with extreme caution, since it is easy to mask a real -programming error in this way! - -When an exception occurs, it may have an associated value, also known as -the exceptions's -{\em argument}. -The presence and type of the argument depend on the exception type. -For exception types which have an argument, the except clause may -specify a variable after the exception name (or list) to receive the -argument's value, as follows: - -\bcode\begin{verbatim} ->>> try: -... foo() -... except NameError, x: -... print 'name', x, 'undefined' -... -name foo undefined ->>> -\end{verbatim}\ecode -% -If an exception has an argument, it is printed as the last part -(`detail') of the message for unhandled exceptions. - -Exception handlers don't just handle exceptions if they occur -immediately in the try clause, but also if they occur inside functions -that are called (even indirectly) in the try clause. -For example: - -\bcode\begin{verbatim} ->>> def this_fails(): -... x = 1/0 -... ->>> try: -... this_fails() -... except ZeroDivisionError, detail: -... print 'Handling run-time error:', detail -... -Handling run-time error: integer division or modulo ->>> -\end{verbatim}\ecode - -\section{Raising Exceptions} - -The {\tt raise} statement allows the programmer to force a specified -exception to occur. -For example: - -\bcode\begin{verbatim} ->>> raise NameError, 'HiThere' -Stack backtrace (innermost last): - File "", line 1 -NameError: HiThere ->>> -\end{verbatim}\ecode -% -The first argument to {\tt raise} names the exception to be raised. -The optional second argument specifies the exception's argument. - -\section{User-defined Exceptions} - -Programs may name their own exceptions by assigning a string to a -variable. -For example: - -\bcode\begin{verbatim} ->>> my_exc = 'my_exc' ->>> try: -... raise my_exc, 2*2 -... except my_exc, val: -... print 'My exception occurred, value:', val -... -My exception occured, value: 4 ->>> raise my_exc, 1 -Stack backtrace (innermost last): - File "", line 7 -my_exc: 1 ->>> -\end{verbatim}\ecode -% -Many standard modules use this to report errors that may occur in -functions they define. - -\section{Defining Clean-up Actions} - -The {\tt try} statement has another optional clause which is intended to -define clean-up actions that must be executed under all circumstances. -For example: - -\bcode\begin{verbatim} ->>> try: -... raise KeyboardInterrupt -... finally: -... print 'Goodbye, world!' -... -Goodbye, world! -Stack backtrace (innermost last): - File "", line 2 -KeyboardInterrupt ->>> -\end{verbatim}\ecode -% -A {\tt finally} clause is executed whether or not an exception has -occurred in the {\tt try} clause. When an exception has occurred, it -is re-raised after the {\tt finally} clauses is executed. The -{\tt finally} clause is also executed ``on the way out'' when the -{\tt try} statement is left via a {\tt break} or {\tt return} -statement. - -A {\tt try} statement must either have one or more {\tt except} -clauses or one {\tt finally} clause, but not both. - - -\chapter{Classes} - -Python's class mechanism adds classes to the language with a minimum -of new syntax and semantics. It is a mixture of the class mechanisms -found in C++ and Modula-3. As is true for modules, classes in Python -do not put an absolute barrier between definition and user, but rather -rely on the politeness of the user not to ``break into the -definition.'' The most important features of classes are retained -with full power, however: the class inheritance mechanism allows -multiple base classes, a derived class can override any methods of its -base class(es), a method can call the method of a base class with the -same name. Objects can contain an arbitrary amount of private data. - -In C++ terminology, all class members (including the data members) are -{\em public}, and all member functions are {\em virtual}. There are -no special constructors or desctructors. As in Modula-3, there are no -shorthands for referencing the object's members from its methods: the -method function is declared with an explicit first argument -representing the object, which is provided implicitly by the call. As -in Smalltalk, classes themselves are objects, albeit in the wider -sense of the word: in Python, all data types are objects. This -provides semantics for importing and renaming. But, just like in C++ -or Modula-3, built-in types cannot be used as base classes for -extension by the user. Also, like in Modula-3 but unlike in C++, the -built-in operators with special syntax (arithmetic operators, -subscriptong etc.) cannot be redefined for class members. - - -\section{A word about terminology} - -Lacking universally accepted terminology to talk about classes, I'll -make occasional use of Smalltalk and C++ terms. (I'd use Modula-3 -terms, since its object-oriented semantics are closer to those of -Python than C++, but I expect that few readers have heard of it...) - -I also have to warn you that there's a terminological pitfall for -object-oriented readers: the word ``object'' in Python does not -necessarily mean a class instance. Like C++ and Modula-3, and unlike -Smalltalk, not all types in Python are classes: the basic built-in -types like integers and lists aren't, and even somewhat more exotic -types like files aren't. However, {\em all} Python types share a little -bit of common semantics that is best described by using the word -object. - -Objects have individuality, and multiple names (in multiple scopes) -can be bound to the same object. This is known as aliasing in other -languages. This is usually not appreciated on a first glance at -Python, and can be safely ignored when dealing with immutable basic -types (numbers, strings, tuples). However, aliasing has an -(intended!) effect on the semantics of Python code involving mutable -objects such as lists, dictionaries, and most types representing -entities outside the program (files, windows, etc.). This is usually -used to the benefit of the program, since aliases behave like pointers -in some respects. For example, passing an object is cheap since only -a pointer is passed by the implementation; and if a function modifies -an object passed as an argument, the caller will see the change --- this -obviates the need for two different argument passing mechanisms as in -Pascal. - - -\section{Python scopes and name spaces} - -Before introducing classes, I first have to tell you something about -Python's scope rules. Class definitions play some neat tricks with -name spaces, and you need to know how scopes and name spaces work to -fully understand what's going on. Incidentally, knowledge about this -subject is useful for any advanced Python programmer. - -Let's begin with some definitions. - -A {\em name space} is a mapping from names to objects. Most name -spaces are currently implemented as Python dictionaries, but that's -normally not noticeable in any way (except for performance), and it -may change in the future. Examples of name spaces are: the set of -built-in names (functions such as \verb\abs()\, and built-in exception -names); the global names in a module; and the local names in a -function invocation. In a sense the set of attributes of an object -also form a name space. The important things to know about name -spaces is that there is absolutely no relation between names in -different name spaces; for instance, two different modules may both -define a function ``maximize'' without confusion --- users of the -modules must prefix it with the module name. - -By the way, I use the word {\em attribute} for any name following a -dot --- for example, in the expression \verb\z.real\, \verb\real\ is -an attribute of the object \verb\z\. Strictly speaking, references to -names in modules are attribute references: in the expression -\verb\modname.funcname\, \verb\modname\ is a module object and -\verb\funcname\ is an attribute of it. In this case there happens to -be a straightforward mapping between the module's attributes and the -global names defined in the module: they share the same name space!% -\footnote{ - Except for one thing. Module objects have a secret read-only - attribute called {\tt __dict__} which returns the dictionary - used to implement the module's name space; the name - {\tt __dict__} is an attribute but not a global name. - Obviously, using this violates the abstraction of name space - implementation, and should be restricted to things like - post-mortem debuggers... -} - -Attributes may be read-only or writable. In the latter case, -assignment to attributes is possible. Module attributes are writable: -you can write \verb\modname.the_answer = 42\. Writable attributes may -also be deleted with the del statement, e.g. -\verb\del modname.the_answer\. - -Name spaces are created at different moments and have different -lifetimes. The name space containing the built-in names is created -when the Python interpreter starts up, and is never deleted. The -global name space for a module is created when the module definition -is read in; normally, module name spaces also last until the -interpreter quits. The statements executed by the top-level -invocation of the interpreter, either read from a script file or -interactively, are considered part of a module called \verb\__main__\, -so they have their own global name space. (The built-in names -actually also live in a module; this is called \verb\__builtin__\.) - -The local name space for a function is created when the function is -called, and deleted when the function returns or raises an exception -that is not handled within the function. (Actually, forgetting would -be a better way to describe what actually happens.) Of course, -recursive invocations each have their own local name space. - -A {\em scope} is a textual region of a Python program where a name space -is directly accessible. ``Directly accessible'' here means that an -unqualified reference to a name attempts to find the name in the name -space. - -Although scopes are determined statically, they are used dynamically. -At any time during execution, exactly three nested scopes are in use -(i.e., exactly three name spaces are directly accessible): the -innermost scope, which is searched first, contains the local names, -the middle scope, searched next, contains the current module's global -names, and the outermost scope (searched last) is the name space -containing built-in names. - -Usually, the local scope references the local names of the (textually) -current function. Outside functions, the the local scope references -the same name space as the global scope: the module's name space. -Class definitions place yet another name space in the local scope. - -It is important to realize that scopes are determined textually: the -global scope of a function defined in a module is that module's name -space, no matter from where or by what alias the function is called. -On the other hand, the actual search for names is done dynamically, at -run time --- however, the the language definition is evolving towards -static name resolution, at ``compile'' time, so don't rely on dynamic -name resolution! (In fact, local variables are already determined -statically.) - -A special quirk of Python is that assignments always go into the -innermost scope. Assignments do not copy data --- they just -bind names to objects. The same is true for deletions: the statement -\verb\del x\ removes the binding of x from the name space referenced by the -local scope. In fact, all operations that introduce new names use the -local scope: in particular, import statements and function definitions -bind the module or function name in the local scope. (The -\verb\global\ statement can be used to indicate that particular -variables live in the global scope.) - - -\section{A first look at classes} - -Classes introduce a little bit of new syntax, three new object types, -and some new semantics. - - -\subsection{Class definition syntax} - -The simplest form of class definition looks like this: - -\begin{verbatim} - class ClassName: - - . - . - . - -\end{verbatim} - -Class definitions, like function definitions (\verb\def\ statements) -must be executed before they have any effect. (You could conceivably -place a class definition in a branch of an \verb\if\ statement, or -inside a function.) - -In practice, the statements inside a class definition will usually be -function definitions, but other statements are allowed, and sometimes -useful --- we'll come back to this later. The function definitions -inside a class normally have a peculiar form of argument list, -dictated by the calling conventions for methods --- again, this is -explained later. - -When a class definition is entered, a new name space is created, and -used as the local scope --- thus, all assignments to local variables -go into this new name space. In particular, function definitions bind -the name of the new function here. - -When a class definition is left normally (via the end), a {\em class -object} is created. This is basically a wrapper around the contents -of the name space created by the class definition; we'll learn more -about class objects in the next section. The original local scope -(the one in effect just before the class definitions was entered) is -reinstated, and the class object is bound here to class name given in -the class definition header (ClassName in the example). - - -\subsection{Class objects} - -Class objects support two kinds of operations: attribute references -and instantiation. - -{\em Attribute references} use the standard syntax used for all -attribute references in Python: \verb\obj.name\. Valid attribute -names are all the names that were in the class's name space when the -class object was created. So, if the class definition looked like -this: - -\begin{verbatim} - class MyClass: - i = 12345 - def f(x): - return 'hello world' -\end{verbatim} - -then \verb\MyClass.i\ and \verb\MyClass.f\ are valid attribute -references, returning an integer and a function object, respectively. -Class attributes can also be assigned to, so you can change the -value of \verb\MyClass.i\ by assignment. - -Class {\em instantiation} uses function notation. Just pretend that -the class object is a parameterless function that returns a new -instance of the class. For example, (assuming the above class): - -\begin{verbatim} - x = MyClass() -\end{verbatim} - -creates a new {\em instance} of the class and assigns this object to -the local variable \verb\x\. - - -\subsection{Instance objects} - -Now what can we do with instance objects? The only operations -understood by instance objects are attribute references. There are -two kinds of valid attribute names. - -The first I'll call {\em data attributes}. These correspond to -``instance variables'' in Smalltalk, and to ``data members'' in C++. -Data attributes need not be declared; like local variables, they -spring into existence when they are first assigned to. For example, -if \verb\x\ in the instance of \verb\MyClass\ created above, the -following piece of code will print the value 16, without leaving a -trace: - -\begin{verbatim} - x.counter = 1 - while x.counter < 10: - x.counter = x.counter * 2 - print x.counter - del x.counter -\end{verbatim} - -The second kind of attribute references understood by instance objects -are {\em methods}. A method is a function that ``belongs to'' an -object. (In Python, the term method is not unique to class instances: -other object types can have methods as well, e.g., list objects have -methods called append, insert, remove, sort, and so on. However, -below, we'll use the term method exclusively to mean methods of class -instance objects, unless explicitly stated otherwise.) - -Valid method names of an instance object depend on its class. By -definition, all attributes of a class that are (user-defined) function -objects define corresponding methods of its instances. So in our -example, \verb\x.f\ is a valid method reference, since -\verb\MyClass.f\ is a function, but \verb\x.i\ is not, since -\verb\MyClass.i\ is not. But \verb\x.f\ is not the -same thing as \verb\MyClass.f\ --- it is a {\em method object}, not a -function object. - - -\subsection{Method objects} - -Usually, a method is called immediately, e.g.: - -\begin{verbatim} - x.f() -\end{verbatim} - -In our example, this will return the string \verb\'hello world'\. -However, it is not necessary to call a method right away: \verb\x.f\ -is a method object, and can be stored away and called at a later -moment, for example: - -\begin{verbatim} - xf = x.f - while 1: - print xf() -\end{verbatim} - -will continue to print \verb\hello world\ until the end of time. - -What exactly happens when a method is called? You may have noticed -that \verb\x.f()\ was called without an argument above, even though -the function definition for \verb\f\ specified an argument. What -happened to the argument? Surely Python raises an exception when a -function that requires an argument is called without any --- even if -the argument isn't actually used... - -Actually, you may have guessed the answer: the special thing about -methods is that the object is passed as the first argument of the -function. In our example, the call \verb\x.f()\ is exactly equivalent -to \verb\MyClass.f(x)\. In general, calling a method with a list of -{\em n} arguments is equivalent to calling the corresponding function -with an argument list that is created by inserting the method's object -before the first argument. - -If you still don't understand how methods work, a look at the -implementation can perhaps clarify matters. When an instance -attribute is referenced that isn't a data attribute, its class is -searched. If the name denotes a valid class attribute that is a -function object, a method object is created by packing (pointers to) -the instance object and the function object just found together in an -abstract object: this is the method object. When the method object is -called with an argument list, it is unpacked again, a new argument -list is constructed from the instance object and the original argument -list, and the function object is called with this new argument list. - - -\section{Random remarks} - - -[These should perhaps be placed more carefully...] - - -Data attributes override method attributes with the same name; to -avoid accidental name conflicts, which may cause hard-to-find bugs in -large programs, it is wise to use some kind of convention that -minimizes the chance of conflicts, e.g., capitalize method names, -prefix data attribute names with a small unique string (perhaps just -an undescore), or use verbs for methods and nouns for data attributes. - - -Data attributes may be referenced by methods as well as by ordinary -users (``clients'') of an object. In other words, classes are not -usable to implement pure abstract data types. In fact, nothing in -Python makes it possible to enforce data hiding --- it is all based -upon convention. (On the other hand, the Python implementation, -written in C, can completely hide implementation details and control -access to an object if necessary; this can be used by extensions to -Python written in C.) - - -Clients should use data attributes with care --- clients may mess up -invariants maintained by the methods by stamping on their data -attributes. Note that clients may add data attributes of their own to -an instance object without affecting the validity of the methods, as -long as name conflicts are avoided --- again, a naming convention can -save a lot of headaches here. - - -There is no shorthand for referencing data attributes (or other -methods!) from within methods. I find that this actually increases -the readability of methods: there is no chance of confusing local -variables and instance variables when glancing through a method. - - -Conventionally, the first argument of methods is often called -\verb\self\. This is nothing more than a convention: the name -\verb\self\ has absolutely no special meaning to Python. (Note, -however, that by not following the convention your code may be less -readable by other Python programmers, and it is also conceivable that -a {\em class browser} program be written which relies upon such a -convention.) - - -Any function object that is a class attribute defines a method for -instances of that class. It is not necessary that the function -definition is textually enclosed in the class definition: assigning a -function object to a local variable in the class is also ok. For -example: - -\begin{verbatim} - # Function defined outside the class - def f1(self, x, y): - return min(x, x+y) - - class C: - f = f1 - def g(self): - return 'hello world' - h = g -\end{verbatim} - -Now \verb\f\, \verb\g\ and \verb\h\ are all attributes of class -\verb\C\ that refer to function objects, and consequently they are all -methods of instances of \verb\C\ --- \verb\h\ being exactly equivalent -to \verb\g\. Note that this practice usually only serves to confuse -the reader of a program. - - -Methods may call other methods by using method attributes of the -\verb\self\ argument, e.g.: - -\begin{verbatim} - class Bag: - def empty(self): - self.data = [] - def add(self, x): - self.data.append(x) - def addtwice(self, x): - self.add(x) - self.add(x) -\end{verbatim} - - -The instantiation operation (``calling'' a class object) creates an -empty object. Many classes like to create objects in a known initial -state. There is no special syntax to enforce this, but a convention -works almost as well: add a method named \verb\init\ to the class, -which initializes the instance (by assigning to some important data -attributes) and returns the instance itself. For example, class -\verb\Bag\ above could have the following method: - -\begin{verbatim} - def init(self): - self.empty() - return self -\end{verbatim} - -The client can then create and initialize an instance in one -statement, as follows: - -\begin{verbatim} - x = Bag().init() -\end{verbatim} - -Of course, the \verb\init\ method may have arguments for greater -flexibility. - -Warning: a common mistake is to forget the \verb\return self\ at the -end of an init method! - - -Methods may reference global names in the same way as ordinary -functions. The global scope associated with a method is the module -containing the class definition. (The class itself is never used as a -global scope!) While one rarely encounters a good reason for using -global data in a method, there are many legitimate uses of the global -scope: for one thing, functions and modules imported into the global -scope can be used by methods, as well as functions and classes defined -in it. Usually, the class containing the method is itself defined in -this global scope, and in the next section we'll find some good -reasons why a method would want to reference its own class! - - -\section{Inheritance} - -Of course, a language feature would not be worthy of the name ``class'' -without supporting inheritance. The syntax for a derived class -definition looks as follows: - -\begin{verbatim} - class DerivedClassName(BaseClassName): - - . - . - . - -\end{verbatim} - -The name \verb\BaseClassName\ must be defined in a scope containing -the derived class definition. Instead of a base class name, an -expression is also allowed. This is useful when the base class is -defined in another module, e.g., - -\begin{verbatim} - class DerivedClassName(modname.BaseClassName): -\end{verbatim} - -Execution of a derived class definition proceeds the same as for a -base class. When the class object is constructed, the base class is -remembered. This is used for resolving attribute references: if a -requested attribute is not found in the class, it is searched in the -base class. This rule is applied recursively if the base class itself -is derived from some other class. - -There's nothing special about instantiation of derived classes: -\verb\DerivedClassName()\ creates a new instance of the class. Method -references are resolved as follows: the corresponding class attribute -is searched, descending down the chain of base classes if necessary, -and the method reference is valid if this yields a function object. - -Derived classes may override methods of their base classes. Because -methods have no special privileges when calling other methods of the -same object, a method of a base class that calls another method -defined in the same base class, may in fact end up calling a method of -a derived class that overrides it. (For C++ programmers: all methods -in Python are ``virtual functions''.) - -An overriding method in a derived class may in fact want to extend -rather than simply replace the base class method of the same name. -There is a simple way to call the base class method directly: just -call \verb\BaseClassName.methodname(self, arguments)\. This is -occasionally useful to clients as well. (Note that this only works if -the base class is defined or imported directly in the global scope.) - - -\subsection{Multiple inheritance} - -Poython supports a limited form of multiple inheritance as well. A -class definition with multiple base classes looks as follows: - -\begin{verbatim} - class DerivedClassName(Base1, Base2, Base3): - - . - . - . - -\end{verbatim} - -The only rule necessary to explain the semantics is the resolution -rule used for class attribute references. This is depth-first, -left-to-right. Thus, if an attribute is not found in -\verb\DerivedClassName\, it is searched in \verb\Base1\, then -(recursively) in the base classes of \verb\Base1\, and only if it is -not found there, it is searched in \verb\Base2\, and so on. - -(To some people breadth first---searching \verb\Base2\ and -\verb\Base3\ before the base classes of \verb\Base1\---looks more -natural. However, this would require you to know whether a particular -attribute of \verb\Base1\ is actually defined in \verb\Base1\ or in -one of its base classes before you can figure out the consequences of -a name conflict with an attribute of \verb\Base2\. The depth-first -rule makes no differences between direct and inherited attributes of -\verb\Base1\.) - -It is clear that indiscriminate use of multiple inheritance is a -maintenance nightmare, given the reliance in Python on conventions to -avoid accidental name conflicts. A well-known problem with multiple -inheritance is a class derived from two classes that happen to have a -common base class. While it is easy enough to figure out what happens -in this case (the instance will have a single copy of ``instance -variables'' or data attributes used by the common base class), it is -not clear that these semantics are in any way useful. - - -\section{Odds and ends} - -Sometimes it is useful to have a data type similar to the Pascal -``record'' or C ``struct'', bundling together a couple of named data -items. An empty class definition will do nicely, e.g.: - -\begin{verbatim} - class Employee: - pass - - john = Employee() # Create an empty employee record - - # Fill the fields of the record - john.name = 'John Doe' - john.dept = 'computer lab' - john.salary = 1000 -\end{verbatim} - - -A piece of Python code that expects a particular abstract data type -can often be passed a class that emulates the methods of that data -type instead. For instance, if you have a function that formats some -data from a file object, you can define a class with methods -\verb\read()\ and \verb\readline()\ that gets the data from a string -buffer instead, and pass it as an argument. (Unfortunately, this -technique has its limitations: a class can't define operations that -are accessed by special syntax such as sequence subscripting or -arithmetic operators, and assigning such a ``pseudo-file'' to -\verb\sys.stdin\ will not cause the interpreter to read further input -from it.) - - -Instance method objects have attributes, too: \verb\m.im_self\ is the -object of which the method is an instance, and \verb\m.im_func\ is the -function object corresponding to the method. - - -XXX Mention bw compat hacks. - - -\end{document} diff --git a/Doc/tut/tut.tex b/Doc/tut/tut.tex deleted file mode 100644 index 532748876a..0000000000 --- a/Doc/tut/tut.tex +++ /dev/null @@ -1,2565 +0,0 @@ -\documentstyle[twoside,11pt,myformat]{report} - -\title{\bf - Python Tutorial -} - -\author{ - Guido van Rossum \\ - Dept. CST, CWI, P.O. Box 94079 \\ - 1090 GB Amsterdam, The Netherlands \\ - E-mail: {\tt guido@cwi.nl} -} - -\date{19 November 1993 \\ Release 0.9.9.++} % XXX update before release! - -\begin{document} - -\pagenumbering{roman} - -\maketitle - -\begin{abstract} - -\noindent -Python is a simple, yet powerful programming language that bridges the -gap between C and shell programming, and is thus ideally suited for -``throw-away programming'' -and rapid prototyping. Its syntax is put -together from constructs borrowed from a variety of other languages; -most prominent are influences from ABC, C, Modula-3 and Icon. - -The Python interpreter is easily extended with new functions and data -types implemented in C. Python is also suitable as an extension -language for highly customizable C applications such as editors or -window managers. - -Python is available for various operating systems, amongst which -several flavors of {\UNIX}, Amoeba, the Apple Macintosh O.S., -and MS-DOS. - -This tutorial introduces the reader informally to the basic concepts -and features of the Python language and system. It helps to have a -Python interpreter handy for hands-on experience, but as the examples -are self-contained, the tutorial can be read off-line as well. - -For a description of standard objects and modules, see the {\em Python -Library Reference} document. The {\em Python Reference Manual} gives -a more formal definition of the language. - -\end{abstract} - -\pagebreak -{ -\parskip = 0mm -\tableofcontents -} - -\pagebreak - -\pagenumbering{arabic} - - -\chapter{Whetting Your Appetite} - -If you ever wrote a large shell script, you probably know this -feeling: you'd love to add yet another feature, but it's already so -slow, and so big, and so complicated; or the feature involves a system -call or other funcion that is only accessible from C \ldots Usually -the problem at hand isn't serious enough to warrant rewriting the -script in C; perhaps because the problem requires variable-length -strings or other data types (like sorted lists of file names) that are -easy in the shell but lots of work to implement in C; or perhaps just -because you're not sufficiently familiar with C. - -In such cases, Python may be just the language for you. Python is -simple to use, but it is a real programming language, offering much -more structure and support for large programs than the shell has. On -the other hand, it also offers much more error checking than C, and, -being a {\em very-high-level language}, it has high-level data types -built in, such as flexible arrays and dictionaries that would cost you -days to implement efficiently in C. Because of its more general data -types Python is applicable to a much larger problem domain than {\em -Awk} or even {\em Perl}, yet many things are at least as easy in -Python as in those languages. - -Python allows you to split up your program in modules that can be -reused in other Python programs. It comes with a large collection of -standard modules that you can use as the basis of your programs --- or -as examples to start learning to program in Python. There are also -built-in modules that provide things like file I/O, system calls, -sockets, and even a generic interface to window systems (STDWIN). - -Python is an interpreted language, which can save you considerable time -during program development because no compilation and linking is -necessary. The interpreter can be used interactively, which makes it -easy to experiment with features of the language, to write throw-away -programs, or to test functions during bottom-up program development. -It is also a handy desk calculator. - -Python allows writing very compact and readable programs. Programs -written in Python are typically much shorter than equivalent C -programs, for several reasons: -\begin{itemize} -\item -the high-level data types allow you to express complex operations in a -single statement; -\item -statement grouping is done by indentation instead of begin/end -brackets; -\item -no variable or argument declarations are necessary. -\end{itemize} - -Python is {\em extensible}: if you know how to program in C it is easy -to add a new built-in -function or -module to the interpreter, either to -perform critical operations at maximum speed, or to link Python -programs to libraries that may only be available in binary form (such -as a vendor-specific graphics library). Once you are really hooked, -you can link the Python interpreter into an application written in C -and use it as an extension or command language for that application. - -By the way, the language is named after the BBC show ``Monty -Python's Flying Circus'' and has nothing to do with nasty reptiles... - -\section{Where From Here} - -Now that you are all excited about Python, you'll want to examine it -in some more detail. Since the best way to learn a language is -using it, you are invited here to do so. - -In the next chapter, the mechanics of using the interpreter are -explained. This is rather mundane information, but essential for -trying out the examples shown later. - -The rest of the tutorial introduces various features of the Python -language and system though examples, beginning with simple -expressions, statements and data types, through functions and modules, -and finally touching upon advanced concepts like exceptions. - -When you're through with the turtorial (or just getting bored), you -should read the Library Reference, which gives complete (though terse) -reference material about built-in and standard types, functions and -modules that can save you a lot of time when writing Python programs. - - -\chapter{Using the Python Interpreter} - -\section{Invoking the Interpreter} - -The Python interpreter is usually installed as {\tt /usr/local/bin/python} -on those machines where it is available; putting {\tt /usr/local/bin} in -your {\UNIX} shell's search path makes it possible to start it by -typing the command - -\bcode\begin{verbatim} -python -\end{verbatim}\ecode -% -to the shell. Since the choice of the directory where the interpreter -lives is an installation option, other places are possible; check with -your local Python guru or system administrator. (E.g., {\tt -/usr/local/python} is a popular alternative location.) - -The interpreter operates somewhat like the {\UNIX} shell: when called -with standard input connected to a tty device, it reads and executes -commands interactively; when called with a file name argument or with -a file as standard input, it reads and executes a {\em script} from -that file. - -A third way of starting the interpreter is -``{\tt python -c command [arg] ...}'', which -executes the statement(s) in {\tt command}, analogous to the shell's -{\tt -c} option. Since Python statements often contain spaces or other -characters that are special to the shell, it is best to quote {\tt -command} in its entirety with double quotes. - -Note that there is a difference between ``{\tt python file}'' and -``{\tt python $<$file}''. In the latter case, input requests from the -program, such as calls to {\tt input()} and {\tt raw_input()}, are -satisfied from {\em file}. Since this file has already been read -until the end by the parser before the program starts executing, the -program will encounter EOF immediately. In the former case (which is -usually what you want) they are satisfied from whatever file or device -is connected to standard input of the Python interpreter. - -When a script file is used, it is sometimes useful to be able to run -the script and enter interactive mode afterwards. This can be done by -passing {\tt -i} before the script. (This does not work if the script -is read from standard input, for the same reason as explained in the -previous paragraph.) - -\subsection{Argument Passing} - -When known to the interpreter, the script name and additional -arguments thereafter are passed to the script in the variable {\tt -sys.argv}, which is a list of strings. Its length is at least one; -when no script and no arguments are given, {\tt sys.argv[0]} is an -empty string. When the script name is given as {\tt '-'} (meaning -standard input), {\tt sys.argv[0]} is set to {\tt '-'}. When {\tt -c -command} is used, {\tt sys.argv[0]} is set to {\tt '-c'}. Options -found after {\tt -c command} are not consumed by the Python -interpreter's option processing but left in {\tt sys.argv} for the -command to handle. - -\subsection{Interactive Mode} - -When commands are read from a tty, the interpreter is said to be in -{\em interactive\ mode}. In this mode it prompts for the next command -with the {\em primary\ prompt}, usually three greater-than signs ({\tt ->>>}); for continuation lines it prompts with the {\em secondary\ -prompt}, by default three dots ({\tt ...}). Typing an EOF (Control-D) -at the primary prompt causes the interpreter to exit with a zero exit -status. - -The interpreter prints a welcome message stating its version number -and a copyright notice before printing the first prompt, e.g.: - -\bcode\begin{verbatim} -python -Python 0.9.9 (Apr 2 1993). -Copyright 1990, 1991, 1992, 1993 Stichting Mathematisch Centrum, Amsterdam ->>> -\end{verbatim}\ecode - -\section{The Interpreter and its Environment} - -\subsection{Error Handling} - -When an error occurs, the interpreter prints an error -message and a stack trace. In interactive mode, it then returns to -the primary prompt; when input came from a file, it exits with a -nonzero exit status after printing -the stack trace. (Exceptions handled by an {\tt except} clause in a -{\tt try} statement are not errors in this context.) Some errors are -unconditionally fatal and cause an exit with a nonzero exit; this -applies to internal inconsistencies and some cases of running out of -memory. All error messages are written to the standard error stream; -normal output from the executed commands is written to standard -output. - -Typing the interrupt character (usually Control-C or DEL) to the -primary or secondary prompt cancels the input and returns to the -primary prompt.% -\footnote{ - A problem with the GNU Readline package may prevent this. -} -Typing an interrupt while a command is executing raises the {\tt -KeyboardInterrupt} exception, which may be handled by a {\tt try} -statement. - -\subsection{The Module Search Path} - -When a module named {\tt foo} is imported, the interpreter searches -for a file named {\tt foo.py} in the list of directories specified by -the environment variable {\tt PYTHONPATH}. It has the same syntax as -the {\UNIX} shell variable {\tt PATH}, i.e., a list of colon-separated -directory names. When {\tt PYTHONPATH} is not set, or when the file -is not found there, the search continues in an installation-dependent -default path, usually {\tt .:/usr/local/lib/python}. - -Actually, modules are searched in the list of directories given by the -variable {\tt sys.path} which is initialized from {\tt PYTHONPATH} and -the installation-dependent default. This allows Python programs that -know what they're doing to modify or replace the module search path. -See the section on Standard Modules later. - -\subsection{``Compiled'' Python files} - -As an important speed-up of the start-up time for short programs that -use a lot of standard modules, if a file called {\tt foo.pyc} exists -in the directory where {\tt foo.py} is found, this is assumed to -contain an already-``compiled'' version of the module {\tt foo}. The -modification time of the version of {\tt foo.py} used to create {\tt -foo.pyc} is recorded in {\tt foo.pyc}, and the file is ignored if -these don't match. - -Whenever {\tt foo.py} is successfully compiled, an attempt is made to -write the compiled version to {\tt foo.pyc}. It is not an error if -this attempt fails; if for any reason the file is not written -completely, the resulting {\tt foo.pyc} file will be recognized as -invalid and thus ignored later. - -\subsection{Executable Python scripts} - -On BSD'ish {\UNIX} systems, Python scripts can be made directly -executable, like shell scripts, by putting the line - -\bcode\begin{verbatim} -#! /usr/local/bin/python -\end{verbatim}\ecode -% -(assuming that's the name of the interpreter) at the beginning of the -script and giving the file an executable mode. The {\tt \#!} must be -the first two characters of the file. - -\subsection{The Interactive Startup File} - -When you use Python interactively, it is frequently handy to have some -standard commands executed every time the interpreter is started. You -can do this by setting an environment variable named {\tt -PYTHONSTARTUP} to the name of a file containing your start-up -commands. This is similar to the {\tt /profile} feature of the UNIX -shells. - -This file is only read in interactive sessions, not when Python reads -commands from a script, and not when {\tt /dev/tty} is given as the -explicit source of commands (which otherwise behaves like an -interactive session). It is executed in the same name space where -interactive commands are executed, so that objects that it defines or -imports can be used without qualification in the interactive session. -You can also change the prompts {\tt sys.ps1} and {\tt sys.ps2} in -this file. - -If you want to read an additional start-up file from the current -directory, you can program this in the global start-up file, e.g. -\verb\execfile('.pythonrc')\. If you want to use the startup file -in a script, you must write this explicitly in the script, e.g. -\verb\import os;\ \verb\execfile(os.environ['PYTHONSTARTUP'])\. - -\section{Interactive Input Editing and History Substitution} - -Some versions of the Python interpreter support editing of the current -input line and history substitution, similar to facilities found in -the Korn shell and the GNU Bash shell. This is implemented using the -{\em GNU\ Readline} library, which supports Emacs-style and vi-style -editing. This library has its own documentation which I won't -duplicate here; however, the basics are easily explained. - -Perhaps the quickest check to see whether command line editing is -supported is typing Control-P to the first Python prompt you get. If -it beeps, you have command line editing. If nothing appears to -happen, or if \verb/^P/ is echoed, you can skip the rest of this -section. - -\subsection{Line Editing} - -If supported, input line editing is active whenever the interpreter -prints a primary or secondary prompt. The current line can be edited -using the conventional Emacs control characters. The most important -of these are: C-A (Control-A) moves the cursor to the beginning of the -line, C-E to the end, C-B moves it one position to the left, C-F to -the right. Backspace erases the character to the left of the cursor, -C-D the character to its right. C-K kills (erases) the rest of the -line to the right of the cursor, C-Y yanks back the last killed -string. C-underscore undoes the last change you made; it can be -repeated for cumulative effect. - -\subsection{History Substitution} - -History substitution works as follows. All non-empty input lines -issued are saved in a history buffer, and when a new prompt is given -you are positioned on a new line at the bottom of this buffer. C-P -moves one line up (back) in the history buffer, C-N moves one down. -Any line in the history buffer can be edited; an asterisk appears in -front of the prompt to mark a line as modified. Pressing the Return -key passes the current line to the interpreter. C-R starts an -incremental reverse search; C-S starts a forward search. - -\subsection{Key Bindings} - -The key bindings and some other parameters of the Readline library can -be customized by placing commands in an initialization file called -{\tt \$HOME/.inputrc}. Key bindings have the form - -\bcode\begin{verbatim} -key-name: function-name -\end{verbatim}\ecode -% -or - -\bcode\begin{verbatim} -"string": function-name -\end{verbatim}\ecode -% -and options can be set with - -\bcode\begin{verbatim} -set option-name value -\end{verbatim}\ecode -% -For example: - -\bcode\begin{verbatim} -# I prefer vi-style editing: -set editing-mode vi -# Edit using a single line: -set horizontal-scroll-mode On -# Rebind some keys: -Meta-h: backward-kill-word -"\C-u": universal-argument -"\C-x\C-r": re-read-init-file -\end{verbatim}\ecode -% -Note that the default binding for TAB in Python is to insert a TAB -instead of Readline's default filename completion function. If you -insist, you can override this by putting - -\bcode\begin{verbatim} -TAB: complete -\end{verbatim}\ecode -% -in your {\tt \$HOME/.inputrc}. (Of course, this makes it hard to type -indented continuation lines...) - -\subsection{Commentary} - -This facility is an enormous step forward compared to previous -versions of the interpreter; however, some wishes are left: It would -be nice if the proper indentation were suggested on continuation lines -(the parser knows if an indent token is required next). The -completion mechanism might use the interpreter's symbol table. A -command to check (or even suggest) matching parentheses, quotes etc. -would also be useful. - - -\chapter{An Informal Introduction to Python} - -In the following examples, input and output are distinguished by the -presence or absence of prompts ({\tt >>>} and {\tt ...}): to repeat -the example, you must type everything after the prompt, when the -prompt appears; lines that do not begin with a prompt are output from -the interpreter.% -\footnote{ - I'd prefer to use different fonts to distinguish input - from output, but the amount of LaTeX hacking that would require - is currently beyond my ability. -} -Note that a secondary prompt on a line by itself in an example means -you must type a blank line; this is used to end a multi-line command. - -\section{Using Python as a Calculator} - -Let's try some simple Python commands. Start the interpreter and wait -for the primary prompt, {\tt >>>}. (It shouldn't take long.) - -\subsection{Numbers} - -The interpreter acts as a simple calculator: you can type an -expression at it and it will write the value. Expression syntax is -straightforward: the operators {\tt +}, {\tt -}, {\tt *} and {\tt /} -work just like in most other languages (e.g., Pascal or C); parentheses -can be used for grouping. For example: - -\bcode\begin{verbatim} ->>> # This is a comment ->>> 2+2 -4 ->>> ->>> (50-5*6)/4 -5 ->>> # Division truncates towards zero: ->>> 7/3 -2 ->>> -\end{verbatim}\ecode -% -Like in C, the equal sign ({\tt =}) is used to assign a value to a -variable. The value of an assignment is not written: - -\bcode\begin{verbatim} ->>> width = 20 ->>> height = 5*9 ->>> width * height -900 ->>> -\end{verbatim}\ecode -% -A value can be assigned to several variables simultaneously: - -\bcode\begin{verbatim} ->>> # Zero x, y and z ->>> x = y = z = 0 ->>> -\end{verbatim}\ecode -% -There is full support for floating point; operators with mixed type -operands convert the integer operand to floating point: - -\bcode\begin{verbatim} ->>> 4 * 2.5 / 3.3 -3.0303030303 ->>> 7.0 / 2 -3.5 ->>> -\end{verbatim}\ecode - -\subsection{Strings} - -Besides numbers, Python can also manipulate strings, enclosed in -single quotes: - -\bcode\begin{verbatim} ->>> 'foo bar' -'foo bar' ->>> 'doesn\'t' -'doesn\'t' ->>> -\end{verbatim}\ecode -% -Strings are written the same way as they are typed for input: inside -quotes and with quotes and other funny characters escaped by -backslashes, to show the precise value. (The {\tt print} statement, -described later, can be used to write strings without quotes or -escapes.) - -Strings can be concatenated (glued together) with the {\tt +} -operator, and repeated with {\tt *}: - -\bcode\begin{verbatim} ->>> word = 'Help' + 'A' ->>> word -'HelpA' ->>> '<' + word*5 + '>' -'' ->>> -\end{verbatim}\ecode -% -Strings can be subscripted (indexed); like in C, the first character of -a string has subscript (index) 0. - -There is no separate character type; a character is simply a string of -size one. Like in Icon, substrings can be specified with the {\em -slice} notation: two indices separated by a colon. - -\bcode\begin{verbatim} ->>> word[4] -'A' ->>> word[0:2] -'He' ->>> word[2:4] -'lp' ->>> -\end{verbatim}\ecode -% -Slice indices have useful defaults; an omitted first index defaults to -zero, an omitted second index defaults to the size of the string being -sliced. - -\bcode\begin{verbatim} ->>> word[:2] # The first two characters -'He' ->>> word[2:] # All but the first two characters -'lpA' ->>> -\end{verbatim}\ecode -% -Here's a useful invariant of slice operations: \verb\s[:i] + s[i:]\ -equals \verb\s\. - -\bcode\begin{verbatim} ->>> word[:2] + word[2:] -'HelpA' ->>> word[:3] + word[3:] -'HelpA' ->>> -\end{verbatim}\ecode -% -Degenerate slice indices are handled gracefully: an index that is too -large is replaced by the string size, an upper bound smaller than the -lower bound returns an empty string. - -\bcode\begin{verbatim} ->>> word[1:100] -'elpA' ->>> word[10:] -'' ->>> word[2:1] -'' ->>> -\end{verbatim}\ecode -% -Indices may be negative numbers, to start counting from the right. -For example: - -\bcode\begin{verbatim} ->>> word[-1] # The last character -'A' ->>> word[-2] # The last-but-one character -'p' ->>> word[-2:] # The last two characters -'pA' ->>> word[:-2] # All but the last two characters -'Hel' ->>> -\end{verbatim}\ecode -% -But note that -0 is really the same as 0, so it does not count from -the right! - -\bcode\begin{verbatim} ->>> word[-0] # (since -0 equals 0) -'H' ->>> -\end{verbatim}\ecode -% -Out-of-range negative slice indices are truncated, but don't try this -for single-element (non-slice) indices: - -\bcode\begin{verbatim} ->>> word[-100:] -'HelpA' ->>> word[-10] # error -Unhandled exception: IndexError: string index out of range ->>> -\end{verbatim}\ecode -% -The best way to remember how slices work is to think of the indices as -pointing {\em between} characters, with the left edge of the first -character numbered 0. Then the right edge of the last character of a -string of {\tt n} characters has index {\tt n}, for example: - -\bcode\begin{verbatim} - +---+---+---+---+---+ - | H | e | l | p | A | - +---+---+---+---+---+ - 0 1 2 3 4 5 --5 -4 -3 -2 -1 -\end{verbatim}\ecode -% -The first row of numbers gives the position of the indices 0...5 in -the string; the second row gives the corresponding negative indices. -The slice from \verb\i\ to \verb\j\ consists of all characters between -the edges labeled \verb\i\ and \verb\j\, respectively. - -For nonnegative indices, the length of a slice is the difference of -the indices, if both are within bounds, e.g., the length of -\verb\word[1:3]\ is 2. - -The built-in function {\tt len()} returns the length of a string: - -\bcode\begin{verbatim} ->>> s = 'supercalifragilisticexpialidocious' ->>> len(s) -34 ->>> -\end{verbatim}\ecode - -\subsection{Lists} - -Python knows a number of {\em compound} data types, used to group -together other values. The most versatile is the {\em list}, which -can be written as a list of comma-separated values (items) between -square brackets. List items need not all have the same type. - -\bcode\begin{verbatim} ->>> a = ['foo', 'bar', 100, 1234] ->>> a -['foo', 'bar', 100, 1234] ->>> -\end{verbatim}\ecode -% -Like string indices, list indices start at 0, and lists can be sliced, -concatenated and so on: - -\bcode\begin{verbatim} ->>> a[0] -'foo' ->>> a[3] -1234 ->>> a[-2] -100 ->>> a[1:-1] -['bar', 100] ->>> a[:2] + ['bletch', 2*2] -['foo', 'bar', 'bletch', 4] ->>> 3*a[:3] + ['Boe!'] -['foo', 'bar', 100, 'foo', 'bar', 100, 'foo', 'bar', 100, 'Boe!'] ->>> -\end{verbatim}\ecode -% -Unlike strings, which are {\em immutable}, it is possible to change -individual elements of a list: - -\bcode\begin{verbatim} ->>> a -['foo', 'bar', 100, 1234] ->>> a[2] = a[2] + 23 ->>> a -['foo', 'bar', 123, 1234] ->>> -\end{verbatim}\ecode -% -Assignment to slices is also possible, and this can even change the size -of the list: - -\bcode\begin{verbatim} ->>> # Replace some items: ->>> a[0:2] = [1, 12] ->>> a -[1, 12, 123, 1234] ->>> # Remove some: ->>> a[0:2] = [] ->>> a -[123, 1234] ->>> # Insert some: ->>> a[1:1] = ['bletch', 'xyzzy'] ->>> a -[123, 'bletch', 'xyzzy', 1234] ->>> a[:0] = a # Insert (a copy of) itself at the beginning ->>> a -[123, 'bletch', 'xyzzy', 1234, 123, 'bletch', 'xyzzy', 1234] ->>> -\end{verbatim}\ecode -% -The built-in function {\tt len()} also applies to lists: - -\bcode\begin{verbatim} ->>> len(a) -8 ->>> -\end{verbatim}\ecode -% -It is possible to nest lists (create lists containing other lists), -for example: - -\bcode\begin{verbatim} ->>> q = [2, 3] ->>> p = [1, q, 4] ->>> len(p) -3 ->>> p[1] -[2, 3] ->>> p[1][0] -2 ->>> p[1].append('xtra') # See section 5.1 ->>> p -[1, [2, 3, 'xtra'], 4] ->>> q -[2, 3, 'xtra'] ->>> -\end{verbatim}\ecode -% -Note that in the last example, {\tt p[1]} and {\tt q} really refer to -the same object! We'll come back to {\em object semantics} later. - -\section{First Steps Towards Programming} - -Of course, we can use Python for more complicated tasks than adding -two and two together. For instance, we can write an initial -subsequence of the {\em Fibonacci} series as follows: - -\bcode\begin{verbatim} ->>> # Fibonacci series: ->>> # the sum of two elements defines the next ->>> a, b = 0, 1 ->>> while b < 10: -... print b -... a, b = b, a+b -... -1 -1 -2 -3 -5 -8 ->>> -\end{verbatim}\ecode -% -This example introduces several new features. - -\begin{itemize} - -\item -The first line contains a {\em multiple assignment}: the variables -{\tt a} and {\tt b} simultaneously get the new values 0 and 1. On the -last line this is used again, demonstrating that the expressions on -the right-hand side are all evaluated first before any of the -assignments take place. - -\item -The {\tt while} loop executes as long as the condition (here: {\tt b < -100}) remains true. In Python, like in C, any non-zero integer value is -true; zero is false. The condition may also be a string or list value, -in fact any sequence; anything with a non-zero length is true, empty -sequences are false. The test used in the example is a simple -comparison. The standard comparison operators are written the same as -in C: {\tt <}, {\tt >}, {\tt ==}, {\tt <=}, {\tt >=} and {\tt !=}. - -\item -The {\em body} of the loop is {\em indented}: indentation is Python's -way of grouping statements. Python does not (yet!) provide an -intelligent input line editing facility, so you have to type a tab or -space(s) for each indented line. In practice you will prepare more -complicated input for Python with a text editor; most text editors have -an auto-indent facility. When a compound statement is entered -interactively, it must be followed by a blank line to indicate -completion (since the parser cannot guess when you have typed the last -line). - -\item -The {\tt print} statement writes the value of the expression(s) it is -given. It differs from just writing the expression you want to write -(as we did earlier in the calculator examples) in the way it handles -multiple expressions and strings. Strings are written without quotes, -and a space is inserted between items, so you can format things nicely, -like this: - -\bcode\begin{verbatim} ->>> i = 256*256 ->>> print 'The value of i is', i -The value of i is 65536 ->>> -\end{verbatim}\ecode -% -A trailing comma avoids the newline after the output: - -\bcode\begin{verbatim} ->>> a, b = 0, 1 ->>> while b < 1000: -... print b, -... a, b = b, a+b -... -1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 ->>> -\end{verbatim}\ecode -% -Note that the interpreter inserts a newline before it prints the next -prompt if the last line was not completed. - -\end{itemize} - - -\chapter{More Control Flow Tools} - -Besides the {\tt while} statement just introduced, Python knows the -usual control flow statements known from other languages, with some -twists. - -\section{If Statements} - -Perhaps the most well-known statement type is the {\tt if} statement. -For example: - -\bcode\begin{verbatim} ->>> if x < 0: -... x = 0 -... print 'Negative changed to zero' -... elif x == 0: -... print 'Zero' -... elif x == 1: -... print 'Single' -... else: -... print 'More' -... -\end{verbatim}\ecode -% -There can be zero or more {\tt elif} parts, and the {\tt else} part is -optional. The keyword `{\tt elif}' is short for `{\tt else if}', and is -useful to avoid excessive indentation. An {\tt if...elif...elif...} -sequence is a substitute for the {\em switch} or {\em case} statements -found in other languages. - -\section{For Statements} - -The {\tt for} statement in Python differs a bit from what you may be -used to in C or Pascal. Rather than always iterating over an -arithmetic progression of numbers (like in Pascal), or leaving the user -completely free in the iteration test and step (as C), Python's {\tt -for} statement iterates over the items of any sequence (e.g., a list -or a string), in the order that they appear in the sequence. For -example (no pun intended): - -\bcode\begin{verbatim} ->>> # Measure some strings: ->>> a = ['cat', 'window', 'defenestrate'] ->>> for x in a: -... print x, len(x) -... -cat 3 -window 6 -defenestrate 12 ->>> -\end{verbatim}\ecode -% -It is not safe to modify the sequence being iterated over in the loop -(this can only happen for mutable sequence types, i.e., lists). If -you need to modify the list you are iterating over, e.g., duplicate -selected items, you must iterate over a copy. The slice notation -makes this particularly convenient: - -\bcode\begin{verbatim} ->>> for x in a[:]: # make a slice copy of the entire list -... if len(x) > 6: a.insert(0, x) -... ->>> a -['defenestrate', 'cat', 'window', 'defenestrate'] ->>> -\end{verbatim}\ecode - -\section{The {\tt range()} Function} - -If you do need to iterate over a sequence of numbers, the built-in -function {\tt range()} comes in handy. It generates lists containing -arithmetic progressions, e.g.: - -\bcode\begin{verbatim} ->>> range(10) -[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ->>> -\end{verbatim}\ecode -% -The given end point is never part of the generated list; {\tt range(10)} -generates a list of 10 values, exactly the legal indices for items of a -sequence of length 10. It is possible to let the range start at another -number, or to specify a different increment (even negative): - -\bcode\begin{verbatim} ->>> range(5, 10) -[5, 6, 7, 8, 9] ->>> range(0, 10, 3) -[0, 3, 6, 9] ->>> range(-10, -100, -30) -[-10, -40, -70] ->>> -\end{verbatim}\ecode -% -To iterate over the indices of a sequence, combine {\tt range()} and -{\tt len()} as follows: - -\bcode\begin{verbatim} ->>> a = ['Mary', 'had', 'a', 'little', 'lamb'] ->>> for i in range(len(a)): -... print i, a[i] -... -0 Mary -1 had -2 a -3 little -4 lamb ->>> -\end{verbatim}\ecode - -\section{Break and Continue Statements, and Else Clauses on Loops} - -The {\tt break} statement, like in C, breaks out of the smallest -enclosing {\tt for} or {\tt while} loop. - -The {\tt continue} statement, also borrowed from C, continues with the -next iteration of the loop. - -Loop statements may have an {\tt else} clause; it is executed when the -loop terminates through exhaustion of the list (with {\tt for}) or when -the condition becomes false (with {\tt while}), but not when the loop is -terminated by a {\tt break} statement. This is exemplified by the -following loop, which searches for a list item of value 0: - -\bcode\begin{verbatim} ->>> for n in range(2, 10): -... for x in range(2, n): -... if n % x == 0: -... print n, 'equals', x, '*', n/x -... break -... else: -... print n, 'is a prime number' -... -2 is a prime number -3 is a prime number -4 equals 2 * 2 -5 is a prime number -6 equals 2 * 3 -7 is a prime number -8 equals 2 * 4 -9 equals 3 * 3 ->>> -\end{verbatim}\ecode - -\section{Pass Statements} - -The {\tt pass} statement does nothing. -It can be used when a statement is required syntactically but the -program requires no action. -For example: - -\bcode\begin{verbatim} ->>> while 1: -... pass # Busy-wait for keyboard interrupt -... -\end{verbatim}\ecode - -\section{Defining Functions} - -We can create a function that writes the Fibonacci series to an -arbitrary boundary: - -\bcode\begin{verbatim} ->>> def fib(n): # write Fibonacci series up to n -... a, b = 0, 1 -... while b <= n: -... print b, -... a, b = b, a+b -... ->>> # Now call the function we just defined: ->>> fib(2000) -1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 ->>> -\end{verbatim}\ecode -% -The keyword {\tt def} introduces a function {\em definition}. It must -be followed by the function name and the parenthesized list of formal -parameters. The statements that form the body of the function starts at -the next line, indented by a tab stop. - -The {\em execution} of a function introduces a new symbol table used -for the local variables of the function. More precisely, all variable -assignments in a function store the value in the local symbol table; -whereas - variable references first look in the local symbol table, then -in the global symbol table, and then in the table of built-in names. -Thus, -global variables cannot be directly assigned to from within a -function, although they may be referenced. - -The actual parameters (arguments) to a function call are introduced in -the local symbol table of the called function when it is called; thus, -arguments are passed using {\em call\ by\ value}.% -\footnote{ - Actually, {\em call by object reference} would be a better - description, since if a mutable object is passed, the caller - will see any changes the callee makes to it (e.g., items - inserted into a list). -} -When a function calls another function, a new local symbol table is -created for that call. - -A function definition introduces the function name in the -current -symbol table. The value -of the function name -has a type that is recognized by the interpreter as a user-defined -function. This value can be assigned to another name which can then -also be used as a function. This serves as a general renaming -mechanism: - -\bcode\begin{verbatim} ->>> fib - ->>> f = fib ->>> f(100) -1 1 2 3 5 8 13 21 34 55 89 ->>> -\end{verbatim}\ecode -% -You might object that {\tt fib} is not a function but a procedure. In -Python, like in C, procedures are just functions that don't return a -value. In fact, technically speaking, procedures do return a value, -albeit a rather boring one. This value is called {\tt None} (it's a -built-in name). Writing the value {\tt None} is normally suppressed by -the interpreter if it would be the only value written. You can see it -if you really want to: - -\bcode\begin{verbatim} ->>> print fib(0) -None ->>> -\end{verbatim}\ecode -% -It is simple to write a function that returns a list of the numbers of -the Fibonacci series, instead of printing it: - -\bcode\begin{verbatim} ->>> def fib2(n): # return Fibonacci series up to n -... result = [] -... a, b = 0, 1 -... while b <= n: -... result.append(b) # see below -... a, b = b, a+b -... return result -... ->>> f100 = fib2(100) # call it ->>> f100 # write the result -[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] ->>> -\end{verbatim}\ecode -% -This example, as usual, demonstrates some new Python features: - -\begin{itemize} - -\item -The {\tt return} statement returns with a value from a function. {\tt -return} without an expression argument is used to return from the middle -of a procedure (falling off the end also returns from a proceduce), in -which case the {\tt None} value is returned. - -\item -The statement {\tt result.append(b)} calls a {\em method} of the list -object {\tt result}. A method is a function that `belongs' to an -object and is named {\tt obj.methodname}, where {\tt obj} is some -object (this may be an expression), and {\tt methodname} is the name -of a method that is defined by the object's type. Different types -define different methods. Methods of different types may have the -same name without causing ambiguity. (It is possible to define your -own object types and methods, using {\em classes}. This is an -advanced feature that is not discussed in this tutorial.) -The method {\tt append} shown in the example, is defined for -list objects; it adds a new element at the end of the list. In this -example -it is equivalent to {\tt result = result + [b]}, but more efficient. - -\end{itemize} - - -\chapter{Odds and Ends} - -This chapter describes some things you've learned about already in -more detail, and adds some new things as well. - -\section{More on Lists} - -The list data type has some more methods. Here are all of the methods -of lists objects: - -\begin{description} - -\item[{\tt insert(i, x)}] -Insert an item at a given position. The first argument is the index of -the element before which to insert, so {\tt a.insert(0, x)} inserts at -the front of the list, and {\tt a.insert(len(a), x)} is equivalent to -{\tt a.append(x)}. - -\item[{\tt append(x)}] -Equivalent to {\tt a.insert(len(a), x)}. - -\item[{\tt index(x)}] -Return the index in the list of the first item whose value is {\tt x}. -It is an error if there is no such item. - -\item[{\tt remove(x)}] -Remove the first item from the list whose value is {\tt x}. -It is an error if there is no such item. - -\item[{\tt sort()}] -Sort the items of the list, in place. - -\item[{\tt reverse()}] -Reverse the elements of the list, in place. - -\end{description} - -An example that uses all list methods: - -\bcode\begin{verbatim} ->>> a = [66.6, 333, 333, 1, 1234.5] ->>> a.insert(2, -1) ->>> a.append(333) ->>> a -[66.6, 333, -1, 333, 1, 1234.5, 333] ->>> a.index(333) -1 ->>> a.remove(333) ->>> a -[66.6, -1, 333, 1, 1234.5, 333] ->>> a.reverse() ->>> a -[333, 1234.5, 1, 333, -1, 66.6] ->>> a.sort() ->>> a -[-1, 1, 66.6, 333, 333, 1234.5] ->>> -\end{verbatim}\ecode - -\section{The {\tt del} statement} - -There is a way to remove an item from a list given its index instead -of its value: the {\tt del} statement. This can also be used to -remove slices from a list (which we did earlier by assignment of an -empty list to the slice). For example: - -\bcode\begin{verbatim} ->>> a -[-1, 1, 66.6, 333, 333, 1234.5] ->>> del a[0] ->>> a -[1, 66.6, 333, 333, 1234.5] ->>> del a[2:4] ->>> a -[1, 66.6, 1234.5] ->>> -\end{verbatim}\ecode -% -{\tt del} can also be used to delete entire variables: - -\bcode\begin{verbatim} ->>> del a ->>> -\end{verbatim}\ecode -% -Referencing the name {\tt a} hereafter is an error (at least until -another value is assigned to it). We'll find other uses for {\tt del} -later. - -\section{Tuples and Sequences} - -We saw that lists and strings have many common properties, e.g., -indexinging and slicing operations. They are two examples of {\em -sequence} data types. Since Python is an evolving language, other -sequence data types may be added. There is also another standard -sequence data type: the {\em tuple}. - -A tuple consists of a number of values separated by commas, for -instance: - -\bcode\begin{verbatim} ->>> t = 12345, 54321, 'hello!' ->>> t[0] -12345 ->>> t -(12345, 54321, 'hello!') ->>> # Tuples may be nested: ->>> u = t, (1, 2, 3, 4, 5) ->>> u -((12345, 54321, 'hello!'), (1, 2, 3, 4, 5)) ->>> -\end{verbatim}\ecode -% -As you see, on output tuples are alway enclosed in parentheses, so -that nested tuples are interpreted correctly; they may be input with -or without surrounding parentheses, although often parentheses are -necessary anyway (if the tuple is part of a larger expression). - -Tuples have many uses, e.g., (x, y) coordinate pairs, employee records -from a database, etc. Tuples, like strings, are immutable: it is not -possible to assign to the individual items of a tuple (you can -simulate much of the same effect with slicing and concatenation, -though). - -A special problem is the construction of tuples containing 0 or 1 -items: the syntax has some extra quirks to accomodate these. Empty -tuples are constructed by an empty pair of parentheses; a tuple with -one item is constructed by following a value with a comma -(it is not sufficient to enclose a single value in parentheses). -Ugly, but effective. For example: - -\bcode\begin{verbatim} ->>> empty = () ->>> singleton = 'hello', # <-- note trailing comma ->>> len(empty) -0 ->>> len(singleton) -1 ->>> singleton -('hello',) ->>> -\end{verbatim}\ecode -% -The statement {\tt t = 12345, 54321, 'hello!'} is an example of {\em -tuple packing}: the values {\tt 12345}, {\tt 54321} and {\tt 'hello!'} -are packed together in a tuple. The reverse operation is also -possible, e.g.: - -\bcode\begin{verbatim} ->>> x, y, z = t ->>> -\end{verbatim}\ecode -% -This is called, appropriately enough, {\em tuple unpacking}. Tuple -unpacking requires that the list of variables on the left has the same -number of elements as the length of the tuple. Note that multiple -assignment is really just a combination of tuple packing and tuple -unpacking! - -Occasionally, the corresponding operation on lists is useful: {\em list -unpacking}. This is supported by enclosing the list of variables in -square brackets: - -\bcode\begin{verbatim} ->>> a = ['foo', 'bar', 100, 1234] ->>> [a1, a2, a3, a4] = a ->>> -\end{verbatim}\ecode - -\section{Dictionaries} - -Another useful data type built into Python is the {\em dictionary}. -Dictionaries are sometimes found in other languages as ``associative -memories'' or ``associative arrays''. Unlike sequences, which are -indexed by a range of numbers, dictionaries are indexed by {\em keys}, -which are strings. It is best to think of a dictionary as an unordered set of -{\em key:value} pairs, with the requirement that the keys are unique -(within one dictionary). -A pair of braces creates an empty dictionary: \verb/{}/. -Placing a comma-separated list of key:value pairs within the -braces adds initial key:value pairs to the dictionary; this is also the -way dictionaries are written on output. - -The main operations on a dictionary are storing a value with some key -and extracting the value given the key. It is also possible to delete -a key:value pair -with {\tt del}. -If you store using a key that is already in use, the old value -associated with that key is forgotten. It is an error to extract a -value using a non-existant key. - -The {\tt keys()} method of a dictionary object returns a list of all the -keys used in the dictionary, in random order (if you want it sorted, -just apply the {\tt sort()} method to the list of keys). To check -whether a single key is in the dictionary, use the \verb/has_key()/ -method of the dictionary. - -Here is a small example using a dictionary: - -\bcode\begin{verbatim} ->>> tel = {'jack': 4098, 'sape': 4139} ->>> tel['guido'] = 4127 ->>> tel -{'sape': 4139, 'guido': 4127, 'jack': 4098} ->>> tel['jack'] -4098 ->>> del tel['sape'] ->>> tel['irv'] = 4127 ->>> tel -{'guido': 4127, 'irv': 4127, 'jack': 4098} ->>> tel.keys() -['guido', 'irv', 'jack'] ->>> tel.has_key('guido') -1 ->>> -\end{verbatim}\ecode - -\section{More on Conditions} - -The conditions used in {\tt while} and {\tt if} statements above can -contain other operators besides comparisons. - -The comparison operators {\tt in} and {\tt not in} check whether a value -occurs (does not occur) in a sequence. The operators {\tt is} and {\tt -is not} compare whether two objects are really the same object; this -only matters for mutable objects like lists. All comparison operators -have the same priority, which is lower than that of all numerical -operators. - -Comparisons can be chained: e.g., {\tt a < b = c} tests whether {\tt a} -is less than {\tt b} and moreover {\tt b} equals {\tt c}. - -Comparisons may be combined by the Boolean operators {\tt and} and {\tt -or}, and the outcome of a comparison (or of any other Boolean -expression) may be negated with {\tt not}. These all have lower -priorities than comparison operators again; between them, {\tt not} has -the highest priority, and {\tt or} the lowest, so that -{\tt A and not B or C} is equivalent to {\tt (A and (not B)) or C}. Of -course, parentheses can be used to express the desired composition. - -The Boolean operators {\tt and} and {\tt or} are so-called {\em -shortcut} operators: their arguments are evaluated from left to right, -and evaluation stops as soon as the outcome is determined. E.g., if -{\tt A} and {\tt C} are true but {\tt B} is false, {\tt A and B and C} -does not evaluate the expression C. In general, the return value of a -shortcut operator, when used as a general value and not as a Boolean, is -the last evaluated argument. - -It is possible to assign the result of a comparison or other Boolean -expression to a variable, but you must enclose the entire Boolean -expression in parentheses. This is necessary because otherwise an -assignment like \verb/a = b = c/ would be ambiguous: does it assign the -value of {\tt c} to {\tt a} and {\tt b}, or does it compare {\tt b} to -{\tt c} and assign the outcome (0 or 1) to {\tt a}? As it is, the first -meaning is what you get, and to get the latter you have to write -\verb/a = (b = c)/. (In Python, unlike C, assignment cannot occur -inside expressions.) - -\section{Comparing Sequences and Other Types} - -Sequence objects may be compared to other objects with the same -sequence type. The comparison uses {\em lexicographical} ordering: -first the first two items are compared, and if they differ this -determines the outcome of the comparison; if they are equal, the next -two items are compared, and so on, until either sequence is exhausted. -If two items to be compared are themselves sequences of the same type, -the lexiographical comparison is carried out recursively. If all -items of two sequences compare equal, the sequences are considered -equal. If one sequence is an initial subsequence of the other, the -shorted sequence is the smaller one. Lexicographical ordering for -strings uses the ASCII ordering for individual characters. Some -examples of comparisons between sequences with the same types: - -\bcode\begin{verbatim} -(1, 2, 3) < (1, 2, 4) -[1, 2, 3] < [1, 2, 4] -'ABC' < 'C' < 'Pascal' < 'Python' -(1, 2, 3, 4) < (1, 2, 4) -(1, 2) < (1, 2, -1) -(1, 2, 3) = (1.0, 2.0, 3.0) -(1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4) -\end{verbatim}\ecode -% -Note that comparing objects of different types is legal. The outcome -is deterministic but arbitrary: the types are ordered by their name. -Thus, a list is always smaller than a string, a string is always -smaller than a tuple, etc. Mixed numeric types are compared according -to their numeric value, so 0 equals 0.0, etc.% -\footnote{ - The rules for comparing objects of different types should - not be relied upon; they may change in a future version of - the language. -} - - -\chapter{Modules} - -If you quit from the Python interpreter and enter it again, the -definitions you have made (functions and variables) are lost. -Therefore, if you want to write a somewhat longer program, you are -better off using a text editor to prepare the input for the interpreter -and run it with that file as input instead. This is known as creating a -{\em script}. As your program gets longer, you may want to split it -into several files for easier maintenance. You may also want to use a -handy function that you've written in several programs without copying -its definition into each program. - -To support this, Python has a way to put definitions in a file and use -them in a script or in an interactive instance of the interpreter. -Such a file is called a {\em module}; definitions from a module can be -{\em imported} into other modules or into the {\em main} module (the -collection of variables that you have access to in a script -executed at the top level -and in calculator mode). - -A module is a file containing Python definitions and statements. The -file name is the module name with the suffix {\tt .py} appended. For -instance, use your favorite text editor to create a file called {\tt -fibo.py} in the current directory with the following contents: - -\bcode\begin{verbatim} -# Fibonacci numbers module - -def fib(n): # write Fibonacci series up to n - a, b = 0, 1 - while b <= n: - print b, - a, b = b, a+b - -def fib2(n): # return Fibonacci series up to n - result = [] - a, b = 0, 1 - while b <= n: - result.append(b) - a, b = b, a+b - return result -\end{verbatim}\ecode -% -Now enter the Python interpreter and import this module with the -following command: - -\bcode\begin{verbatim} ->>> import fibo ->>> -\end{verbatim}\ecode -% -This does not enter the names of the functions defined in -{\tt fibo} -directly in the current symbol table; it only enters the module name -{\tt fibo} -there. -Using the module name you can access the functions: - -\bcode\begin{verbatim} ->>> fibo.fib(1000) -1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 ->>> fibo.fib2(100) -[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] ->>> -\end{verbatim}\ecode -% -If you intend to use a function often you can assign it to a local name: - -\bcode\begin{verbatim} ->>> fib = fibo.fib ->>> fib(500) -1 1 2 3 5 8 13 21 34 55 89 144 233 377 ->>> -\end{verbatim}\ecode - -\section{More on Modules} - -A module can contain executable statements as well as function -definitions. -These statements are intended to initialize the module. -They are executed only the -{\em first} -time the module is imported somewhere.% -\footnote{ - In fact function definitions are also `statements' that are - `executed'; the execution enters the function name in the - module's global symbol table. -} - -Each module has its own private symbol table, which is used as the -global symbol table by all functions defined in the module. -Thus, the author of a module can use global variables in the module -without worrying about accidental clashes with a user's global -variables. -On the other hand, if you know what you are doing you can touch a -module's global variables with the same notation used to refer to its -functions, -{\tt modname.itemname}. - -Modules can import other modules. -It is customary but not required to place all -{\tt import} -statements at the beginning of a module (or script, for that matter). -The imported module names are placed in the importing module's global -symbol table. - -There is a variant of the -{\tt import} -statement that imports names from a module directly into the importing -module's symbol table. -For example: - -\bcode\begin{verbatim} ->>> from fibo import fib, fib2 ->>> fib(500) -1 1 2 3 5 8 13 21 34 55 89 144 233 377 ->>> -\end{verbatim}\ecode -% -This does not introduce the module name from which the imports are taken -in the local symbol table (so in the example, {\tt fibo} is not -defined). - -There is even a variant to import all names that a module defines: - -\bcode\begin{verbatim} ->>> from fibo import * ->>> fib(500) -1 1 2 3 5 8 13 21 34 55 89 144 233 377 ->>> -\end{verbatim}\ecode -% -This imports all names except those beginning with an underscore -({\tt _}). - -\section{Standard Modules} - -Python comes with a library of standard modules, described in a separate -document (Python Library Reference). Some modules are built into the -interpreter; these provide access to operations that are not part of the -core of the language but are nevertheless built in, either for -efficiency or to provide access to operating system primitives such as -system calls. The set of such modules is a configuration option; e.g., -the {\tt amoeba} module is only provided on systems that somehow support -Amoeba primitives. One particular module deserves some attention: {\tt -sys}, which is built into every Python interpreter. The variables {\tt -sys.ps1} and {\tt sys.ps2} define the strings used as primary and -secondary prompts: - -\bcode\begin{verbatim} ->>> import sys ->>> sys.ps1 -'>>> ' ->>> sys.ps2 -'... ' ->>> sys.ps1 = 'C> ' -C> print 'Yuck!' -Yuck! -C> -\end{verbatim}\ecode -% -These two variables are only defined if the interpreter is in -interactive mode. - -The variable -{\tt sys.path} -is a list of strings that determine the interpreter's search path for -modules. -It is initialized to a default path taken from the environment variable -{\tt PYTHONPATH}, -or from a built-in default if -{\tt PYTHONPATH} -is not set. -You can modify it using standard list operations, e.g.: - -\bcode\begin{verbatim} ->>> import sys ->>> sys.path.append('/ufs/guido/lib/python') ->>> -\end{verbatim}\ecode - -\section{The {\tt dir()} function} - -The built-in function {\tt dir} is used to find out which names a module -defines. It returns a sorted list of strings: - -\bcode\begin{verbatim} ->>> import fibo, sys ->>> dir(fibo) -['fib', 'fib2'] ->>> dir(sys) -['argv', 'exit', 'modules', 'path', 'ps1', 'ps2', 'stderr', 'stdin', 'stdout'] ->>> -\end{verbatim}\ecode -% -Without arguments, {\tt dir()} lists the names you have defined currently: - -\bcode\begin{verbatim} ->>> a = [1, 2, 3, 4, 5] ->>> import fibo, sys ->>> fib = fibo.fib ->>> dir() -['a', 'fib', 'fibo', 'sys'] ->>> -\end{verbatim}\ecode -% -Note that it lists all types of names: variables, modules, functions, etc. - -{\tt dir()} does not list the names of built-in functions and variables. -If you want a list of those, they are defined in the standard module -{\tt __builtin__}: - -\bcode\begin{verbatim} ->>> import __builtin__ ->>> dir(__builtin__) -['AccessError', 'AttributeError', 'ConflictError', 'EOFError', 'IOError', 'I -mportError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'MemoryError', ' -NameError', 'None', 'OverflowError', 'RuntimeError', 'SyntaxError', 'SystemE -rror', 'SystemExit', 'TypeError', 'ValueError', 'ZeroDivisionError', 'abs', -'apply', 'chr', 'cmp', 'coerce', 'compile', 'dir', 'divmod', 'eval', 'execfi -le', 'float', 'getattr', 'hasattr', 'hash', 'hex', 'id', 'input', 'int', 'le -n', 'long', 'max', 'min', 'oct', 'open', 'ord', 'pow', 'range', 'raw_input', - 'reload', 'repr', 'round', 'setattr', 'str', 'type'] ->>> -\end{verbatim}\ecode - - -\chapter{Output Formatting} - -So far we've encountered two ways of writing values: {\em expression -statements} and the {\tt print} statement. (A third way is using the -{\tt write} method of file objects; the standard output file can be -referenced as {\tt sys.stdout}. See the Library Reference for more -information on this.) - -Often you'll want more control over the formatting of your output than -simply printing space-separated values. The key to nice formatting in -Python is to do all the string handling yourself; using string slicing -and concatenation operations you can create any lay-out you can imagine. -The standard module {\tt string} contains some useful operations for -padding strings to a given column width; these will be discussed shortly. - -One question remains, of course: how do you convert values to strings? -Luckily, Python has a way to convert any value to a string: just write -the value between reverse quotes (\verb/``/). Some examples: - -\bcode\begin{verbatim} ->>> x = 10 * 3.14 ->>> y = 200*200 ->>> s = 'The value of x is ' + `x` + ', and y is ' + `y` + '...' ->>> print s -The value of x is 31.4, and y is 40000... ->>> # Reverse quotes work on other types besides numbers: ->>> p = [x, y] ->>> ps = `p` ->>> ps -'[31.4, 40000]' ->>> # Converting a string adds string quotes and backslashes: ->>> hello = 'hello, world\n' ->>> hellos = `hello` ->>> print hellos -'hello, world\012' ->>> # The argument of reverse quotes may be a tuple: ->>> `x, y, ('foo', 'bar')` -'(31.4, 40000, (\'foo\', \'bar\'))' ->>> -\end{verbatim}\ecode -% -Here is how you write a table of squares and cubes: - -\bcode\begin{verbatim} ->>> import string ->>> for x in range(1, 11): -... print string.rjust(`x`, 2), string.rjust(`x*x`, 3), -... # Note trailing comma on previous line -... print string.rjust(`x*x*x`, 4) -... - 1 1 1 - 2 4 8 - 3 9 27 - 4 16 64 - 5 25 125 - 6 36 216 - 7 49 343 - 8 64 512 - 9 81 729 -10 100 1000 ->>> -\end{verbatim}\ecode -% -(Note that one space between each column was added by the way {\tt print} -works: it always adds spaces between its arguments.) - -This example demonstrates the function {\tt string.rjust()}, which -right-justifies a string in a field of a given width by padding it with -spaces on the left. There are similar functions {\tt string.ljust()} -and {\tt string.center()}. These functions do not write anything, they -just return a new string. If the input string is too long, they don't -truncate it, but return it unchanged; this will mess up your column -lay-out but that's usually better than the alternative, which would be -lying about a value. (If you really want truncation you can always add -a slice operation, as in {\tt string.ljust(x,~n)[0:n]}.) - -There is another function, {\tt string.zfill}, which pads a numeric -string on the left with zeros. It understands about plus and minus -signs:% -\footnote{ - Better facilities for formatting floating point numbers are - lacking at this moment. -} - -\bcode\begin{verbatim} ->>> string.zfill('12', 5) -'00012' ->>> string.zfill('-3.14', 7) -'-003.14' ->>> string.zfill('3.14159265359', 5) -'3.14159265359' ->>> -\end{verbatim}\ecode - - -\chapter{Errors and Exceptions} - -Until now error messages haven't been more than mentioned, but if you -have tried out the examples you have probably seen some. There are -(at least) two distinguishable kinds of errors: {\em syntax\ errors} -and {\em exceptions}. - -\section{Syntax Errors} - -Syntax errors, also known as parsing errors, are perhaps the most common -kind of complaint you get while you are still learning Python: - -\bcode\begin{verbatim} ->>> while 1 print 'Hello world' -Parsing error: file , line 1: -while 1 print 'Hello world' - ^ -Unhandled exception: run-time error: syntax error ->>> -\end{verbatim}\ecode -% -The parser repeats the offending line and displays a little `arrow' -pointing at the earliest point in the line where the error was detected. -The error is caused by (or at least detected at) the token -{\em preceding} -the arrow: in the example, the error is detected at the keyword -{\tt print}, since a colon ({\tt :}) is missing before it. -File name and line number are printed so you know where to look in case -the input came from a script. - -\section{Exceptions} - -Even if a statement or expression is syntactically correct, it may -cause an error when an attempt is made to execute it. -Errors detected during execution are called {\em exceptions} and are -not unconditionally fatal: you will soon learn how to handle them in -Python programs. Most exceptions are not handled by programs, -however, and result in error messages as shown here: - -\bcode\small\begin{verbatim} ->>> 10 * (1/0) -Traceback (innermost last): - File "", line 1 -ZeroDivisionError: integer division or modulo ->>> 4 + foo*3 -Stack backtrace (innermost last): - File "", line 1 -NameError: foo ->>> '2' + 2 -Stack backtrace (innermost last): - File "", line 1 -TypeError: illegal argument type for built-in operation ->>> -\end{verbatim}\ecode -% -The last line of the error message indicates what happened. -Exceptions come in different types, and the type is printed as part of -the message: the types in the example are -{\tt ZeroDivisionError}, -{\tt NameError} -and -{\tt TypeError}. -The string printed as the exception type is the name of the built-in -name for the exception that occurred. This is true for all built-in -exceptions, but need not be true for user-defined exceptions (although -it is a useful convention). -Standard exception names are built-in identifiers (not reserved -keywords). - -The rest of the line is a detail whose interpretation depends on the -exception type; its meaning is dependent on the exception type. - -The preceding part of the error message shows the context where the -exception happened, in the form of a stack backtrace. -In general it contains a stack backtrace listing source lines; however, -it will not display lines read from standard input. - -The Python library reference manual lists the built-in exceptions and -their meanings. - -\section{Handling Exceptions} - -It is possible to write programs that handle selected exceptions. -Look at the following example, which prints a table of inverses of -some floating point numbers: - -\bcode\begin{verbatim} ->>> numbers = [0.3333, 2.5, 0, 10] ->>> for x in numbers: -... print x, -... try: -... print 1.0 / x -... except ZeroDivisionError: -... print '*** has no inverse ***' -... -0.3333 3.00030003 -2.5 0.4 -0 *** has no inverse *** -10 0.1 ->>> -\end{verbatim}\ecode -% -The {\tt try} statement works as follows. -\begin{itemize} -\item -First, the -{\em try\ clause} -(the statement(s) between the {\tt try} and {\tt except} keywords) is -executed. -\item -If no exception occurs, the -{\em except\ clause} -is skipped and execution of the {\tt try} statement is finished. -\item -If an exception occurs during execution of the try clause, -the rest of the clause is skipped. Then if -its type matches the exception named after the {\tt except} keyword, -the rest of the try clause is skipped, the except clause is executed, -and then execution continues after the {\tt try} statement. -\item -If an exception occurs which does not match the exception named in the -except clause, it is passed on to outer try statements; if no handler is -found, it is an -{\em unhandled\ exception} -and execution stops with a message as shown above. -\end{itemize} -A {\tt try} statement may have more than one except clause, to specify -handlers for different exceptions. -At most one handler will be executed. -Handlers only handle exceptions that occur in the corresponding try -clause, not in other handlers of the same {\tt try} statement. -An except clause may name multiple exceptions as a parenthesized list, -e.g.: - -\bcode\begin{verbatim} -... except (RuntimeError, TypeError, NameError): -... pass -\end{verbatim}\ecode -% -The last except clause may omit the exception name(s), to serve as a -wildcard. -Use this with extreme caution, since it is easy to mask a real -programming error in this way! - -When an exception occurs, it may have an associated value, also known as -the exceptions's -{\em argument}. -The presence and type of the argument depend on the exception type. -For exception types which have an argument, the except clause may -specify a variable after the exception name (or list) to receive the -argument's value, as follows: - -\bcode\begin{verbatim} ->>> try: -... foo() -... except NameError, x: -... print 'name', x, 'undefined' -... -name foo undefined ->>> -\end{verbatim}\ecode -% -If an exception has an argument, it is printed as the last part -(`detail') of the message for unhandled exceptions. - -Exception handlers don't just handle exceptions if they occur -immediately in the try clause, but also if they occur inside functions -that are called (even indirectly) in the try clause. -For example: - -\bcode\begin{verbatim} ->>> def this_fails(): -... x = 1/0 -... ->>> try: -... this_fails() -... except ZeroDivisionError, detail: -... print 'Handling run-time error:', detail -... -Handling run-time error: integer division or modulo ->>> -\end{verbatim}\ecode - -\section{Raising Exceptions} - -The {\tt raise} statement allows the programmer to force a specified -exception to occur. -For example: - -\bcode\begin{verbatim} ->>> raise NameError, 'HiThere' -Stack backtrace (innermost last): - File "", line 1 -NameError: HiThere ->>> -\end{verbatim}\ecode -% -The first argument to {\tt raise} names the exception to be raised. -The optional second argument specifies the exception's argument. - -\section{User-defined Exceptions} - -Programs may name their own exceptions by assigning a string to a -variable. -For example: - -\bcode\begin{verbatim} ->>> my_exc = 'my_exc' ->>> try: -... raise my_exc, 2*2 -... except my_exc, val: -... print 'My exception occurred, value:', val -... -My exception occured, value: 4 ->>> raise my_exc, 1 -Stack backtrace (innermost last): - File "", line 7 -my_exc: 1 ->>> -\end{verbatim}\ecode -% -Many standard modules use this to report errors that may occur in -functions they define. - -\section{Defining Clean-up Actions} - -The {\tt try} statement has another optional clause which is intended to -define clean-up actions that must be executed under all circumstances. -For example: - -\bcode\begin{verbatim} ->>> try: -... raise KeyboardInterrupt -... finally: -... print 'Goodbye, world!' -... -Goodbye, world! -Stack backtrace (innermost last): - File "", line 2 -KeyboardInterrupt ->>> -\end{verbatim}\ecode -% -A {\tt finally} clause is executed whether or not an exception has -occurred in the {\tt try} clause. When an exception has occurred, it -is re-raised after the {\tt finally} clauses is executed. The -{\tt finally} clause is also executed ``on the way out'' when the -{\tt try} statement is left via a {\tt break} or {\tt return} -statement. - -A {\tt try} statement must either have one or more {\tt except} -clauses or one {\tt finally} clause, but not both. - - -\chapter{Classes} - -Python's class mechanism adds classes to the language with a minimum -of new syntax and semantics. It is a mixture of the class mechanisms -found in C++ and Modula-3. As is true for modules, classes in Python -do not put an absolute barrier between definition and user, but rather -rely on the politeness of the user not to ``break into the -definition.'' The most important features of classes are retained -with full power, however: the class inheritance mechanism allows -multiple base classes, a derived class can override any methods of its -base class(es), a method can call the method of a base class with the -same name. Objects can contain an arbitrary amount of private data. - -In C++ terminology, all class members (including the data members) are -{\em public}, and all member functions are {\em virtual}. There are -no special constructors or desctructors. As in Modula-3, there are no -shorthands for referencing the object's members from its methods: the -method function is declared with an explicit first argument -representing the object, which is provided implicitly by the call. As -in Smalltalk, classes themselves are objects, albeit in the wider -sense of the word: in Python, all data types are objects. This -provides semantics for importing and renaming. But, just like in C++ -or Modula-3, built-in types cannot be used as base classes for -extension by the user. Also, like in Modula-3 but unlike in C++, the -built-in operators with special syntax (arithmetic operators, -subscriptong etc.) cannot be redefined for class members. - - -\section{A word about terminology} - -Lacking universally accepted terminology to talk about classes, I'll -make occasional use of Smalltalk and C++ terms. (I'd use Modula-3 -terms, since its object-oriented semantics are closer to those of -Python than C++, but I expect that few readers have heard of it...) - -I also have to warn you that there's a terminological pitfall for -object-oriented readers: the word ``object'' in Python does not -necessarily mean a class instance. Like C++ and Modula-3, and unlike -Smalltalk, not all types in Python are classes: the basic built-in -types like integers and lists aren't, and even somewhat more exotic -types like files aren't. However, {\em all} Python types share a little -bit of common semantics that is best described by using the word -object. - -Objects have individuality, and multiple names (in multiple scopes) -can be bound to the same object. This is known as aliasing in other -languages. This is usually not appreciated on a first glance at -Python, and can be safely ignored when dealing with immutable basic -types (numbers, strings, tuples). However, aliasing has an -(intended!) effect on the semantics of Python code involving mutable -objects such as lists, dictionaries, and most types representing -entities outside the program (files, windows, etc.). This is usually -used to the benefit of the program, since aliases behave like pointers -in some respects. For example, passing an object is cheap since only -a pointer is passed by the implementation; and if a function modifies -an object passed as an argument, the caller will see the change --- this -obviates the need for two different argument passing mechanisms as in -Pascal. - - -\section{Python scopes and name spaces} - -Before introducing classes, I first have to tell you something about -Python's scope rules. Class definitions play some neat tricks with -name spaces, and you need to know how scopes and name spaces work to -fully understand what's going on. Incidentally, knowledge about this -subject is useful for any advanced Python programmer. - -Let's begin with some definitions. - -A {\em name space} is a mapping from names to objects. Most name -spaces are currently implemented as Python dictionaries, but that's -normally not noticeable in any way (except for performance), and it -may change in the future. Examples of name spaces are: the set of -built-in names (functions such as \verb\abs()\, and built-in exception -names); the global names in a module; and the local names in a -function invocation. In a sense the set of attributes of an object -also form a name space. The important things to know about name -spaces is that there is absolutely no relation between names in -different name spaces; for instance, two different modules may both -define a function ``maximize'' without confusion --- users of the -modules must prefix it with the module name. - -By the way, I use the word {\em attribute} for any name following a -dot --- for example, in the expression \verb\z.real\, \verb\real\ is -an attribute of the object \verb\z\. Strictly speaking, references to -names in modules are attribute references: in the expression -\verb\modname.funcname\, \verb\modname\ is a module object and -\verb\funcname\ is an attribute of it. In this case there happens to -be a straightforward mapping between the module's attributes and the -global names defined in the module: they share the same name space!% -\footnote{ - Except for one thing. Module objects have a secret read-only - attribute called {\tt __dict__} which returns the dictionary - used to implement the module's name space; the name - {\tt __dict__} is an attribute but not a global name. - Obviously, using this violates the abstraction of name space - implementation, and should be restricted to things like - post-mortem debuggers... -} - -Attributes may be read-only or writable. In the latter case, -assignment to attributes is possible. Module attributes are writable: -you can write \verb\modname.the_answer = 42\. Writable attributes may -also be deleted with the del statement, e.g. -\verb\del modname.the_answer\. - -Name spaces are created at different moments and have different -lifetimes. The name space containing the built-in names is created -when the Python interpreter starts up, and is never deleted. The -global name space for a module is created when the module definition -is read in; normally, module name spaces also last until the -interpreter quits. The statements executed by the top-level -invocation of the interpreter, either read from a script file or -interactively, are considered part of a module called \verb\__main__\, -so they have their own global name space. (The built-in names -actually also live in a module; this is called \verb\__builtin__\.) - -The local name space for a function is created when the function is -called, and deleted when the function returns or raises an exception -that is not handled within the function. (Actually, forgetting would -be a better way to describe what actually happens.) Of course, -recursive invocations each have their own local name space. - -A {\em scope} is a textual region of a Python program where a name space -is directly accessible. ``Directly accessible'' here means that an -unqualified reference to a name attempts to find the name in the name -space. - -Although scopes are determined statically, they are used dynamically. -At any time during execution, exactly three nested scopes are in use -(i.e., exactly three name spaces are directly accessible): the -innermost scope, which is searched first, contains the local names, -the middle scope, searched next, contains the current module's global -names, and the outermost scope (searched last) is the name space -containing built-in names. - -Usually, the local scope references the local names of the (textually) -current function. Outside functions, the the local scope references -the same name space as the global scope: the module's name space. -Class definitions place yet another name space in the local scope. - -It is important to realize that scopes are determined textually: the -global scope of a function defined in a module is that module's name -space, no matter from where or by what alias the function is called. -On the other hand, the actual search for names is done dynamically, at -run time --- however, the the language definition is evolving towards -static name resolution, at ``compile'' time, so don't rely on dynamic -name resolution! (In fact, local variables are already determined -statically.) - -A special quirk of Python is that assignments always go into the -innermost scope. Assignments do not copy data --- they just -bind names to objects. The same is true for deletions: the statement -\verb\del x\ removes the binding of x from the name space referenced by the -local scope. In fact, all operations that introduce new names use the -local scope: in particular, import statements and function definitions -bind the module or function name in the local scope. (The -\verb\global\ statement can be used to indicate that particular -variables live in the global scope.) - - -\section{A first look at classes} - -Classes introduce a little bit of new syntax, three new object types, -and some new semantics. - - -\subsection{Class definition syntax} - -The simplest form of class definition looks like this: - -\begin{verbatim} - class ClassName: - - . - . - . - -\end{verbatim} - -Class definitions, like function definitions (\verb\def\ statements) -must be executed before they have any effect. (You could conceivably -place a class definition in a branch of an \verb\if\ statement, or -inside a function.) - -In practice, the statements inside a class definition will usually be -function definitions, but other statements are allowed, and sometimes -useful --- we'll come back to this later. The function definitions -inside a class normally have a peculiar form of argument list, -dictated by the calling conventions for methods --- again, this is -explained later. - -When a class definition is entered, a new name space is created, and -used as the local scope --- thus, all assignments to local variables -go into this new name space. In particular, function definitions bind -the name of the new function here. - -When a class definition is left normally (via the end), a {\em class -object} is created. This is basically a wrapper around the contents -of the name space created by the class definition; we'll learn more -about class objects in the next section. The original local scope -(the one in effect just before the class definitions was entered) is -reinstated, and the class object is bound here to class name given in -the class definition header (ClassName in the example). - - -\subsection{Class objects} - -Class objects support two kinds of operations: attribute references -and instantiation. - -{\em Attribute references} use the standard syntax used for all -attribute references in Python: \verb\obj.name\. Valid attribute -names are all the names that were in the class's name space when the -class object was created. So, if the class definition looked like -this: - -\begin{verbatim} - class MyClass: - i = 12345 - def f(x): - return 'hello world' -\end{verbatim} - -then \verb\MyClass.i\ and \verb\MyClass.f\ are valid attribute -references, returning an integer and a function object, respectively. -Class attributes can also be assigned to, so you can change the -value of \verb\MyClass.i\ by assignment. - -Class {\em instantiation} uses function notation. Just pretend that -the class object is a parameterless function that returns a new -instance of the class. For example, (assuming the above class): - -\begin{verbatim} - x = MyClass() -\end{verbatim} - -creates a new {\em instance} of the class and assigns this object to -the local variable \verb\x\. - - -\subsection{Instance objects} - -Now what can we do with instance objects? The only operations -understood by instance objects are attribute references. There are -two kinds of valid attribute names. - -The first I'll call {\em data attributes}. These correspond to -``instance variables'' in Smalltalk, and to ``data members'' in C++. -Data attributes need not be declared; like local variables, they -spring into existence when they are first assigned to. For example, -if \verb\x\ in the instance of \verb\MyClass\ created above, the -following piece of code will print the value 16, without leaving a -trace: - -\begin{verbatim} - x.counter = 1 - while x.counter < 10: - x.counter = x.counter * 2 - print x.counter - del x.counter -\end{verbatim} - -The second kind of attribute references understood by instance objects -are {\em methods}. A method is a function that ``belongs to'' an -object. (In Python, the term method is not unique to class instances: -other object types can have methods as well, e.g., list objects have -methods called append, insert, remove, sort, and so on. However, -below, we'll use the term method exclusively to mean methods of class -instance objects, unless explicitly stated otherwise.) - -Valid method names of an instance object depend on its class. By -definition, all attributes of a class that are (user-defined) function -objects define corresponding methods of its instances. So in our -example, \verb\x.f\ is a valid method reference, since -\verb\MyClass.f\ is a function, but \verb\x.i\ is not, since -\verb\MyClass.i\ is not. But \verb\x.f\ is not the -same thing as \verb\MyClass.f\ --- it is a {\em method object}, not a -function object. - - -\subsection{Method objects} - -Usually, a method is called immediately, e.g.: - -\begin{verbatim} - x.f() -\end{verbatim} - -In our example, this will return the string \verb\'hello world'\. -However, it is not necessary to call a method right away: \verb\x.f\ -is a method object, and can be stored away and called at a later -moment, for example: - -\begin{verbatim} - xf = x.f - while 1: - print xf() -\end{verbatim} - -will continue to print \verb\hello world\ until the end of time. - -What exactly happens when a method is called? You may have noticed -that \verb\x.f()\ was called without an argument above, even though -the function definition for \verb\f\ specified an argument. What -happened to the argument? Surely Python raises an exception when a -function that requires an argument is called without any --- even if -the argument isn't actually used... - -Actually, you may have guessed the answer: the special thing about -methods is that the object is passed as the first argument of the -function. In our example, the call \verb\x.f()\ is exactly equivalent -to \verb\MyClass.f(x)\. In general, calling a method with a list of -{\em n} arguments is equivalent to calling the corresponding function -with an argument list that is created by inserting the method's object -before the first argument. - -If you still don't understand how methods work, a look at the -implementation can perhaps clarify matters. When an instance -attribute is referenced that isn't a data attribute, its class is -searched. If the name denotes a valid class attribute that is a -function object, a method object is created by packing (pointers to) -the instance object and the function object just found together in an -abstract object: this is the method object. When the method object is -called with an argument list, it is unpacked again, a new argument -list is constructed from the instance object and the original argument -list, and the function object is called with this new argument list. - - -\section{Random remarks} - - -[These should perhaps be placed more carefully...] - - -Data attributes override method attributes with the same name; to -avoid accidental name conflicts, which may cause hard-to-find bugs in -large programs, it is wise to use some kind of convention that -minimizes the chance of conflicts, e.g., capitalize method names, -prefix data attribute names with a small unique string (perhaps just -an undescore), or use verbs for methods and nouns for data attributes. - - -Data attributes may be referenced by methods as well as by ordinary -users (``clients'') of an object. In other words, classes are not -usable to implement pure abstract data types. In fact, nothing in -Python makes it possible to enforce data hiding --- it is all based -upon convention. (On the other hand, the Python implementation, -written in C, can completely hide implementation details and control -access to an object if necessary; this can be used by extensions to -Python written in C.) - - -Clients should use data attributes with care --- clients may mess up -invariants maintained by the methods by stamping on their data -attributes. Note that clients may add data attributes of their own to -an instance object without affecting the validity of the methods, as -long as name conflicts are avoided --- again, a naming convention can -save a lot of headaches here. - - -There is no shorthand for referencing data attributes (or other -methods!) from within methods. I find that this actually increases -the readability of methods: there is no chance of confusing local -variables and instance variables when glancing through a method. - - -Conventionally, the first argument of methods is often called -\verb\self\. This is nothing more than a convention: the name -\verb\self\ has absolutely no special meaning to Python. (Note, -however, that by not following the convention your code may be less -readable by other Python programmers, and it is also conceivable that -a {\em class browser} program be written which relies upon such a -convention.) - - -Any function object that is a class attribute defines a method for -instances of that class. It is not necessary that the function -definition is textually enclosed in the class definition: assigning a -function object to a local variable in the class is also ok. For -example: - -\begin{verbatim} - # Function defined outside the class - def f1(self, x, y): - return min(x, x+y) - - class C: - f = f1 - def g(self): - return 'hello world' - h = g -\end{verbatim} - -Now \verb\f\, \verb\g\ and \verb\h\ are all attributes of class -\verb\C\ that refer to function objects, and consequently they are all -methods of instances of \verb\C\ --- \verb\h\ being exactly equivalent -to \verb\g\. Note that this practice usually only serves to confuse -the reader of a program. - - -Methods may call other methods by using method attributes of the -\verb\self\ argument, e.g.: - -\begin{verbatim} - class Bag: - def empty(self): - self.data = [] - def add(self, x): - self.data.append(x) - def addtwice(self, x): - self.add(x) - self.add(x) -\end{verbatim} - - -The instantiation operation (``calling'' a class object) creates an -empty object. Many classes like to create objects in a known initial -state. There is no special syntax to enforce this, but a convention -works almost as well: add a method named \verb\init\ to the class, -which initializes the instance (by assigning to some important data -attributes) and returns the instance itself. For example, class -\verb\Bag\ above could have the following method: - -\begin{verbatim} - def init(self): - self.empty() - return self -\end{verbatim} - -The client can then create and initialize an instance in one -statement, as follows: - -\begin{verbatim} - x = Bag().init() -\end{verbatim} - -Of course, the \verb\init\ method may have arguments for greater -flexibility. - -Warning: a common mistake is to forget the \verb\return self\ at the -end of an init method! - - -Methods may reference global names in the same way as ordinary -functions. The global scope associated with a method is the module -containing the class definition. (The class itself is never used as a -global scope!) While one rarely encounters a good reason for using -global data in a method, there are many legitimate uses of the global -scope: for one thing, functions and modules imported into the global -scope can be used by methods, as well as functions and classes defined -in it. Usually, the class containing the method is itself defined in -this global scope, and in the next section we'll find some good -reasons why a method would want to reference its own class! - - -\section{Inheritance} - -Of course, a language feature would not be worthy of the name ``class'' -without supporting inheritance. The syntax for a derived class -definition looks as follows: - -\begin{verbatim} - class DerivedClassName(BaseClassName): - - . - . - . - -\end{verbatim} - -The name \verb\BaseClassName\ must be defined in a scope containing -the derived class definition. Instead of a base class name, an -expression is also allowed. This is useful when the base class is -defined in another module, e.g., - -\begin{verbatim} - class DerivedClassName(modname.BaseClassName): -\end{verbatim} - -Execution of a derived class definition proceeds the same as for a -base class. When the class object is constructed, the base class is -remembered. This is used for resolving attribute references: if a -requested attribute is not found in the class, it is searched in the -base class. This rule is applied recursively if the base class itself -is derived from some other class. - -There's nothing special about instantiation of derived classes: -\verb\DerivedClassName()\ creates a new instance of the class. Method -references are resolved as follows: the corresponding class attribute -is searched, descending down the chain of base classes if necessary, -and the method reference is valid if this yields a function object. - -Derived classes may override methods of their base classes. Because -methods have no special privileges when calling other methods of the -same object, a method of a base class that calls another method -defined in the same base class, may in fact end up calling a method of -a derived class that overrides it. (For C++ programmers: all methods -in Python are ``virtual functions''.) - -An overriding method in a derived class may in fact want to extend -rather than simply replace the base class method of the same name. -There is a simple way to call the base class method directly: just -call \verb\BaseClassName.methodname(self, arguments)\. This is -occasionally useful to clients as well. (Note that this only works if -the base class is defined or imported directly in the global scope.) - - -\subsection{Multiple inheritance} - -Poython supports a limited form of multiple inheritance as well. A -class definition with multiple base classes looks as follows: - -\begin{verbatim} - class DerivedClassName(Base1, Base2, Base3): - - . - . - . - -\end{verbatim} - -The only rule necessary to explain the semantics is the resolution -rule used for class attribute references. This is depth-first, -left-to-right. Thus, if an attribute is not found in -\verb\DerivedClassName\, it is searched in \verb\Base1\, then -(recursively) in the base classes of \verb\Base1\, and only if it is -not found there, it is searched in \verb\Base2\, and so on. - -(To some people breadth first---searching \verb\Base2\ and -\verb\Base3\ before the base classes of \verb\Base1\---looks more -natural. However, this would require you to know whether a particular -attribute of \verb\Base1\ is actually defined in \verb\Base1\ or in -one of its base classes before you can figure out the consequences of -a name conflict with an attribute of \verb\Base2\. The depth-first -rule makes no differences between direct and inherited attributes of -\verb\Base1\.) - -It is clear that indiscriminate use of multiple inheritance is a -maintenance nightmare, given the reliance in Python on conventions to -avoid accidental name conflicts. A well-known problem with multiple -inheritance is a class derived from two classes that happen to have a -common base class. While it is easy enough to figure out what happens -in this case (the instance will have a single copy of ``instance -variables'' or data attributes used by the common base class), it is -not clear that these semantics are in any way useful. - - -\section{Odds and ends} - -Sometimes it is useful to have a data type similar to the Pascal -``record'' or C ``struct'', bundling together a couple of named data -items. An empty class definition will do nicely, e.g.: - -\begin{verbatim} - class Employee: - pass - - john = Employee() # Create an empty employee record - - # Fill the fields of the record - john.name = 'John Doe' - john.dept = 'computer lab' - john.salary = 1000 -\end{verbatim} - - -A piece of Python code that expects a particular abstract data type -can often be passed a class that emulates the methods of that data -type instead. For instance, if you have a function that formats some -data from a file object, you can define a class with methods -\verb\read()\ and \verb\readline()\ that gets the data from a string -buffer instead, and pass it as an argument. (Unfortunately, this -technique has its limitations: a class can't define operations that -are accessed by special syntax such as sequence subscripting or -arithmetic operators, and assigning such a ``pseudo-file'' to -\verb\sys.stdin\ will not cause the interpreter to read further input -from it.) - - -Instance method objects have attributes, too: \verb\m.im_self\ is the -object of which the method is an instance, and \verb\m.im_func\ is the -function object corresponding to the method. - - -XXX Mention bw compat hacks. - - -\end{document} diff --git a/Grammar/Makefile b/Grammar/Makefile deleted file mode 100644 index a48bbdbe30..0000000000 --- a/Grammar/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -TOP= .. -PGENDIR= $(TOP)/Parser -PGEN= $(PGENDIR)/pgen -DESTH= $(TOP)/Py/graminit.h -DESTC= $(TOP)/Python/graminit.c - -all: install - -install: $(DESTH) $(DESTC) - -$(DESTH): graminit.h - cp graminit.h $(DESTH) - -$(DESTC): graminit.c - cp graminit.c $(DESTC) - -graminit.c graminit.h: $(PGEN) Grammar - $(PGEN) Grammar - -$(PGEN): - cd $(PGENDIR); make pgen - -clean: - -rm -f *.o core *~ [@,#]* *.old *.orig *.rej - -rm -f graminit.[ch] - -clobber: clean - -rm -f tags TAGS diff --git a/Include/myproto.h b/Include/myproto.h deleted file mode 100644 index e6de60ea95..0000000000 --- a/Include/myproto.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef Py_PROTO_H -#define Py_PROTO_H -#ifdef __cplusplus -extern "C" { -#endif - -/*********************************************************** -Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum, -Amsterdam, The Netherlands. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the names of Stichting Mathematisch -Centrum or CWI not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior permission. - -STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO -THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE -FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -******************************************************************/ - -#ifdef HAVE_PROTOTYPES -#define PROTO(x) x -#else -#define PROTO(x) () -#endif - -#ifndef FPROTO -#define FPROTO(x) PROTO(x) -#endif - -#ifdef __cplusplus -} -#endif -#endif /* !Py_PROTO_H */ diff --git a/Include/mytime.h b/Include/mytime.h deleted file mode 100644 index fd263d62d3..0000000000 --- a/Include/mytime.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef Py_MYTIME_H -#define Py_MYTIME_H -#ifdef __cplusplus -extern "C" { -#endif - -/*********************************************************** -Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum, -Amsterdam, The Netherlands. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the names of Stichting Mathematisch -Centrum or CWI not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior permission. - -STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO -THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE -FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -******************************************************************/ - -/* Include file instead of and/or */ - -#ifdef TIME_WITH_SYS_TIME -#include -#include -#else /* !TIME_WITH_SYS_TIME */ -#ifdef HAVE_SYS_TIME_H -#include -#else /* !HAVE_SYS_TIME_H */ -#include -#endif /* !HAVE_SYS_TIME_H */ -#endif /* !TIME_WITH_SYS_TIME */ - -#ifdef __cplusplus -} -#endif -#endif /* !Py_MYTIME_H */ diff --git a/Lib/Queue.py b/Lib/Queue.py deleted file mode 100644 index 0d69777b44..0000000000 --- a/Lib/Queue.py +++ /dev/null @@ -1,120 +0,0 @@ -# A multi-producer, multi-consumer queue. - -Empty = 'Queue.Empty' # Exception raised by get_nowait() - -class Queue: - - # Initialize a queue object with a given maximum size - # (If maxsize is <= 0, the maximum size is infinite) - def __init__(self, maxsize): - self._init(maxsize) - self.mutex = thread.allocate_lock() - self.esema = thread.allocate_lock() - self.esema.acquire_lock() - self.fsema = thread.allocate_lock() - - # Get an approximation of the queue size (not reliable!) - def qsize(self): - self.mutex.acquire_lock() - n = self._qsize() - self.mutex.release_lock() - return n - - # Check if the queue is empty (not reliable!) - def empty(self): - self.mutex.acquire_lock() - n = self._empty() - self.mutex.release_lock() - return n - - # Check if the queue is full (not reliable!) - def full(self): - self.mutex.acquire_lock() - n = self._full() - self.mutex.release_lock() - return n - - # Put a new item into the queue - def put(self, item): - self.fsema.acquire_lock() - self.mutex.acquire_lock() - was_empty = self._empty() - self._put(item) - if was_empty: - self.esema.release_lock() - if not self._full(): - self.fsema.release_lock() - self.mutex.release_lock() - - # Get an item from the queue, - # blocking if necessary until one is available - def get(self): - self.esema.acquire_lock() - self.mutex.acquire_lock() - was_full = self._full() - item = self._get() - if was_full: - self.fsema.release_lock() - if not self._empty(): - self.esema.release_lock() - self.mutex.release_lock() - return item - - # Get an item from the queue if one is immediately available, - # raise Empty if the queue is empty or temporarily unavailable - def get_nowait(self): - locked = self.esema.acquire_lock(0) - self.mutex.acquire_lock() - if self._empty(): - # The queue is empyt -- we can't have esema - self.mutex.release_lock() - raise Empty - if not locked: - locked = self.esema.acquire_lock(0) - if not locked: - # Somebody else has esema - # but we have mutex -- - # go out of their way - self.mutex.release_lock() - raise Empty - was_full = self._full() - item = self._get() - if was_full: - self.fsema.release_lock() - if not self._empty(): - self.esema.release_lock() - self.mutex.release_lock() - return item - - # XXX Need to define put_nowait() as well. - - - # Override these methods to implement other queue organizations - # (e.g. stack or priority queue). - # These will only be called with appropriate locks held - - # Initialize the queue representation - def _init(self, maxsize): - self.maxsize = maxsize - self.queue = [] - - def _qsize(self): - return len(self.queue) - - # Check wheter the queue is empty - def _empty(self): - return not self.queue - - # Check whether the queue is full - def _full(self): - return self.maxsize > 0 and len(self.queue) == self.maxsize - - # Put a new item in the queue - def _put(self, item): - self.queue.append(item) - - # Get an item from the queue - def _get(self): - item = self.queue[0] - del self.queue[0] - return item diff --git a/Lib/UserDict.py b/Lib/UserDict.py deleted file mode 100644 index f6b2f823af..0000000000 --- a/Lib/UserDict.py +++ /dev/null @@ -1,18 +0,0 @@ -# A more or less complete user-defined wrapper around dictionary objects - -class UserDict: - def __init__(self): self.data = {} - def __repr__(self): return repr(self.data) - def __cmp__(self, dict): - if type(dict) == type(self.data): - return cmp(self.data, dict) - else: - return cmp(self.data, dict.data) - def __len__(self): return len(self.data) - def __getitem__(self, key): return self.data[key] - def __setitem__(self, key, item): self.data[key] = item - def __delitem__(self, key): del self.data[key] - def keys(self): return self.data.keys() - def items(self): return self.data.items() - def values(self): return self.data.values() - def has_key(self, key): return self.data.has_key(key) diff --git a/Lib/UserList.py b/Lib/UserList.py deleted file mode 100644 index 9fbcc02ad5..0000000000 --- a/Lib/UserList.py +++ /dev/null @@ -1,39 +0,0 @@ -# A more or less complete user-defined wrapper around list objects - -class UserList: - def __init__(self, *args): - if len(args) > 1: raise TypeError, 'too many args' - self.data = [] - if args: - list = args[0] - if type(list) == type(self.data): - self.data[:] = list - else: - self.data[:] = list.data[:] - def __repr__(self): return repr(self.data) - def __cmp__(self, list): - if type(list) == type(self.data): - return cmp(self.data, list) - else: - return cmp(self.data, list.data) - def __len__(self): return len(self.data) - def __getitem__(self, i): return self.data[i] - def __setitem__(self, i, item): self.data[i] = item - def __delitem__(self, i): del self.data[i] - def __getslice__(self, i, j): - userlist = UserList() - userlist.data[:] = self.data[i:j] - return userlist - def __setslice__(self, i, j, list): - if type(list) == type(self.data): - self.data[i:j] = list - else: - self.data[i:j] = list.data - def __delslice__(self, i, j): del self.data[i:j] - def append(self, item): self.data.append(item) - def insert(self, i, item): self.data.insert(i, item) - def remove(self, item): self.data.remove(item) - def count(self, item): return self.data.count(item) - def index(self, item): return self.data.index(item) - def reverse(self): self.data.reverse() - def sort(self, *args): apply(self.data.sort, args) diff --git a/Lib/aifc.py b/Lib/aifc.py deleted file mode 100644 index 69d38dd242..0000000000 --- a/Lib/aifc.py +++ /dev/null @@ -1,1002 +0,0 @@ -# Stuff to parse AIFF-C and AIFF files. -# -# Unless explicitly stated otherwise, the description below is true -# both for AIFF-C files and AIFF files. -# -# An AIFF-C file has the following structure. -# -# +-----------------+ -# | FORM | -# +-----------------+ -# | | -# +----+------------+ -# | | AIFC | -# | +------------+ -# | | | -# | | . | -# | | . | -# | | . | -# +----+------------+ -# -# An AIFF file has the string "AIFF" instead of "AIFC". -# -# A chunk consists of an identifier (4 bytes) followed by a size (4 bytes, -# big endian order), followed by the data. The size field does not include -# the size of the 8 byte header. -# -# The following chunk types are recognized. -# -# FVER -# (AIFF-C only). -# MARK -# <# of markers> (2 bytes) -# list of markers: -# (2 bytes, must be > 0) -# (4 bytes) -# ("pstring") -# COMM -# <# of channels> (2 bytes) -# <# of sound frames> (4 bytes) -# (2 bytes) -# (10 bytes, IEEE 80-bit extended -# floating point) -# in AIFF-C files only: -# (4 bytes) -# ("pstring") -# SSND -# (4 bytes, not used by this program) -# (4 bytes, not used by this program) -# -# -# A pstring consists of 1 byte length, a string of characters, and 0 or 1 -# byte pad to make the total length even. -# -# Usage. -# -# Reading AIFF files: -# f = aifc.open(file, 'r') -# where file is either the name of a file or an open file pointer. -# The open file pointer must have methods read(), seek(), and close(). -# In some types of audio files, if the setpos() method is not used, -# the seek() method is not necessary. -# -# This returns an instance of a class with the following public methods: -# getnchannels() -- returns number of audio channels (1 for -# mono, 2 for stereo) -# getsampwidth() -- returns sample width in bytes -# getframerate() -- returns sampling frequency -# getnframes() -- returns number of audio frames -# getcomptype() -- returns compression type ('NONE' for AIFF files) -# getcompname() -- returns human-readable version of -# compression type ('not compressed' for AIFF files) -# getparams() -- returns a tuple consisting of all of the -# above in the above order -# getmarkers() -- get the list of marks in the audio file or None -# if there are no marks -# getmark(id) -- get mark with the specified id (raises an error -# if the mark does not exist) -# readframes(n) -- returns at most n frames of audio -# rewind() -- rewind to the beginning of the audio stream -# setpos(pos) -- seek to the specified position -# tell() -- return the current position -# close() -- close the instance (make it unusable) -# The position returned by tell(), the position given to setpos() and -# the position of marks are all compatible and have nothing to do with -# the actual postion in the file. -# The close() method is called automatically when the class instance -# is destroyed. -# -# Writing AIFF files: -# f = aifc.open(file, 'w') -# where file is either the name of a file or an open file pointer. -# The open file pointer must have methods write(), tell(), seek(), and -# close(). -# -# This returns an instance of a class with the following public methods: -# aiff() -- create an AIFF file (AIFF-C default) -# aifc() -- create an AIFF-C file -# setnchannels(n) -- set the number of channels -# setsampwidth(n) -- set the sample width -# setframerate(n) -- set the frame rate -# setnframes(n) -- set the number of frames -# setcomptype(type, name) -# -- set the compression type and the -# human-readable compression type -# setparams(nchannels, sampwidth, framerate, nframes, comptype, compname) -# -- set all parameters at once -# setmark(id, pos, name) -# -- add specified mark to the list of marks -# tell() -- return current position in output file (useful -# in combination with setmark()) -# writeframesraw(data) -# -- write audio frames without pathing up the -# file header -# writeframes(data) -# -- write audio frames and patch up the file header -# close() -- patch up the file header and close the -# output file -# You should set the parameters before the first writeframesraw or -# writeframes. The total number of frames does not need to be set, -# but when it is set to the correct value, the header does not have to -# be patched up. -# It is best to first set all parameters, perhaps possibly the -# compression type, and then write audio frames using writeframesraw. -# When all frames have been written, either call writeframes('') or -# close() to patch up the sizes in the header. -# Marks can be added anytime. If there are any marks, ypu must call -# close() after all frames have been written. -# The close() method is called automatically when the class instance -# is destroyed. -# -# When a file is opened with the extension '.aiff', an AIFF file is -# written, otherwise an AIFF-C file is written. This default can be -# changed by calling aiff() or aifc() before the first writeframes or -# writeframesraw. - -import builtin -import AL -try: - import CL -except ImportError: - pass - -Error = 'aifc.Error' - -_AIFC_version = 0xA2805140 # Version 1 of AIFF-C - -_skiplist = 'COMT', 'INST', 'MIDI', 'AESD', \ - 'APPL', 'NAME', 'AUTH', '(c) ', 'ANNO' - -_nchannelslist = [(1, AL.MONO), (2, AL.STEREO)] -_sampwidthlist = [(8, AL.SAMPLE_8), (16, AL.SAMPLE_16), (24, AL.SAMPLE_24)] -_frameratelist = [(48000, AL.RATE_48000), - (44100, AL.RATE_44100), - (32000, AL.RATE_32000), - (22050, AL.RATE_22050), - (16000, AL.RATE_16000), - (11025, AL.RATE_11025), - ( 8000, AL.RATE_8000)] - -def _convert1(value, list): - for t in list: - if value == t[0]: - return t[1] - raise Error, 'unknown parameter value' - -def _convert2(value, list): - for t in list: - if value == t[1]: - return t[0] - raise Error, 'unknown parameter value' - -def _read_long(file): - x = 0L - for i in range(4): - byte = file.read(1) - if byte == '': - raise EOFError - x = x*256 + ord(byte) - if x >= 0x80000000L: - x = x - 0x100000000L - return int(x) - -def _read_ulong(file): - x = 0L - for i in range(4): - byte = file.read(1) - if byte == '': - raise EOFError - x = x*256 + ord(byte) - return x - -def _read_short(file): - x = 0 - for i in range(2): - byte = file.read(1) - if byte == '': - raise EOFError - x = x*256 + ord(byte) - if x >= 0x8000: - x = x - 0x10000 - return x - -def _read_string(file): - length = ord(file.read(1)) - data = file.read(length) - if length & 1 == 0: - dummy = file.read(1) - return data - -_HUGE_VAL = 1.79769313486231e+308 # See - -def _read_float(f): # 10 bytes - import math - expon = _read_short(f) # 2 bytes - sign = 1 - if expon < 0: - sign = -1 - expon = expon + 0x8000 - himant = _read_ulong(f) # 4 bytes - lomant = _read_ulong(f) # 4 bytes - if expon == himant == lomant == 0: - f = 0.0 - elif expon == 0x7FFF: - f = _HUGE_VAL - else: - expon = expon - 16383 - f = (himant * 0x100000000L + lomant) * pow(2.0, expon - 63) - return sign * f - -def _write_short(f, x): - d, m = divmod(x, 256) - f.write(chr(d)) - f.write(chr(m)) - -def _write_long(f, x): - if x < 0: - x = x + 0x100000000L - data = [] - for i in range(4): - d, m = divmod(x, 256) - data.insert(0, m) - x = d - for i in range(4): - f.write(chr(int(data[i]))) - -def _write_string(f, s): - f.write(chr(len(s))) - f.write(s) - if len(s) & 1 == 0: - f.write(chr(0)) - -def _write_float(f, x): - import math - if x < 0: - sign = 0x8000 - x = x * -1 - else: - sign = 0 - if x == 0: - expon = 0 - himant = 0 - lomant = 0 - else: - fmant, expon = math.frexp(x) - if expon > 16384 or fmant >= 1: # Infinity or NaN - expon = sign|0x7FFF - himant = 0 - lomant = 0 - else: # Finite - expon = expon + 16382 - if expon < 0: # denormalized - fmant = math.ldexp(fmant, expon) - expon = 0 - expon = expon | sign - fmant = math.ldexp(fmant, 32) - fsmant = math.floor(fmant) - himant = long(fsmant) - fmant = math.ldexp(fmant - fsmant, 32) - fsmant = math.floor(fmant) - lomant = long(fsmant) - _write_short(f, expon) - _write_long(f, himant) - _write_long(f, lomant) - -class Chunk: - def __init__(self, file): - self.file = file - self.chunkname = self.file.read(4) - if len(self.chunkname) < 4: - raise EOFError - self.chunksize = _read_long(self.file) - self.size_read = 0 - self.offset = self.file.tell() - - def rewind(self): - self.file.seek(self.offset, 0) - self.size_read = 0 - - def setpos(self, pos): - if pos < 0 or pos > self.chunksize: - raise RuntimeError - self.file.seek(self.offset + pos, 0) - self.size_read = pos - - def read(self, length): - if self.size_read >= self.chunksize: - return '' - if length > self.chunksize - self.size_read: - length = self.chunksize - self.size_read - data = self.file.read(length) - self.size_read = self.size_read + len(data) - return data - - def skip(self): - try: - self.file.seek(self.chunksize - self.size_read, 1) - except RuntimeError: - while self.size_read < self.chunksize: - dummy = self.read(8192) - if not dummy: - raise EOFError - if self.chunksize & 1: - dummy = self.read(1) - -class Aifc_read: - # Variables used in this class: - # - # These variables are available to the user though appropriate - # methods of this class: - # _file -- the open file with methods read(), close(), and seek() - # set through the __init__() method - # _nchannels -- the number of audio channels - # available through the getnchannels() method - # _nframes -- the number of audio frames - # available through the getnframes() method - # _sampwidth -- the number of bytes per audio sample - # available through the getsampwidth() method - # _framerate -- the sampling frequency - # available through the getframerate() method - # _comptype -- the AIFF-C compression type ('NONE' if AIFF) - # available through the getcomptype() method - # _compname -- the human-readable AIFF-C compression type - # available through the getcomptype() method - # _markers -- the marks in the audio file - # available through the getmarkers() and getmark() - # methods - # _soundpos -- the position in the audio stream - # available through the tell() method, set through the - # setpos() method - # - # These variables are used internally only: - # _version -- the AIFF-C version number - # _decomp -- the decompressor from builtin module cl - # _comm_chunk_read -- 1 iff the COMM chunk has been read - # _aifc -- 1 iff reading an AIFF-C file - # _ssnd_seek_needed -- 1 iff positioned correctly in audio - # file for readframes() - # _ssnd_chunk -- instantiation of a chunk class for the SSND chunk - # _framesize -- size of one frame in the file - - access _file, _nchannels, _nframes, _sampwidth, _framerate, \ - _comptype, _compname, _markers, _soundpos, _version, \ - _decomp, _comm_chunk_read, __aifc, _ssnd_seek_needed, \ - _ssnd_chunk, _framesize: private - - def initfp(self, file): - self._file = file - self._version = 0 - self._decomp = None - self._convert = None - self._markers = [] - self._soundpos = 0 - form = self._file.read(4) - if form != 'FORM': - raise Error, 'file does not start with FORM id' - formlength = _read_long(self._file) - if formlength <= 0: - raise Error, 'invalid FORM chunk data size' - formdata = self._file.read(4) - formlength = formlength - 4 - if formdata == 'AIFF': - self._aifc = 0 - elif formdata == 'AIFC': - self._aifc = 1 - else: - raise Error, 'not an AIFF or AIFF-C file' - self._comm_chunk_read = 0 - while formlength > 0: - self._ssnd_seek_needed = 1 - #DEBUG: SGI's soundfiler has a bug. There should - # be no need to check for EOF here. - try: - chunk = Chunk(self._file) - except EOFError: - if formlength == 8: - print 'Warning: FORM chunk size too large' - formlength = 0 - break - raise EOFError # different error, raise exception - if chunk.chunkname == 'COMM': - self._read_comm_chunk(chunk) - self._comm_chunk_read = 1 - elif chunk.chunkname == 'SSND': - self._ssnd_chunk = chunk - dummy = chunk.read(8) - self._ssnd_seek_needed = 0 - elif chunk.chunkname == 'FVER': - self._version = _read_long(chunk) - elif chunk.chunkname == 'MARK': - self._readmark(chunk) - elif chunk.chunkname in _skiplist: - pass - else: - raise Error, 'unrecognized chunk type '+chunk.chunkname - formlength = formlength - 8 - chunk.chunksize - if chunk.chunksize & 1: - formlength = formlength - 1 - if formlength > 0: - chunk.skip() - if not self._comm_chunk_read or not self._ssnd_chunk: - raise Error, 'COMM chunk and/or SSND chunk missing' - if self._aifc and self._decomp: - params = [CL.ORIGINAL_FORMAT, 0, \ - CL.BITS_PER_COMPONENT, 0, \ - CL.FRAME_RATE, self._framerate] - if self._nchannels == AL.MONO: - params[1] = CL.MONO - else: - params[1] = CL.STEREO_INTERLEAVED - if self._sampwidth == AL.SAMPLE_8: - params[3] = 8 - elif self._sampwidth == AL.SAMPLE_16: - params[3] = 16 - else: - params[3] = 24 - self._decomp.SetParams(params) - - def __init__(self, f): - if type(f) == type(''): - f = builtin.open(f, 'r') - # else, assume it is an open file object already - self.initfp(f) - - def __del__(self): - if self._file: - self.close() - - # - # User visible methods. - # - def getfp(self): - return self._file - - def rewind(self): - self._ssnd_seek_needed = 1 - self._soundpos = 0 - - def close(self): - if self._decomp: - self._decomp.CloseDecompressor() - self._decomp = None - self._file = None - - def tell(self): - return self._soundpos - - def getnchannels(self): - return self._nchannels - - def getnframes(self): - return self._nframes - - def getsampwidth(self): - return self._sampwidth - - def getframerate(self): - return self._framerate - - def getcomptype(self): - return self._comptype - - def getcompname(self): - return self._compname - -## def getversion(self): -## return self._version - - def getparams(self): - return self.getnchannels(), self.getsampwidth(), \ - self.getframerate(), self.getnframes(), \ - self.getcomptype(), self.getcompname() - - def getmarkers(self): - if len(self._markers) == 0: - return None - return self._markers - - def getmark(self, id): - for marker in self._markers: - if id == marker[0]: - return marker - raise Error, 'marker ' + `id` + ' does not exist' - - def setpos(self, pos): - if pos < 0 or pos > self._nframes: - raise Error, 'position not in range' - self._soundpos = pos - self._ssnd_seek_needed = 1 - - def readframes(self, nframes): - if self._ssnd_seek_needed: - self._ssnd_chunk.rewind() - dummy = self._ssnd_chunk.read(8) - pos = self._soundpos * self._framesize - if pos: - self._ssnd_chunk.setpos(pos + 8) - self._ssnd_seek_needed = 0 - if nframes == 0: - return '' - data = self._ssnd_chunk.read(nframes * self._framesize) - if self._convert and data: - data = self._convert(data) - self._soundpos = self._soundpos + len(data) / (self._nchannels * self._sampwidth) - return data - - # - # Internal methods. - # - access *: private - - def _decomp_data(self, data): - dummy = self._decomp.SetParam(CL.FRAME_BUFFER_SIZE, - len(data) * 2) - return self._decomp.Decompress(len(data) / self._nchannels, - data) - - def _ulaw2lin(self, data): - import audioop - return audioop.ulaw2lin(data, 2) - - def _read_comm_chunk(self, chunk): - nchannels = _read_short(chunk) - self._nchannels = _convert1(nchannels, _nchannelslist) - self._nframes = _read_long(chunk) - sampwidth = _read_short(chunk) - self._sampwidth = _convert1(sampwidth, _sampwidthlist) - framerate = _read_float(chunk) - self._framerate = _convert1(framerate, _frameratelist) - self._framesize = self._nchannels * self._sampwidth - if self._aifc: - #DEBUG: SGI's soundeditor produces a bad size :-( - kludge = 0 - if chunk.chunksize == 18: - kludge = 1 - print 'Warning: bad COMM chunk size' - chunk.chunksize = 23 - #DEBUG end - self._comptype = chunk.read(4) - #DEBUG start - if kludge: - length = ord(chunk.file.read(1)) - if length & 1 == 0: - length = length + 1 - chunk.chunksize = chunk.chunksize + length - chunk.file.seek(-1, 1) - #DEBUG end - self._compname = _read_string(chunk) - if self._comptype != 'NONE': - try: - import cl, CL - except ImportError: - if self._comptype == 'ULAW': - try: - import audioop - self._convert = self._ulaw2lin - self._framesize = self._framesize / 2 - return - except ImportError: - pass - raise Error, 'cannot read compressed AIFF-C files' - if self._comptype == 'ULAW': - scheme = CL.G711_ULAW - self._framesize = self._framesize / 2 - elif self._comptype == 'ALAW': - scheme = CL.G711_ALAW - self._framesize = self._framesize / 2 - else: - raise Error, 'unsupported compression type' - self._decomp = cl.OpenDecompressor(scheme) - self._convert = self._decomp_data - else: - self._comptype = 'NONE' - self._compname = 'not compressed' - - def _readmark(self, chunk): - nmarkers = _read_short(chunk) - # Some files appear to contain invalid counts. - # Cope with this by testing for EOF. - try: - for i in range(nmarkers): - id = _read_short(chunk) - pos = _read_long(chunk) - name = _read_string(chunk) - self._markers.append((id, pos, name)) - except EOFError: - print 'Warning: MARK chunk contains only', - print len(self._markers), - if len(self._markers) == 1: print 'marker', - else: print 'markers', - print 'instead of', nmarkers - -class Aifc_write: - # Variables used in this class: - # - # These variables are user settable through appropriate methods - # of this class: - # _file -- the open file with methods write(), close(), tell(), seek() - # set through the __init__() method - # _comptype -- the AIFF-C compression type ('NONE' in AIFF) - # set through the setcomptype() or setparams() method - # _compname -- the human-readable AIFF-C compression type - # set through the setcomptype() or setparams() method - # _nchannels -- the number of audio channels - # set through the setnchannels() or setparams() method - # _sampwidth -- the number of bytes per audio sample - # set through the setsampwidth() or setparams() method - # _framerate -- the sampling frequency - # set through the setframerate() or setparams() method - # _nframes -- the number of audio frames written to the header - # set through the setnframes() or setparams() method - # _aifc -- whether we're writing an AIFF-C file or an AIFF file - # set through the aifc() method, reset through the - # aiff() method - # - # These variables are used internally only: - # _version -- the AIFF-C version number - # _comp -- the compressor from builtin module cl - # _nframeswritten -- the number of audio frames actually written - # _datalength -- the size of the audio samples written to the header - # _datawritten -- the size of the audio samples actually written - - access _file, _comptype, _compname, _nchannels, _sampwidth, \ - _framerate, _nframes, _aifc, _version, _comp, \ - _nframeswritten, _datalength, _datawritten: private - - def __init__(self, f): - if type(f) == type(''): - filename = f - f = builtin.open(f, 'w') - else: - # else, assume it is an open file object already - filename = '???' - self.initfp(f) - if filename[-5:] == '.aiff': - self._aifc = 0 - else: - self._aifc = 1 - - def initfp(self, file): - self._file = file - self._version = _AIFC_version - self._comptype = 'NONE' - self._compname = 'not compressed' - self._comp = None - self._convert = None - self._nchannels = 0 - self._sampwidth = 0 - self._framerate = 0 - self._nframes = 0 - self._nframeswritten = 0 - self._datawritten = 0 - self._datalength = 0 - self._markers = [] - self._marklength = 0 - self._aifc = 1 # AIFF-C is default - - def __del__(self): - if self._file: - self.close() - - # - # User visible methods. - # - def aiff(self): - if self._nframeswritten: - raise Error, 'cannot change parameters after starting to write' - self._aifc = 0 - - def aifc(self): - if self._nframeswritten: - raise Error, 'cannot change parameters after starting to write' - self._aifc = 1 - - def setnchannels(self, nchannels): - if self._nframeswritten: - raise Error, 'cannot change parameters after starting to write' - dummy = _convert2(nchannels, _nchannelslist) - self._nchannels = nchannels - - def getnchannels(self): - if not self._nchannels: - raise Error, 'number of channels not set' - return self._nchannels - - def setsampwidth(self, sampwidth): - if self._nframeswritten: - raise Error, 'cannot change parameters after starting to write' - dummy = _convert2(sampwidth, _sampwidthlist) - self._sampwidth = sampwidth - - def getsampwidth(self): - if not self._sampwidth: - raise Error, 'sample width not set' - return self._sampwidth - - def setframerate(self, framerate): - if self._nframeswritten: - raise Error, 'cannot change parameters after starting to write' - dummy = _convert2(framerate, _frameratelist) - self._framerate = framerate - - def getframerate(self): - if not self._framerate: - raise Error, 'frame rate not set' - return self._framerate - - def setnframes(self, nframes): - if self._nframeswritten: - raise Error, 'cannot change parameters after starting to write' - self._nframes = nframes - - def getnframes(self): - return self._nframeswritten - - def setcomptype(self, comptype, compname): - if self._nframeswritten: - raise Error, 'cannot change parameters after starting to write' - if comptype not in ('NONE', 'ULAW', 'ALAW'): - raise Error, 'unsupported compression type' - self._comptype = comptype - self._compname = compname - - def getcomptype(self): - return self._comptype - - def getcompname(self): - return self._compname - -## def setversion(self, version): -## if self._nframeswritten: -## raise Error, 'cannot change parameters after starting to write' -## self._version = version - - def setparams(self, (nchannels, sampwidth, framerate, nframes, comptype, compname)): - if self._nframeswritten: - raise Error, 'cannot change parameters after starting to write' - if comptype not in ('NONE', 'ULAW', 'ALAW'): - raise Error, 'unsupported compression type' - dummy = _convert2(nchannels, _nchannelslist) - dummy = _convert2(sampwidth, _sampwidthlist) - dummy = _convert2(framerate, _frameratelist) - self._nchannels = nchannels - self._sampwidth = sampwidth - self._framerate = framerate - self._nframes = nframes - self._comptype = comptype - self._compname = compname - - def getparams(self): - if not self._nchannels or not self._sampwidth or not self._framerate: - raise Error, 'not all parameters set' - return self._nchannels, self._sampwidth, self._framerate, \ - self._nframes, self._comptype, self._compname - - def setmark(self, id, pos, name): - if id <= 0: - raise Error, 'marker ID must be > 0' - if pos < 0: - raise Error, 'marker position must be >= 0' - if type(name) != type(''): - raise Error, 'marker name must be a string' - for i in range(len(self._markers)): - if id == self._markers[i][0]: - self._markers[i] = id, pos, name - return - self._markers.append((id, pos, name)) - - def getmark(self, id): - for marker in self._markers: - if id == marker[0]: - return marker - raise Error, 'marker ' + `id` + ' does not exist' - - def getmarkers(self): - if len(self._markers) == 0: - return None - return self._markers - - def tell(self): - return self._nframeswritten - - def writeframesraw(self, data): - self._ensure_header_written(len(data)) - nframes = len(data) / (self._sampwidth * self._nchannels) - if self._convert: - data = self._convert(data) - self._file.write(data) - self._nframeswritten = self._nframeswritten + nframes - self._datawritten = self._datawritten + len(data) - - def writeframes(self, data): - self.writeframesraw(data) - if self._nframeswritten != self._nframes or \ - self._datalength != self._datawritten: - self._patchheader() - - def close(self): - self._ensure_header_written(0) - if self._datawritten & 1: - # quick pad to even size - self._file.write(chr(0)) - self._datawritten = self._datawritten + 1 - self._writemarkers() - if self._nframeswritten != self._nframes or \ - self._datalength != self._datawritten or \ - self._marklength: - self._patchheader() - if self._comp: - self._comp.CloseCompressor() - self._comp = None - self._file.flush() - self._file = None - - # - # Internal methods. - # - access *: private - - def _comp_data(self, data): - dum = self._comp.SetParam(CL.FRAME_BUFFER_SIZE, len(data)) - dum = self._comp.SetParam(CL.COMPRESSED_BUFFER_SIZE, len(data)) - return self._comp.Compress(nframes, data) - - def _lin2ulaw(self, data): - import audioop - return audioop.lin2ulaw(data, 2) - - def _ensure_header_written(self, datasize): - if not self._nframeswritten: - if self._comptype in ('ULAW', 'ALAW'): - if not self._sampwidth: - self._sampwidth = AL.SAMPLE_16 - if self._sampwidth != AL.SAMPLE_16: - raise Error, 'sample width must be 2 when compressing with ULAW or ALAW' - if not self._nchannels: - raise Error, '# channels not specified' - if not self._sampwidth: - raise Error, 'sample width not specified' - if not self._framerate: - raise Error, 'sampling rate not specified' - self._write_header(datasize) - - def _init_compression(self): - try: - import cl, CL - except ImportError: - if self._comptype == 'ULAW': - try: - import audioop - self._convert = self._lin2ulaw - return - except ImportError: - pass - raise Error, 'cannot write compressed AIFF-C files' - if self._comptype == 'ULAW': - scheme = CL.G711_ULAW - elif self._comptype == 'ALAW': - scheme = CL.G711_ALAW - else: - raise Error, 'unsupported compression type' - self._comp = cl.OpenCompressor(scheme) - params = [CL.ORIGINAL_FORMAT, 0, \ - CL.BITS_PER_COMPONENT, 0, \ - CL.FRAME_RATE, self._framerate, \ - CL.FRAME_BUFFER_SIZE, 100, \ - CL.COMPRESSED_BUFFER_SIZE, 100] - if self._nchannels == AL.MONO: - params[1] = CL.MONO - else: - params[1] = CL.STEREO_INTERLEAVED - if self._sampwidth == AL.SAMPLE_8: - params[3] = 8 - elif self._sampwidth == AL.SAMPLE_16: - params[3] = 16 - else: - params[3] = 24 - self._comp.SetParams(params) - # the compressor produces a header which we ignore - dummy = self._comp.Compress(0, '') - self._convert = self._comp_data - - def _write_header(self, initlength): - if self._aifc and self._comptype != 'NONE': - self._init_compression() - self._file.write('FORM') - if not self._nframes: - self._nframes = initlength / (self._nchannels * self._sampwidth) - self._datalength = self._nframes * self._nchannels * self._sampwidth - if self._datalength & 1: - self._datalength = self._datalength + 1 - if self._aifc and self._comptype in ('ULAW', 'ALAW'): - self._datalength = self._datalength / 2 - if self._datalength & 1: - self._datalength = self._datalength + 1 - self._form_length_pos = self._file.tell() - commlength = self._write_form_length(self._datalength) - if self._aifc: - self._file.write('AIFC') - self._file.write('FVER') - _write_long(self._file, 4) - _write_long(self._file, self._version) - else: - self._file.write('AIFF') - self._file.write('COMM') - _write_long(self._file, commlength) - _write_short(self._file, _convert2(self._nchannels, _nchannelslist)) - self._nframes_pos = self._file.tell() - _write_long(self._file, self._nframes) - _write_short(self._file, _convert2(self._sampwidth, _sampwidthlist)) - _write_float(self._file, _convert2(self._framerate, _frameratelist)) - if self._aifc: - self._file.write(self._comptype) - _write_string(self._file, self._compname) - self._file.write('SSND') - self._ssnd_length_pos = self._file.tell() - _write_long(self._file, self._datalength + 8) - _write_long(self._file, 0) - _write_long(self._file, 0) - - def _write_form_length(self, datalength): - if self._aifc: - commlength = 18 + 5 + len(self._compname) - if commlength & 1: - commlength = commlength + 1 - verslength = 12 - else: - commlength = 18 - verslength = 0 - _write_long(self._file, 4 + verslength + self._marklength + \ - 8 + commlength + 16 + datalength) - return commlength - - def _patchheader(self): - curpos = self._file.tell() - if self._datawritten & 1: - datalength = self._datawritten + 1 - self._file.write(chr(0)) - else: - datalength = self._datawritten - if datalength == self._datalength and \ - self._nframes == self._nframeswritten and \ - self._marklength == 0: - self._file.seek(curpos, 0) - return - self._file.seek(self._form_length_pos, 0) - dummy = self._write_form_length(datalength) - self._file.seek(self._nframes_pos, 0) - _write_long(self._file, self._nframeswritten) - self._file.seek(self._ssnd_length_pos, 0) - _write_long(self._file, datalength + 8) - self._file.seek(curpos, 0) - self._nframes = self._nframeswritten - self._datalength = datalength - - def _writemarkers(self): - if len(self._markers) == 0: - return - self._file.write('MARK') - length = 2 - for marker in self._markers: - id, pos, name = marker - length = length + len(name) + 1 + 6 - if len(name) & 1 == 0: - length = length + 1 - _write_long(self._file, length) - self._marklength = length + 8 - _write_short(self._file, len(self._markers)) - for marker in self._markers: - id, pos, name = marker - _write_short(self._file, id) - _write_long(self._file, pos) - _write_string(self._file, name) - -def open(f, mode): - if mode == 'r': - return Aifc_read(f) - elif mode == 'w': - return Aifc_write(f) - else: - raise Error, "mode must be 'r' or 'w'" - -openfp = open # B/W compatibility diff --git a/Lib/audiodev.py b/Lib/audiodev.py deleted file mode 100644 index d0dcfed22e..0000000000 --- a/Lib/audiodev.py +++ /dev/null @@ -1,205 +0,0 @@ -import AL, SUNAUDIODEV - -error = 'audiodev.error' - -class Play_Audio_sgi: - # Private instance variables - access frameratelist, nchannelslist, sampwidthlist, oldparams, \ - params, config, inited_outrate, inited_width, \ - inited_nchannels, port, converter: private - - frameratelist = [(48000, AL.RATE_48000), - (44100, AL.RATE_44100), - (32000, AL.RATE_32000), - (22050, AL.RATE_22050), - (16000, AL.RATE_16000), - (11025, AL.RATE_11025), - ( 8000, AL.RATE_8000)] - nchannelslist = [(1, AL.MONO), - (2, AL.STEREO)] - sampwidthlist = [(1, AL.SAMPLE_8), - (2, AL.SAMPLE_16), - (3, AL.SAMPLE_24)] - - def __init__(self): - import al - self.oldparams = [] - self.params = [AL.OUTPUT_RATE, 0] - self.config = al.newconfig() - self.inited_outrate = 0 - self.inited_width = 0 - self.inited_nchannels = 0 - self.converter = None - self.port = None - return - - def __del__(self): - if self.port: - self.stop() - if self.oldparams: - import al - al.setparams(AL.DEFAULT_DEVICE, self.oldparams) - self.oldparams = [] - - def wait(self): - if not self.port: - return - import time - while self.port.getfilled() > 0: - time.sleep(0.1) - self.stop() - - def stop(self): - if self.port: - self.port.closeport() - self.port = None - if self.oldparams: - import al - al.setparams(AL.DEFAULT_DEVICE, self.oldparams) - self.oldparams = [] - - def setoutrate(self, rate): - for (raw, cooked) in self.frameratelist: - if rate == raw: - self.params[1] = cooked - self.inited_outrate = 1 - break - else: - raise error, 'bad output rate' - - def setsampwidth(self, width): - for (raw, cooked) in self.sampwidthlist: - if width == raw: - self.config.setwidth(cooked) - self.inited_width = 1 - break - else: - if width == 0: - self.inited_width = 0 - self.config.setwidth(AL.SAMPLE_16) - self.converter = self.ulaw2lin - else: - raise error, 'bad sample width' - - def setnchannels(self, nchannels): - for (raw, cooked) in self.nchannelslist: - if nchannels == raw: - self.config.setchannels(cooked) - self.inited_nchannels = 1 - break - else: - raise error, 'bad # of channels' - - def writeframes(self, data): - if not (self.inited_outrate and self.inited_nchannels): - raise error, 'params not specified' - if not self.port: - import al - self.port = al.openport('Python', 'w', self.config) - self.oldparams = self.params[:] - al.getparams(AL.DEFAULT_DEVICE, self.oldparams) - al.setparams(AL.DEFAULT_DEVICE, self.params) - if self.converter: - data = self.converter(data) - self.port.writesamps(data) - - def getfilled(self): - if self.port: - return self.port.getfilled() - else: - return 0 - - def getfillable(self): - if self.port: - return self.port.getfillable() - else: - return self.config.getqueuesize() - - # private methods - access *: private - - def ulaw2lin(self, data): - import audioop - return audioop.ulaw2lin(data, 2) - -class Play_Audio_sun: - access outrate, sampwidth, nchannels, inited_outrate, inited_width, \ - inited_nchannels, converter: private - - def __init__(self): - self.outrate = 0 - self.sampwidth = 0 - self.nchannels = 0 - self.inited_outrate = 0 - self.inited_width = 0 - self.inited_nchannels = 0 - self.converter = None - self.port = None - return - - def __del__(self): - self.stop() - - def setoutrate(self, rate): - self.outrate = rate - self.inited_outrate = 1 - - def setsampwidth(self, width): - self.sampwidth = width - self.inited_width = 1 - - def setnchannels(self, nchannels): - self.nchannels = nchannels - self.inited_nchannels = 1 - - def writeframes(self, data): - if not (self.inited_outrate and self.inited_width and self.inited_nchannels): - raise error, 'params not specified' - if not self.port: - import sunaudiodev - self.port = sunaudiodev.open('w') - info = self.port.getinfo() - info.o_sample_rate = self.outrate - info.o_channels = self.nchannels - if self.sampwidth == 0: - info.o_precision = 8 - self.o_encoding = ENCODING_ULAW - else: - info.o_precision = 8 * self.sampwidth - info.o_encoding = SUNAUDIODEV.ENCODING_LINEAR - self.port.setinfo(info) - if self.converter: - data = self.converter(data) - self.port.write(data) - - def wait(self): - if not self.port: - return - self.port.drain() - self.stop() - - def stop(self): - if self.port: - self.port.flush() - self.port.close() - self.port = None - - def getfilled(self): - if self.port: - return self.port.obufcount() - else: - return 0 - - def getfillable(self): - return BUFFERSIZE - self.getfilled() - -def AudioDev(): - try: - import al - return Play_Audio_sgi() - except ImportError: - try: - import sunaudiodev - return Play_Audio_sun() - except ImportError: - raise error, 'no audio device' diff --git a/Lib/bdb.py b/Lib/bdb.py deleted file mode 100644 index 6b3eab9564..0000000000 --- a/Lib/bdb.py +++ /dev/null @@ -1,306 +0,0 @@ -# A generic Python debugger base class. -# This class takes care of details of the trace facility; -# a derived class should implement user interaction. -# There are two debuggers based upon this: -# 'pdb', a text-oriented debugger not unlike dbx or gdb; -# and 'wdb', a window-oriented debugger. -# And of course... you can roll your own! - -import sys - -BdbQuit = 'bdb.BdbQuit' # Exception to give up completely - - -class Bdb: # Basic Debugger - - def __init__(self): - self.breaks = {} - - def reset(self): - self.botframe = None - self.stopframe = None - self.returnframe = None - self.quitting = 0 - - def trace_dispatch(self, frame, event, arg): - if self.quitting: - return # None - if event == 'line': - return self.dispatch_line(frame) - if event == 'call': - return self.dispatch_call(frame, arg) - if event == 'return': - return self.dispatch_return(frame, arg) - if event == 'exception': - return self.dispatch_exception(frame, arg) - print 'bdb.Bdb.dispatch: unknown debugging event:', `event` - return self.trace_dispatch - - def dispatch_line(self, frame): - if self.stop_here(frame) or self.break_here(frame): - self.user_line(frame) - if self.quitting: raise BdbQuit - return self.trace_dispatch - - def dispatch_call(self, frame, arg): - frame.f_locals['__args__'] = arg - if self.botframe is None: - # First call of dispatch since reset() - self.botframe = frame - return self.trace_dispatch - if not (self.stop_here(frame) or self.break_anywhere(frame)): - # No need to trace this function - return # None - self.user_call(frame, arg) - if self.quitting: raise BdbQuit - return self.trace_dispatch - - def dispatch_return(self, frame, arg): - if self.stop_here(frame) or frame == self.returnframe: - self.user_return(frame, arg) - if self.quitting: raise BdbQuit - - def dispatch_exception(self, frame, arg): - if self.stop_here(frame): - self.user_exception(frame, arg) - if self.quitting: raise BdbQuit - return self.trace_dispatch - - # Normally derived classes don't override the following - # methods, but they may if they want to redefine the - # definition of stopping and breakpoints. - - def stop_here(self, frame): - if self.stopframe is None: - return 1 - if frame is self.stopframe: - return 1 - while frame is not None and frame is not self.stopframe: - if frame is self.botframe: - return 1 - frame = frame.f_back - return 0 - - def break_here(self, frame): - if not self.breaks.has_key(frame.f_code.co_filename): - return 0 - if not frame.f_lineno in \ - self.breaks[frame.f_code.co_filename]: - return 0 - return 1 - - def break_anywhere(self, frame): - return self.breaks.has_key(frame.f_code.co_filename) - - # Derived classes should override the user_* methods - # to gain control. - - def user_call(self, frame, argument_list): - # This method is called when there is the remote possibility - # that we ever need to stop in this function - pass - - def user_line(self, frame): - # This method is called when we stop or break at this line - pass - - def user_return(self, frame, return_value): - # This method is called when a return trap is set here - pass - - def user_exception(self, frame, (exc_type, exc_value, exc_traceback)): - # This method is called if an exception occurs, - # but only if we are to stop at or just below this level - pass - - # Derived classes and clients can call the following methods - # to affect the stepping state. - - def set_step(self): - # Stop after one line of code - self.stopframe = None - self.returnframe = None - self.quitting = 0 - - def set_next(self, frame): - # Stop on the next line in or below the given frame - self.stopframe = frame - self.returnframe = None - self.quitting = 0 - - def set_return(self, frame): - # Stop when returning from the given frame - self.stopframe = frame.f_back - self.returnframe = frame - self.quitting = 0 - - def set_continue(self): - # Don't stop except at breakpoints or when finished - self.stopframe = self.botframe - self.returnframe = None - self.quitting = 0 - - def set_quit(self): - self.stopframe = self.botframe - self.returnframe = None - self.quitting = 1 - sys.settrace(None) - - # Derived classes and clients can call the following methods - # to manipulate breakpoints. These methods return an - # error message is something went wrong, None if all is well. - # Call self.get_*break*() to see the breakpoints. - - def set_break(self, filename, lineno): - import linecache # Import as late as possible - line = linecache.getline(filename, lineno) - if not line: - return 'That line does not exist!' - if not self.breaks.has_key(filename): - self.breaks[filename] = [] - list = self.breaks[filename] - if lineno in list: - return 'There is already a breakpoint there!' - list.append(lineno) - - def clear_break(self, filename, lineno): - if not self.breaks.has_key(filename): - return 'There are no breakpoints in that file!' - if lineno not in self.breaks[filename]: - return 'There is no breakpoint there!' - self.breaks[filename].remove(lineno) - if not self.breaks[filename]: - del self.breaks[filename] - - def clear_all_file_breaks(self, filename): - if not self.breaks.has_key(filename): - return 'There are no breakpoints in that file!' - del self.breaks[filename] - - def clear_all_breaks(self, filename, lineno): - if not self.breaks: - return 'There are no breakpoints!' - self.breaks = {} - - def get_break(self, filename, lineno): - return self.breaks.has_key(filename) and \ - lineno in self.breaks[filename] - - def get_file_breaks(self, filename): - if self.breaks.has_key(filename): - return self.breaks[filename] - else: - return [] - - def get_all_breaks(self): - return self.breaks - - # Derived classes and clients can call the following method - # to get a data structure representing a stack trace. - - def get_stack(self, f, t): - stack = [] - if t and t.tb_frame is f: - t = t.tb_next - while f is not None: - stack.append((f, f.f_lineno)) - if f is self.botframe: - break - f = f.f_back - stack.reverse() - i = max(0, len(stack) - 1) - while t is not None: - stack.append((t.tb_frame, t.tb_lineno)) - t = t.tb_next - return stack, i - - # - - def format_stack_entry(self, frame_lineno): - import codehack, linecache, repr, string - frame, lineno = frame_lineno - filename = frame.f_code.co_filename - s = filename + '(' + `lineno` + ')' - s = s + codehack.getcodename(frame.f_code) - if frame.f_locals.has_key('__args__'): - args = frame.f_locals['__args__'] - if args is not None: - s = s + repr.repr(args) - if frame.f_locals.has_key('__return__'): - rv = frame.f_locals['__return__'] - s = s + '->' - s = s + repr.repr(rv) - line = linecache.getline(filename, lineno) - if line: s = s + ': ' + string.strip(line) - return s - - # The following two methods can be called by clients to use - # a debugger to debug a statement, given as a string. - - def run(self, cmd): - import __main__ - dict = __main__.__dict__ - self.runctx(cmd, dict, dict) - - def runctx(self, cmd, globals, locals): - self.reset() - sys.settrace(self.trace_dispatch) - try: - try: - exec(cmd + '\n', globals, locals) - except BdbQuit: - pass - finally: - self.quitting = 1 - sys.settrace(None) - - # This method is more useful to debug a single function call. - - def runcall(self, func, *args): - self.reset() - sys.settrace(self.trace_dispatch) - try: - try: - apply(func, args) - except BdbQuit: - pass - finally: - self.quitting = 1 - sys.settrace(None) - - -# -------------------- testing -------------------- - -class Tdb(Bdb): - def user_call(self, frame, args): - import codehack - name = codehack.getcodename(frame.f_code) - if not name: name = '???' - print '+++ call', name, args - def user_line(self, frame): - import linecache, string, codehack - name = codehack.getcodename(frame.f_code) - if not name: name = '???' - fn = frame.f_code.co_filename - line = linecache.getline(fn, frame.f_lineno) - print '+++', fn, frame.f_lineno, name, ':', string.strip(line) - def user_return(self, frame, retval): - print '+++ return', retval - def user_exception(self, frame, exc_stuff): - print '+++ exception', exc_stuff - self.set_continue() - -def foo(n): - print 'foo(', n, ')' - x = bar(n*10) - print 'bar returned', x - -def bar(a): - print 'bar(', a, ')' - return a/2 - -def test(): - import linecache - linecache.checkcache() - t = Tdb() - t.run('import bdb; bdb.foo(10)') diff --git a/Lib/bisect.py b/Lib/bisect.py deleted file mode 100644 index 688666a411..0000000000 --- a/Lib/bisect.py +++ /dev/null @@ -1,23 +0,0 @@ -# Bisection algorithms - - -# Insert item x in list a, and keep it sorted assuming a is sorted - -def insort(a, x): - lo, hi = 0, len(a) - while lo < hi: - mid = (lo+hi)/2 - if x < a[mid]: hi = mid - else: lo = mid+1 - a.insert(lo, x) - - -# Find the index where to insert item x in list a, assuming a is sorted - -def bisect(a, x): - lo, hi = 0, len(a) - while lo < hi: - mid = (lo+hi)/2 - if x < a[mid]: hi = mid - else: lo = mid+1 - return lo diff --git a/Lib/builtin.py b/Lib/builtin.py deleted file mode 100755 index 710d8253a2..0000000000 --- a/Lib/builtin.py +++ /dev/null @@ -1,3 +0,0 @@ -# B/W compat hack so code that says "import builtin" won't break after -# name change from builtin to __builtin__. -from __builtin__ import * diff --git a/Lib/calendar.py b/Lib/calendar.py deleted file mode 100644 index b4e3aaddbf..0000000000 --- a/Lib/calendar.py +++ /dev/null @@ -1,159 +0,0 @@ -############################### -# Calendar printing functions # -############################### - -# Revision 2: uses funtions from built-in time module - -# Import functions and variables from time module -from time import gmtime, localtime, mktime, asctime, ctime -from time import timezone, altzone, daylight, tzname - -# Exception raised for bad input (with string parameter for details) -error = 'calendar.error' - -# Note when comparing these calendars to the ones printed by cal(1): -# My calendars have Monday as the first day of the week, and Sunday as -# the last! (I believe this is the European convention.) - -# Constants for months referenced later -January = 1 -February = 2 - -# Number of days per month (except for February in leap years) -mdays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] - -# Full and abbreviated names of weekdays -day_name = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', \ - 'Friday', 'Saturday', 'Sunday'] -day_abbr = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] - -# Full and abbreviated names of months (1-based arrays!!!) -month_name = ['', 'January', 'February', 'March', 'April', \ - 'May', 'June', 'July', 'August', \ - 'September', 'October', 'November', 'December'] -month_abbr = [' ', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', \ - 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] - -# Return 1 for leap years, 0 for non-leap years -def isleap(year): - return year % 4 == 0 and (year % 100 <> 0 or year % 400 == 0) - -# Return number of leap years in range [y1, y2) -# Assume y1 <= y2 and no funny (non-leap century) years -def leapdays(y1, y2): - return (y2+3)/4 - (y1+3)/4 - -# Return weekday (0-6 ~ Mon-Sun) for year (1970-...), month (1-12), day (1-31) -def weekday(year, month, day): - secs = mktime((year, month, day, 0, 0, 0, 0, 0, 0)) - tuple = localtime(secs) - return tuple[6] - -# Return weekday (0-6 ~ Mon-Sun) and number of days (28-31) for year, month -def monthrange(year, month): - if not 1 <= month <= 12: raise ValueError, 'bad month number' - day1 = weekday(year, month, 1) - ndays = mdays[month] + (month == February and isleap(year)) - return day1, ndays - -# Return a matrix representing a month's calendar -# Each row represents a week; days outside this month are zero -def _monthcalendar(year, month): - day1, ndays = monthrange(year, month) - rows = [] - r7 = range(7) - day = 1 - day1 - while day <= ndays: - row = [0, 0, 0, 0, 0, 0, 0] - for i in r7: - if 1 <= day <= ndays: row[i] = day - day = day + 1 - rows.append(row) - return rows - -# Caching interface to _monthcalendar -_mc_cache = {} -def monthcalendar(year, month): - key = (year, month) - if _mc_cache.has_key(key): - return _mc_cache[key] - else: - _mc_cache[key] = ret = _monthcalendar(year, month) - return ret - -# Center a string in a field -def _center(str, width): - n = width - len(str) - if n <= 0: return str - return ' '*((n+1)/2) + str + ' '*((n)/2) - -# XXX The following code knows that print separates items with space! - -# Print a single week (no newline) -def prweek(week, width): - for day in week: - if day == 0: s = '' - else: s = `day` - print _center(s, width), - -# Return a header for a week -def weekheader(width): - str = '' - if width >= 9: names = day_name - else: names = day_abbr - for i in range(7): - if str: str = str + ' ' - str = str + _center(names[i%7][:width], width) - return str - -# Print a month's calendar -def prmonth(year, month, *rest): - if rest[2:]: raise TypeError, 'too many args' - w = 0 - l = 0 - if rest[0:]: w = rest[0] - if rest[1:]: l = rest[1] - w = max(2, w) - l = max(1, l) - print _center(month_name[month] + ' ' + `year`, 7*(w+1) - 1), - print '\n'*l, - print weekheader(w), - print '\n'*l, - for week in monthcalendar(year, month): - prweek(week, w) - print '\n'*l, - -# Spacing of month columns -_colwidth = 7*3 - 1 # Amount printed by prweek() -_spacing = ' '*4 # Spaces between columns - -# 3-column formatting for year calendars -def format3c(a, b, c): - print _center(a, _colwidth), - print _spacing, - print _center(b, _colwidth), - print _spacing, - print _center(c, _colwidth) - -# Print a year's calendar -def prcal(year): - header = weekheader(2) - format3c('', `year`, '') - for q in range(January, January+12, 3): - print - format3c(month_name[q], month_name[q+1], month_name[q+2]) - format3c(header, header, header) - data = [] - height = 0 - for month in range(q, q+3): - cal = monthcalendar(year, month) - if len(cal) > height: height = len(cal) - data.append(cal) - for i in range(height): - for cal in data: - if i >= len(cal): - print ' '*_colwidth, - else: - prweek(cal[i], 2) - print _spacing, - print diff --git a/Lib/cmd.py b/Lib/cmd.py deleted file mode 100644 index 87ddcfa7e7..0000000000 --- a/Lib/cmd.py +++ /dev/null @@ -1,63 +0,0 @@ -# A generic class to build line-oriented command interpreters - -import string -import sys -import linecache - -PROMPT = '(Cmd) ' -IDENTCHARS = string.letters + string.digits + '_' - -class Cmd: - - def __init__(self): - self.prompt = PROMPT - self.identchars = IDENTCHARS - self.lastcmd = '' - - def cmdloop(self): - stop = None - while not stop: - try: - line = raw_input(self.prompt) - except EOFError: - line = 'EOF' - stop = self.onecmd(line) - - def onecmd(self, line): - line = string.strip(line) - if not line: - line = self.lastcmd - else: - self.lastcmd = line - i, n = 0, len(line) - while i < n and line[i] in self.identchars: i = i+1 - cmd, arg = line[:i], string.strip(line[i:]) - if cmd == '': - return self.default(line) - else: - try: - func = getattr(self, 'do_' + cmd) - except AttributeError: - return self.default(line) - return func(arg) - - def default(self, line): - print '*** Unknown syntax:', line - - def do_help(self, arg): - if arg: - # XXX check arg syntax - try: - func = getattr(self, 'help_' + arg) - except: - print '*** No help on', `arg` - return - func() - else: - import newdir - names = newdir.dir(self.__class__) - cmds = [] - for name in names: - if name[:3] == 'do_': - cmds.append(name[3:]) - print cmds diff --git a/Lib/cmp.py b/Lib/cmp.py deleted file mode 100644 index a73b795f8b..0000000000 --- a/Lib/cmp.py +++ /dev/null @@ -1,61 +0,0 @@ -# Module 'cmp' - -# Efficiently compare files, boolean outcome only (equal / not equal). - -# Tricks (used in this order): -# - Files with identical type, size & mtime are assumed to be clones -# - Files with different type or size cannot be identical -# - We keep a cache of outcomes of earlier comparisons -# - We don't fork a process to run 'cmp' but read the files ourselves - -import os - -cache = {} - -def cmp(f1, f2): # Compare two files, use the cache if possible. - # Return 1 for identical files, 0 for different. - # Raise exceptions if either file could not be statted, read, etc. - s1, s2 = sig(os.stat(f1)), sig(os.stat(f2)) - if s1[0] <> 8 or s2[0] <> 8: - # Either is a not a plain file -- always report as different - return 0 - if s1 == s2: - # type, size & mtime match -- report same - return 1 - if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother - # types or sizes differ -- report different - return 0 - # same type and size -- look in the cache - key = f1 + ' ' + f2 - try: - cs1, cs2, outcome = cache[key] - # cache hit - if s1 == cs1 and s2 == cs2: - # cached signatures match - return outcome - # stale cached signature(s) - except KeyError: - # cache miss - pass - # really compare - outcome = do_cmp(f1, f2) - cache[key] = s1, s2, outcome - return outcome - -def sig(st): # Return signature (i.e., type, size, mtime) from raw stat data - # 0-5: st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid - # 6-9: st_size, st_atime, st_mtime, st_ctime - type = st[0] / 4096 - size = st[6] - mtime = st[8] - return type, size, mtime - -def do_cmp(f1, f2): # Compare two files, really - bufsize = 8096 # Could be tuned - fp1 = open(f1, 'r') - fp2 = open(f2, 'r') - while 1: - b1 = fp1.read(bufsize) - b2 = fp2.read(bufsize) - if b1 <> b2: return 0 - if not b1: return 1 diff --git a/Lib/cmpcache.py b/Lib/cmpcache.py deleted file mode 100644 index d59fa60d02..0000000000 --- a/Lib/cmpcache.py +++ /dev/null @@ -1,68 +0,0 @@ -# Module 'cmpcache' -# -# Efficiently compare files, boolean outcome only (equal / not equal). -# -# Tricks (used in this order): -# - Use the statcache module to avoid statting files more than once -# - Files with identical type, size & mtime are assumed to be clones -# - Files with different type or size cannot be identical -# - We keep a cache of outcomes of earlier comparisons -# - We don't fork a process to run 'cmp' but read the files ourselves - -import os -from stat import * -import statcache - - -# The cache. -# -cache = {} - - -# Compare two files, use the cache if possible. -# May raise os.error if a stat or open of either fails. -# -def cmp(f1, f2): - # Return 1 for identical files, 0 for different. - # Raise exceptions if either file could not be statted, read, etc. - s1, s2 = sig(statcache.stat(f1)), sig(statcache.stat(f2)) - if not S_ISREG(s1[0]) or not S_ISREG(s2[0]): - # Either is a not a plain file -- always report as different - return 0 - if s1 == s2: - # type, size & mtime match -- report same - return 1 - if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother - # types or sizes differ -- report different - return 0 - # same type and size -- look in the cache - key = f1 + ' ' + f2 - if cache.has_key(key): - cs1, cs2, outcome = cache[key] - # cache hit - if s1 == cs1 and s2 == cs2: - # cached signatures match - return outcome - # stale cached signature(s) - # really compare - outcome = do_cmp(f1, f2) - cache[key] = s1, s2, outcome - return outcome - -# Return signature (i.e., type, size, mtime) from raw stat data. -# -def sig(st): - return S_IFMT(st[ST_MODE]), st[ST_SIZE], st[ST_MTIME] - -# Compare two files, really. -# -def do_cmp(f1, f2): - #print ' cmp', f1, f2 # XXX remove when debugged - bufsize = 8096 # Could be tuned - fp1 = open(f1, 'r') - fp2 = open(f2, 'r') - while 1: - b1 = fp1.read(bufsize) - b2 = fp2.read(bufsize) - if b1 <> b2: return 0 - if not b1: return 1 diff --git a/Lib/codehack.py b/Lib/codehack.py deleted file mode 100644 index d00d2bfec9..0000000000 --- a/Lib/codehack.py +++ /dev/null @@ -1,63 +0,0 @@ -# A subroutine for extracting a function name from a code object -# (with cache) - -import sys -from stat import * -import string -import os -import linecache - -# Extract the function or class name from a code object. -# This is a bit of a hack, since a code object doesn't contain -# the name directly. So what do we do: -# - get the filename (which *is* in the code object) -# - look in the code string to find the first SET_LINENO instruction -# (this must be the first instruction) -# - get the line from the file -# - if the line starts with 'class' or 'def' (after possible whitespace), -# extract the following identifier -# -# This breaks apart when the function was read from -# or constructed by exec(), when the file is not accessible, -# and also when the file has been modified or when a line is -# continued with a backslash before the function or class name. -# -# Because this is a pretty expensive hack, a cache is kept. - -SET_LINENO = 127 # The opcode (see "opcode.h" in the Python source) -identchars = string.letters + string.digits + '_' # Identifier characters - -_namecache = {} # The cache - -def getcodename(co): - key = `co` # arbitrary but uniquely identifying string - if _namecache.has_key(key): return _namecache[key] - filename = co.co_filename - code = co.co_code - name = '' - if ord(code[0]) == SET_LINENO: - lineno = ord(code[1]) | ord(code[2]) << 8 - line = linecache.getline(filename, lineno) - words = string.split(line) - if len(words) >= 2 and words[0] in ('def', 'class'): - name = words[1] - for i in range(len(name)): - if name[i] not in identchars: - name = name[:i] - break - _namecache[key] = name - return name - -# Use the above routine to find a function's name. - -def getfuncname(func): - return getcodename(func.func_code) - -# A part of the above code to extract just the line number from a code object. - -def getlineno(co): - code = co.co_code - if ord(code[0]) == SET_LINENO: - return ord(code[1]) | ord(code[2]) << 8 - else: - return -1 diff --git a/Lib/colorsys.py b/Lib/colorsys.py deleted file mode 100644 index c48b2cbc30..0000000000 --- a/Lib/colorsys.py +++ /dev/null @@ -1,119 +0,0 @@ -# Conversion functions between RGB and other color systems. -# -# Define two functions for each color system XYZ: -# rgb_to_xyz(r, g, b) --> x, y, z -# xyz_to_rgb(x, y, z) --> r, g, b -# All inputs and outputs are triples of floats in the range [0.0...1.0]. -# Inputs outside this range may cause exceptions or invalid outputs. -# -# Supported color systems: -# RGB: Red, Green, Blue components -# YIQ: used by composite video signals -# HLS: Hue, Luminance, S??? -# HSV: Hue, Saturation, Value(?) -# -# References: -# XXX Where's the literature? - - -# Some floating point constants - -ONE_THIRD = 1.0/3.0 -ONE_SIXTH = 1.0/6.0 -TWO_THIRD = 2.0/3.0 - - -# YIQ: used by composite video signals (linear combinations of RGB) -# Y: perceived grey level (0.0 == black, 1.0 == white) -# I, Q: color components - -def rgb_to_yiq(r, g, b): - y = 0.30*r + 0.59*g + 0.11*b - i = 0.60*r - 0.28*g - 0.32*b - q = 0.21*r - 0.52*g + 0.31*b - return (y, i, q) - -def yiq_to_rgb(y, i, q): - r = y + 0.948262*i + 0.624013*q - g = y - 0.276066*i - 0.639810*q - b = y - 1.105450*i + 1.729860*q - if r < 0.0: r = 0.0 - if g < 0.0: g = 0.0 - if b < 0.0: b = 0.0 - if r > 1.0: r = 1.0 - if g > 1.0: g = 1.0 - if b > 1.0: b = 1.0 - return (r, g, b) - - -# HLS: Hue, Luminance, S??? -# H: position in the spectrum -# L: ??? -# S: ??? - -def rgb_to_hls(r, g, b): - maxc = max(r, g, b) - minc = min(r, g, b) - # XXX Can optimize (maxc+minc) and (maxc-minc) - l = (minc+maxc)/2.0 - if minc == maxc: return 0.0, l, 0.0 - if l <= 0.5: s = (maxc-minc) / (maxc+minc) - else: s = (maxc-minc) / (2.0-maxc-minc) - rc = (maxc-r) / (maxc-minc) - gc = (maxc-g) / (maxc-minc) - bc = (maxc-b) / (maxc-minc) - if r == maxc: h = bc-gc - elif g == maxc: h = 2.0+rc-bc - else: h = 4.0+gc-rc - h = (h/6.0) % 1.0 - return h, l, s - -def hls_to_rgb(h, l, s): - if s == 0.0: return l, l, l - if l <= 0.5: m2 = l * (1.0+s) - else: m2 = l+s-(l*s) - m1 = 2.0*l - m2 - return (_v(m1, m2, h+ONE_THIRD), _v(m1, m2, h), _v(m1, m2, h-ONE_THIRD)) - -def _v(m1, m2, hue): - hue = hue % 1.0 - if hue < ONE_SIXTH: return m1 + (m2-m1)*hue*6.0 - if hue < 0.5: return m2 - if hue < TWO_THIRD: return m1 + (m2-m1)*(TWO_THIRD-hue)*6.0 - return m1 - - -# HSV: Hue, Saturation, Value(?) -# H: position in the spectrum -# S: ??? -# V: ??? - -def rgb_to_hsv(r, g, b): - maxc = max(r, g, b) - minc = min(r, g, b) - v = maxc - if minc == maxc: return 0.0, 0.0, v - s = (maxc-minc) / maxc - rc = (maxc-r) / (maxc-minc) - gc = (maxc-g) / (maxc-minc) - bc = (maxc-b) / (maxc-minc) - if r == maxc: h = bc-gc - elif g == maxc: h = 2.0+rc-bc - else: h = 4.0+gc-rc - h = (h/6.0) % 1.0 - return h, s, v - -def hsv_to_rgb(h, s, v): - if s == 0.0: return v, v, v - i = int(h*6.0) # XXX assume int() truncates! - f = (h*6.0) - i - p = v*(1.0 - s) - q = v*(1.0 - s*f) - t = v*(1.0 - s*(1.0-f)) - if i%6 == 0: return v, t, p - if i == 1: return q, v, p - if i == 2: return p, v, t - if i == 3: return p, q, v - if i == 4: return t, p, v - if i == 5: return v, p, q - # Cannot get here diff --git a/Lib/commands.py b/Lib/commands.py deleted file mode 100644 index 428a830764..0000000000 --- a/Lib/commands.py +++ /dev/null @@ -1,56 +0,0 @@ -# Module 'commands' -# -# Various tools for executing commands and looking at their output and status. -# -# NB This only works (and is only relevant) for UNIX. - - -# Get 'ls -l' status for an object into a string -# -def getstatus(file): - return getoutput('ls -ld' + mkarg(file)) - - -# Get the output from a shell command into a string. -# The exit status is ignored; a trailing newline is stripped. -# Assume the command will work with '{ ... ; } 2>&1' around it.. -# -def getoutput(cmd): - return getstatusoutput(cmd)[1] - - -# Ditto but preserving the exit status. -# Returns a pair (sts, output) -# -def getstatusoutput(cmd): - import os - pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r') - text = pipe.read() - sts = pipe.close() - if sts == None: sts = 0 - if text[-1:] == '\n': text = text[:-1] - return sts, text - - -# Make command argument from directory and pathname (prefix space, add quotes). -# -def mk2arg(head, x): - import os - return mkarg(os.path.join(head, x)) - - -# Make a shell command argument from a string. -# Two strategies: enclose in single quotes if it contains none; -# otherwise, enclose in double quotes and prefix quotable characters -# with backslash. -# -def mkarg(x): - if '\'' not in x: - return ' \'' + x + '\'' - s = ' "' - for c in x: - if c in '\\$"`': - s = s + '\\' - s = s + c - s = s + '"' - return s diff --git a/Lib/dircache.py b/Lib/dircache.py deleted file mode 100644 index ef68b429f9..0000000000 --- a/Lib/dircache.py +++ /dev/null @@ -1,35 +0,0 @@ -# Module 'dircache' -# -# Return a sorted list of the files in a directory, using a cache -# to avoid reading the directory more often than necessary. -# Also contains a subroutine to append slashes to directories. - -import os - -cache = {} - -def listdir(path): # List directory contents, using cache - try: - cached_mtime, list = cache[path] - del cache[path] - except KeyError: - cached_mtime, list = -1, [] - try: - mtime = os.stat(path)[8] - except os.error: - return [] - if mtime <> cached_mtime: - try: - list = os.listdir(path) - except os.error: - return [] - list.sort() - cache[path] = mtime, list - return list - -opendir = listdir # XXX backward compatibility - -def annotate(head, list): # Add '/' suffixes to directories - for i in range(len(list)): - if os.path.isdir(os.path.join(head, list[i])): - list[i] = list[i] + '/' diff --git a/Lib/dircmp.py b/Lib/dircmp.py deleted file mode 100644 index 1227aa753c..0000000000 --- a/Lib/dircmp.py +++ /dev/null @@ -1,203 +0,0 @@ -# Module 'dirmp' -# -# Defines a class to build directory diff tools on. - -import os - -import dircache -import cmpcache -import statcache -from stat import * - -# Directory comparison class. -# -class dircmp: - # - def new(self, a, b): # Initialize - self.a = a - self.b = b - # Properties that caller may change before calling self.run(): - self.hide = [os.curdir, os.pardir] # Names never to be shown - self.ignore = ['RCS', 'tags'] # Names ignored in comparison - # - return self - # - def run(self): # Compare everything except common subdirectories - self.a_list = filter(dircache.listdir(self.a), self.hide) - self.b_list = filter(dircache.listdir(self.b), self.hide) - self.a_list.sort() - self.b_list.sort() - self.phase1() - self.phase2() - self.phase3() - # - def phase1(self): # Compute common names - self.a_only = [] - self.common = [] - for x in self.a_list: - if x in self.b_list: - self.common.append(x) - else: - self.a_only.append(x) - # - self.b_only = [] - for x in self.b_list: - if x not in self.common: - self.b_only.append(x) - # - def phase2(self): # Distinguish files, directories, funnies - self.common_dirs = [] - self.common_files = [] - self.common_funny = [] - # - for x in self.common: - a_path = os.path.join(self.a, x) - b_path = os.path.join(self.b, x) - # - ok = 1 - try: - a_stat = statcache.stat(a_path) - except os.error, why: - # print 'Can\'t stat', a_path, ':', why[1] - ok = 0 - try: - b_stat = statcache.stat(b_path) - except os.error, why: - # print 'Can\'t stat', b_path, ':', why[1] - ok = 0 - # - if ok: - a_type = S_IFMT(a_stat[ST_MODE]) - b_type = S_IFMT(b_stat[ST_MODE]) - if a_type <> b_type: - self.common_funny.append(x) - elif S_ISDIR(a_type): - self.common_dirs.append(x) - elif S_ISREG(a_type): - self.common_files.append(x) - else: - self.common_funny.append(x) - else: - self.common_funny.append(x) - # - def phase3(self): # Find out differences between common files - xx = cmpfiles(self.a, self.b, self.common_files) - self.same_files, self.diff_files, self.funny_files = xx - # - def phase4(self): # Find out differences between common subdirectories - # A new dircmp object is created for each common subdirectory, - # these are stored in a dictionary indexed by filename. - # The hide and ignore properties are inherited from the parent - self.subdirs = {} - for x in self.common_dirs: - a_x = os.path.join(self.a, x) - b_x = os.path.join(self.b, x) - self.subdirs[x] = newdd = dircmp().new(a_x, b_x) - newdd.hide = self.hide - newdd.ignore = self.ignore - newdd.run() - # - def phase4_closure(self): # Recursively call phase4() on subdirectories - self.phase4() - for x in self.subdirs.keys(): - self.subdirs[x].phase4_closure() - # - def report(self): # Print a report on the differences between a and b - # Assume that phases 1 to 3 have been executed - # Output format is purposely lousy - print 'diff', self.a, self.b - if self.a_only: - print 'Only in', self.a, ':', self.a_only - if self.b_only: - print 'Only in', self.b, ':', self.b_only - if self.same_files: - print 'Identical files :', self.same_files - if self.diff_files: - print 'Differing files :', self.diff_files - if self.funny_files: - print 'Trouble with common files :', self.funny_files - if self.common_dirs: - print 'Common subdirectories :', self.common_dirs - if self.common_funny: - print 'Common funny cases :', self.common_funny - # - def report_closure(self): # Print reports on self and on subdirs - # If phase 4 hasn't been done, no subdir reports are printed - self.report() - try: - x = self.subdirs - except AttributeError: - return # No subdirectories computed - for x in self.subdirs.keys(): - print - self.subdirs[x].report_closure() - # - def report_phase4_closure(self): # Report and do phase 4 recursively - self.report() - self.phase4() - for x in self.subdirs.keys(): - print - self.subdirs[x].report_phase4_closure() - - -# Compare common files in two directories. -# Return: -# - files that compare equal -# - files that compare different -# - funny cases (can't stat etc.) -# -def cmpfiles(a, b, common): - res = ([], [], []) - for x in common: - res[cmp(os.path.join(a, x), os.path.join(b, x))].append(x) - return res - - -# Compare two files. -# Return: -# 0 for equal -# 1 for different -# 2 for funny cases (can't stat, etc.) -# -def cmp(a, b): - try: - if cmpcache.cmp(a, b): return 0 - return 1 - except os.error: - return 2 - - -# Remove a list item. -# NB: This modifies the list argument. -# -def remove(list, item): - for i in range(len(list)): - if list[i] == item: - del list[i] - break - - -# Return a copy with items that occur in skip removed. -# -def filter(list, skip): - result = [] - for item in list: - if item not in skip: result.append(item) - return result - - -# Demonstration and testing. -# -def demo(): - import sys - import getopt - options, args = getopt.getopt(sys.argv[1:], 'r') - if len(args) <> 2: raise getopt.error, 'need exactly two args' - dd = dircmp().new(args[0], args[1]) - dd.run() - if ('-r', '') in options: - dd.report_phase4_closure() - else: - dd.report() - -# demo() diff --git a/Lib/dis.py b/Lib/dis.py deleted file mode 100644 index cd625006c3..0000000000 --- a/Lib/dis.py +++ /dev/null @@ -1,188 +0,0 @@ -# Disassembler - -import sys -import string - -def dis(): - tb = sys.last_traceback - while tb.tb_next: tb = tb.tb_next - distb(tb) - -def distb(tb): - disassemble(tb.tb_frame.f_code, tb.tb_lasti) - -def disco(co): - disassemble(co, -1) - -def disassemble(co, lasti): - code = co.co_code - labels = findlabels(code) - n = len(code) - i = 0 - while i < n: - c = code[i] - op = ord(c) - if op == SET_LINENO and i > 0: print # Extra blank line - if i == lasti: print '-->', - else: print ' ', - if i in labels: print '>>', - else: print ' ', - print string.rjust(`i`, 4), - print string.ljust(opname[op], 15), - i = i+1 - if op >= HAVE_ARGUMENT: - oparg = ord(code[i]) + ord(code[i+1])*256 - i = i+2 - print string.rjust(`oparg`, 5), - if op in hasconst: - print '(' + `co.co_consts[oparg]` + ')', - elif op in hasname: - print '(' + co.co_names[oparg] + ')', - elif op in hasjrel: - print '(to ' + `i + oparg` + ')', - print - -def findlabels(code): - labels = [] - n = len(code) - i = 0 - while i < n: - c = code[i] - op = ord(c) - i = i+1 - if op >= HAVE_ARGUMENT: - oparg = ord(code[i]) + ord(code[i+1])*256 - i = i+2 - label = -1 - if op in hasjrel: - label = i+oparg - elif op in hasjabs: - label = oparg - if label >= 0: - if label not in labels: - labels.append(label) - return labels - -hasconst = [] -hasname = [] -hasjrel = [] -hasjabs = [] - -opname = [''] * 256 -for op in range(256): opname[op] = '<' + `op` + '>' - -def def_op(name, op): - opname[op] = name - -def name_op(name, op): - opname[op] = name - hasname.append(op) - -def jrel_op(name, op): - opname[op] = name - hasjrel.append(op) - -def jabs_op(name, op): - opname[op] = name - hasjabs.append(op) - -# Instruction opcodes for compiled code - -def_op('STOP_CODE', 0) -def_op('POP_TOP', 1) -def_op('ROT_TWO', 2) -def_op('ROT_THREE', 3) -def_op('DUP_TOP', 4) - -def_op('UNARY_POSITIVE', 10) -def_op('UNARY_NEGATIVE', 11) -def_op('UNARY_NOT', 12) -def_op('UNARY_CONVERT', 13) -def_op('UNARY_CALL', 14) -def_op('UNARY_INVERT', 15) - -def_op('BINARY_MULTIPLY', 20) -def_op('BINARY_DIVIDE', 21) -def_op('BINARY_MODULO', 22) -def_op('BINARY_ADD', 23) -def_op('BINARY_SUBTRACT', 24) -def_op('BINARY_SUBSCR', 25) -def_op('BINARY_CALL', 26) - -def_op('SLICE+0', 30) -def_op('SLICE+1', 31) -def_op('SLICE+2', 32) -def_op('SLICE+3', 33) - -def_op('STORE_SLICE+0', 40) -def_op('STORE_SLICE+1', 41) -def_op('STORE_SLICE+2', 42) -def_op('STORE_SLICE+3', 43) - -def_op('DELETE_SLICE+0', 50) -def_op('DELETE_SLICE+1', 51) -def_op('DELETE_SLICE+2', 52) -def_op('DELETE_SLICE+3', 53) - -def_op('STORE_SUBSCR', 60) -def_op('DELETE_SUBSCR', 61) - -def_op('PRINT_EXPR', 70) -def_op('PRINT_ITEM', 71) -def_op('PRINT_NEWLINE', 72) - -def_op('BREAK_LOOP', 80) -def_op('RAISE_EXCEPTION', 81) -def_op('LOAD_LOCALS', 82) -def_op('RETURN_VALUE', 83) - -def_op('BUILD_FUNCTION', 86) -def_op('POP_BLOCK', 87) -def_op('END_FINALLY', 88) -def_op('BUILD_CLASS', 89) - -HAVE_ARGUMENT = 90 # Opcodes from here have an argument: - -name_op('STORE_NAME', 90) # Index in name list -name_op('DELETE_NAME', 91) # "" -def_op('UNPACK_TUPLE', 92) # Number of tuple items -def_op('UNPACK_LIST', 93) # Number of list items -def_op('UNPACK_ARG', 94) # Number of arguments expected -name_op('STORE_ATTR', 95) # Index in name list -name_op('DELETE_ATTR', 96) # "" -name_op('STORE_GLOBAL', 97) # "" -name_op('DELETE_GLOBAL', 98) # "" -name_op('UNPACK_VARARG', 99) # Minimal number of arguments - -def_op('LOAD_CONST', 100) # Index in const list -hasconst.append(100) -name_op('LOAD_NAME', 101) # Index in name list -def_op('BUILD_TUPLE', 102) # Number of tuple items -def_op('BUILD_LIST', 103) # Number of list items -def_op('BUILD_MAP', 104) # Always zero for now -name_op('LOAD_ATTR', 105) # Index in name list -def_op('COMPARE_OP', 106) # Comparison operator -name_op('IMPORT_NAME', 107) # Index in name list -name_op('IMPORT_FROM', 108) # Index in name list - -jrel_op('JUMP_FORWARD', 110) # Number of bytes to skip -jrel_op('JUMP_IF_FALSE', 111) # "" -jrel_op('JUMP_IF_TRUE', 112) # "" -jabs_op('JUMP_ABSOLUTE', 113) # Target byte offset from beginning of code -jrel_op('FOR_LOOP', 114) # Number of bytes to skip - -name_op('LOAD_LOCAL', 115) # Index in name list -name_op('LOAD_GLOBAL', 116) # Index in name list - -jrel_op('SETUP_LOOP', 120) # Distance to target address -jrel_op('SETUP_EXCEPT', 121) # "" -jrel_op('SETUP_FINALLY', 122) # "" - -def_op('RESERVE_FAST', 123) # Number of local variables -hasconst.append(123) -def_op('LOAD_FAST', 124) # Local variable number -def_op('STORE_FAST', 125) # Local variable number -def_op('DELETE_FAST', 126) # Local variable number - -def_op('SET_LINENO', 127) # Current line number -SET_LINENO = 127 diff --git a/Lib/dump.py b/Lib/dump.py deleted file mode 100644 index ec895b7e07..0000000000 --- a/Lib/dump.py +++ /dev/null @@ -1,63 +0,0 @@ -# Module 'dump' -# -# Print python code that reconstructs a variable. -# This only works in certain cases. -# -# It works fine for: -# - ints and floats (except NaNs and other weird things) -# - strings -# - compounds and lists, provided it works for all their elements -# - imported modules, provided their name is the module name -# -# It works for top-level dictionaries but not for dictionaries -# contained in other objects (could be made to work with some hassle -# though). -# -# It does not work for functions (all sorts), classes, class objects, -# windows, files etc. -# -# Finally, objects referenced by more than one name or contained in more -# than one other object lose their sharing property (this is bad for -# strings used as exception identifiers, for instance). - -# Dump a whole symbol table -# -def dumpsymtab(dict): - for key in dict.keys(): - dumpvar(key, dict[key]) - -# Dump a single variable -# -def dumpvar(name, x): - import sys - t = type(x) - if t == type({}): - print name, '= {}' - for key in x.keys(): - item = x[key] - if not printable(item): - print '#', - print name, '[', `key`, '] =', `item` - elif t in (type(''), type(0), type(0.0), type([]), type(())): - if not printable(x): - print '#', - print name, '=', `x` - elif t == type(sys): - print 'import', name, '#', x - else: - print '#', name, '=', x - -# check if a value is printable in a way that can be read back with input() -# -def printable(x): - t = type(x) - if t in (type(''), type(0), type(0.0)): - return 1 - if t in (type([]), type(())): - for item in x: - if not printable(item): - return 0 - return 1 - if x == {}: - return 1 - return 0 diff --git a/Lib/emacs.py b/Lib/emacs.py deleted file mode 100644 index ffce099ac3..0000000000 --- a/Lib/emacs.py +++ /dev/null @@ -1,18 +0,0 @@ -# Execute Emacs code from a Python interpreter. -# This code should be imported from a Python interpreter that is -# running as an inferior process of Emacs. -# See misc/py-connect.el for the companion Emacs lisp code. -# Author: Terrence M. Brannon. - -start_marker = '+' -end_marker = '~' - -def eval (string): - tmpstr = start_marker + '(' + string + ')' + end_marker - print tmpstr - -def dired (directory): - eval( 'dired ' + '"' + directory + '"' ) - -def buffer_menu (): - eval( 'buffer-menu(buffer-list)' ) diff --git a/Lib/fnmatch.py b/Lib/fnmatch.py deleted file mode 100644 index 5c1bc711c1..0000000000 --- a/Lib/fnmatch.py +++ /dev/null @@ -1,56 +0,0 @@ -# module 'fnmatch' -- filename matching with shell patterns -# This version translates the pattern to a regular expression -# and moreover caches the expressions. - -import os -import regex - -cache = {} - -def fnmatch(name, pat): - name = os.path.normcase(name) - pat = os.path.normcase(pat) - if not cache.has_key(pat): - res = translate(pat) - save_syntax = regex.set_syntax(0) - cache[pat] = regex.compile(res) - save_syntax = regex.set_syntax(save_syntax) - return cache[pat].match(name) == len(name) - -def translate(pat): - i, n = 0, len(pat) - res = '' - while i < n: - c = pat[i] - i = i+1 - if c == '*': - res = res + '.*' - elif c == '?': - res = res + '.' - elif c == '[': - j = i - if j < n and pat[j] == '!': - j = j+1 - if j < n and pat[j] == ']': - j = j+1 - while j < n and pat[j] != ']': - j = j+1 - if j >= n: - res = res + '\\[' - else: - stuff = pat[i:j] - i = j+1 - if stuff[0] == '!': - stuff = '[^' + stuff[1:] + ']' - elif stuff == '^'*len(stuff): - stuff = '\\^' - else: - while stuff[0] == '^': - stuff = stuff[1:] + stuff[0] - stuff = '[' + stuff + ']' - res = res + stuff - elif c in '\\.+^$': - res = res + ('\\' + c) - else: - res = res + c - return res diff --git a/Lib/fpformat.py b/Lib/fpformat.py deleted file mode 100644 index 457457595c..0000000000 --- a/Lib/fpformat.py +++ /dev/null @@ -1,138 +0,0 @@ -# General floating point formatting functions. - -# Functions: -# fix(x, digits_behind) -# sci(x, digits_behind) - -# Each takes a number or a string and a number of digits as arguments. - -# Parameters: -# x: number to be formatted; or a string resembling a number -# digits_behind: number of digits behind the decimal point - - -import regex - -# Compiled regular expression to "decode" a number -decoder = regex.compile( \ - '^\([-+]?\)0*\([0-9]*\)\(\(\.[0-9]*\)?\)\(\([eE][-+]?[0-9]+\)?\)$') -# \0 the whole thing -# \1 leading sign or empty -# \2 digits left of decimal point -# \3 fraction (empty or begins with point) -# \5 exponent part (empty or begins with 'e' or 'E') - -NotANumber = 'fpformat.NotANumber' - -# Return (sign, intpart, fraction, expo) or raise an exception: -# sign is '+' or '-' -# intpart is 0 or more digits beginning with a nonzero -# fraction is 0 or more digits -# expo is an integer -def extract(s): - if decoder.match(s) < 0: raise NotANumber - (a1, b1), (a2, b2), (a3, b3), (a4, b4), (a5, b5) = decoder.regs[1:6] - sign, intpart, fraction, exppart = \ - s[a1:b1], s[a2:b2], s[a3:b3], s[a5:b5] - if sign == '+': sign = '' - if fraction: fraction = fraction[1:] - if exppart: expo = eval(exppart[1:]) - else: expo = 0 - return sign, intpart, fraction, expo - -# Remove the exponent by changing intpart and fraction -def unexpo(intpart, fraction, expo): - if expo > 0: # Move the point left - f = len(fraction) - intpart, fraction = intpart + fraction[:expo], fraction[expo:] - if expo > f: - intpart = intpart + '0'*(expo-f) - elif expo < 0: # Move the point right - i = len(intpart) - intpart, fraction = intpart[:expo], intpart[expo:] + fraction - if expo < -i: - fraction = '0'*(-expo-i) + fraction - return intpart, fraction - -# Round or extend the fraction to size digs -def roundfrac(intpart, fraction, digs): - f = len(fraction) - if f <= digs: - return intpart, fraction + '0'*(digs-f) - i = len(intpart) - if i+digs < 0: - return '0'*-digs, '' - total = intpart + fraction - nextdigit = total[i+digs] - if nextdigit >= '5': # Hard case: increment last digit, may have carry! - n = i + digs - 1 - while n >= 0: - if total[n] != '9': break - n = n-1 - else: - total = '0' + total - i = i+1 - n = 0 - total = total[:n] + chr(ord(total[n]) + 1) + '0'*(len(total)-n-1) - intpart, fraction = total[:i], total[i:] - if digs >= 0: - return intpart, fraction[:digs] - else: - return intpart[:digs] + '0'*-digs, '' - -# Format x as [-]ddd.ddd with 'digs' digits after the point -# and at least one digit before. -# If digs <= 0, the point is suppressed. -def fix(x, digs): - if type(x) != type(''): x = `x` - try: - sign, intpart, fraction, expo = extract(x) - except NotANumber: - return x - intpart, fraction = unexpo(intpart, fraction, expo) - intpart, fraction = roundfrac(intpart, fraction, digs) - while intpart and intpart[0] == '0': intpart = intpart[1:] - if intpart == '': intpart = '0' - if digs > 0: return sign + intpart + '.' + fraction - else: return sign + intpart - -# Format x as [-]d.dddE[+-]ddd with 'digs' digits after the point -# and exactly one digit before. -# If digs is <= 0, one digit is kept and the point is suppressed. -def sci(x, digs): - if type(x) != type(''): x = `x` - sign, intpart, fraction, expo = extract(x) - if not intpart: - while fraction and fraction[0] == '0': - fraction = fraction[1:] - expo = expo - 1 - if fraction: - intpart, fraction = fraction[0], fraction[1:] - expo = expo - 1 - else: - intpart = '0' - else: - expo = expo + len(intpart) - 1 - intpart, fraction = intpart[0], intpart[1:] + fraction - digs = max(0, digs) - intpart, fraction = roundfrac(intpart, fraction, digs) - if len(intpart) > 1: - intpart, fraction, expo = \ - intpart[0], intpart[1:] + fraction[:-1], \ - expo + len(intpart) - 1 - s = sign + intpart - if digs > 0: s = s + '.' + fraction - e = `abs(expo)` - e = '0'*(3-len(e)) + e - if expo < 0: e = '-' + e - else: e = '+' + e - return s + 'e' + e - -# Interactive test run -def test(): - try: - while 1: - x, digs = input('Enter (x, digs): ') - print x, fix(x, digs), sci(x, digs) - except (EOFError, KeyboardInterrupt): - pass diff --git a/Lib/ftplib.py b/Lib/ftplib.py deleted file mode 100644 index c441f1f739..0000000000 --- a/Lib/ftplib.py +++ /dev/null @@ -1,452 +0,0 @@ -# An FTP client class. Based on RFC 959: File Transfer Protocol -# (FTP), by J. Postel and J. Reynolds - -# Changes and improvements suggested by Steve Majewski - - -# Example: -# -# >>> from ftplib import FTP -# >>> ftp = FTP('ftp.cwi.nl') # connect to host, default port -# >>> ftp.login() # default, i.e.: user anonymous, passwd user@hostname -# >>> def handle_one_line(line): # callback for ftp.retrlines -# ... print line -# ... -# >>> ftp.retrlines('LIST', handle_one_line) # list directory contents -# total 43 -# d--x--x--x 2 root root 512 Jul 1 16:50 bin -# d--x--x--x 2 root root 512 Sep 16 1991 etc -# drwxr-xr-x 2 root ftp 10752 Sep 16 1991 lost+found -# drwxr-srwt 15 root ftp 10240 Nov 5 20:43 pub -# >>> ftp.quit() -# -# To download a file, use ftp.retrlines('RETR ' + filename, handle_one_line), -# or ftp.retrbinary() with slightly different arguments. -# To upload a file, use ftp.storlines() or ftp.storbinary(), which have -# an open file as argument. -# The download/upload functions first issue appropriate TYPE and PORT -# commands. - - -import os -import sys -import socket -import string - - -# Magic number from -MSG_OOB = 0x1 # Process data out of band - - -# The standard FTP server control port -FTP_PORT = 21 - - -# Exception raised when an error or invalid response is received -error_reply = 'ftplib.error_reply' # unexpected [123]xx reply -error_temp = 'ftplib.error_temp' # 4xx errors -error_perm = 'ftplib.error_perm' # 5xx errors -error_proto = 'ftplib.error_proto' # response does not begin with [1-5] - - -# All exceptions (hopefully) that may be raised here and that aren't -# (always) programming errors on our side -all_errors = (error_reply, error_temp, error_perm, error_proto, \ - socket.error, IOError) - - -# Line terminators (we always output CRLF, but accept any of CRLF, CR, LF) -CRLF = '\r\n' - - -# Next port to be used by makeport(), with PORT_OFFSET added -# (This is now only used when the python interpreter doesn't support -# the getsockname() method yet) -nextport = 0 -PORT_OFFSET = 40000 -PORT_CYCLE = 1000 - - -# The class itself -class FTP: - - # New initialization method (called by class instantiation) - # Initialize host to localhost, port to standard ftp port - # Optional arguments are host (for connect()), - # and user, passwd, acct (for login()) - def __init__(self, *args): - # Initialize the instance to something mostly harmless - self.debugging = 0 - self.host = '' - self.port = FTP_PORT - self.sock = None - self.file = None - self.welcome = None - if args: - self.connect(args[0]) - if args[1:]: - apply(self.login, args[1:]) - - # Connect to host. Arguments: - # - host: hostname to connect to (default previous host) - # - port: port to connect to (default previous port) - def connect(self, *args): - if args: self.host = args[0] - if args[1:]: self.port = args[1] - if args[2:]: raise TypeError, 'too many args' - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.sock.connect(self.host, self.port) - self.file = self.sock.makefile('r') - self.welcome = self.getresp() - - # Get the welcome message from the server - # (this is read and squirreled away by connect()) - def getwelcome(self): - if self.debugging: print '*welcome*', `self.welcome` - return self.welcome - - # Set the debugging level. Argument level means: - # 0: no debugging output (default) - # 1: print commands and responses but not body text etc. - # 2: also print raw lines read and sent before stripping CR/LF - def set_debuglevel(self, level): - self.debugging = level - debug = set_debuglevel - - # Internal: send one line to the server, appending CRLF - def putline(self, line): - line = line + CRLF - if self.debugging > 1: print '*put*', `line` - self.sock.send(line) - - # Internal: send one command to the server (through putline()) - def putcmd(self, line): - if self.debugging: print '*cmd*', `line` - self.putline(line) - - # Internal: return one line from the server, stripping CRLF. - # Raise EOFError if the connection is closed - def getline(self): - line = self.file.readline() - if self.debugging > 1: - print '*get*', `line` - if not line: raise EOFError - if line[-2:] == CRLF: line = line[:-2] - elif line[-1:] in CRLF: line = line[:-1] - return line - - # Internal: get a response from the server, which may possibly - # consist of multiple lines. Return a single string with no - # trailing CRLF. If the response consists of multiple lines, - # these are separated by '\n' characters in the string - def getmultiline(self): - line = self.getline() - if line[3:4] == '-': - code = line[:3] - while 1: - nextline = self.getline() - line = line + ('\n' + nextline) - if nextline[:3] == code and \ - nextline[3:4] <> '-': - break - return line - - # Internal: get a response from the server. - # Raise various errors if the response indicates an error - def getresp(self): - resp = self.getmultiline() - if self.debugging: print '*resp*', `resp` - self.lastresp = resp[:3] - c = resp[:1] - if c == '4': - raise error_temp, resp - if c == '5': - raise error_perm, resp - if c not in '123': - raise error_proto, resp - return resp - - # Expect a response beginning with '2' - def voidresp(self): - resp = self.getresp() - if resp[0] <> '2': - raise error_reply, resp - - # Abort a file transfer. Uses out-of-band data. - # This does not follow the procedure from the RFC to send Telnet - # IP and Synch; that doesn't seem to work with the servers I've - # tried. Instead, just send the ABOR command as OOB data. - def abort(self): - line = 'ABOR' + CRLF - if self.debugging > 1: print '*put urgent*', `line` - self.sock.send(line, MSG_OOB) - resp = self.getmultiline() - if resp[:3] not in ('426', '226'): - raise error_proto, resp - - # Send a command and return the response - def sendcmd(self, cmd): - self.putcmd(cmd) - return self.getresp() - - # Send a command and expect a response beginning with '2' - def voidcmd(self, cmd): - self.putcmd(cmd) - self.voidresp() - - # Send a PORT command with the current host and the given port number - def sendport(self, port): - hostname = socket.gethostname() - hostaddr = socket.gethostbyname(hostname) - hbytes = string.splitfields(hostaddr, '.') - pbytes = [`port/256`, `port%256`] - bytes = hbytes + pbytes - cmd = 'PORT ' + string.joinfields(bytes, ',') - self.voidcmd(cmd) - - # Create a new socket and send a PORT command for it - def makeport(self): - global nextport - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - try: - getsockname = sock.getsockname - except AttributeError: - if self.debugging > 1: - print '*** getsockname not supported', - print '-- using manual port assignment ***' - port = nextport + PORT_OFFSET - nextport = (nextport + 1) % PORT_CYCLE - sock.bind('', port) - getsockname = None - sock.listen(0) # Assigns the port if not explicitly bound - if getsockname: - host, port = getsockname() - resp = self.sendport(port) - return sock - - # Send a port command and a transfer command, accept the connection - # and return the socket for the connection - def transfercmd(self, cmd): - sock = self.makeport() - resp = self.sendcmd(cmd) - if resp[0] <> '1': - raise error_reply, resp - conn, sockaddr = sock.accept() - return conn - - # Login, default anonymous - def login(self, *args): - user = passwd = acct = '' - n = len(args) - if n > 3: raise TypeError, 'too many arguments' - if n > 0: user = args[0] - if n > 1: passwd = args[1] - if n > 2: acct = args[2] - if not user: user = 'anonymous' - if user == 'anonymous' and passwd in ('', '-'): - thishost = socket.gethostname() - if os.environ.has_key('LOGNAME'): - realuser = os.environ['LOGNAME'] - elif os.environ.has_key('USER'): - realuser = os.environ['USER'] - else: - realuser = 'anonymous' - passwd = passwd + realuser + '@' + thishost - resp = self.sendcmd('USER ' + user) - if resp[0] == '3': resp = self.sendcmd('PASS ' + passwd) - if resp[0] == '3': resp = self.sendcmd('ACCT ' + acct) - if resp[0] <> '2': - raise error_reply, resp - - # Retrieve data in binary mode. - # The argument is a RETR command. - # The callback function is called for each block. - # This creates a new port for you - def retrbinary(self, cmd, callback, blocksize): - self.voidcmd('TYPE I') - conn = self.transfercmd(cmd) - while 1: - data = conn.recv(blocksize) - if not data: - break - callback(data) - conn.close() - self.voidresp() - - # Retrieve data in line mode. - # The argument is a RETR or LIST command. - # The callback function is called for each line, with trailing - # CRLF stripped. This creates a new port for you. - # print_lines is the default callback - def retrlines(self, cmd, *args): - callback = None - if args: - callback = args[0] - if args[1:]: raise TypeError, 'too many args' - if not callback: callback = print_line - resp = self.sendcmd('TYPE A') - conn = self.transfercmd(cmd) - fp = conn.makefile('r') - while 1: - line = fp.readline() - if not line: - break - if line[-2:] == CRLF: - line = line[:-2] - elif line[:-1] == '\n': - line = line[:-1] - callback(line) - fp.close() - conn.close() - self.voidresp() - - # Store a file in binary mode - def storbinary(self, cmd, fp, blocksize): - self.voidcmd('TYPE I') - conn = self.transfercmd(cmd) - while 1: - buf = fp.read(blocksize) - if not buf: break - conn.send(buf) - conn.close() - self.voidresp() - - # Store a file in line mode - def storlines(self, cmd, fp): - self.voidcmd('TYPE A') - conn = self.transfercmd(cmd) - while 1: - buf = fp.readline() - if not buf: break - if buf[-2:] <> CRLF: - if buf[-1] in CRLF: buf = buf[:-1] - buf = buf + CRLF - conn.send(buf) - conn.close() - self.voidresp() - - # Return a list of files in a given directory (default the current) - def nlst(self, *args): - cmd = 'NLST' - for arg in args: - cmd = cmd + (' ' + arg) - files = [] - self.retrlines(cmd, files.append) - return files - - # List a directory in long form. By default list current directory - # to stdout. Optional last argument is callback function; - # all non-empty arguments before it are concatenated to the - # LIST command. (This *should* only be used for a pathname.) - def dir(self, *args): - cmd = 'LIST' - func = None - if args[-1:] and type(args[-1]) != type(''): - args, func = args[:-1], args[-1] - for arg in args: - if arg: - cmd = cmd + (' ' + arg) - self.retrlines(cmd, func) - - # Rename a file - def rename(self, fromname, toname): - resp = self.sendcmd('RNFR ' + fromname) - if resp[0] <> '3': - raise error_reply, resp - self.voidcmd('RNTO ' + toname) - - # Change to a directory - def cwd(self, dirname): - if dirname == '..': - try: - self.voidcmd('CDUP') - return - except error_perm, msg: - if msg[:3] != '500': - raise error_perm, msg - cmd = 'CWD ' + dirname - self.voidcmd(cmd) - - # Retrieve the size of a file - def size(self, filename): - resp = self.sendcmd('SIZE ' + filename) - if resp[:3] == '213': - return string.atoi(string.strip(resp[3:])) - - # Make a directory, return its full pathname - def mkd(self, dirname): - resp = self.sendcmd('MKD ' + dirname) - return parse257(resp) - - # Return current wording directory - def pwd(self): - resp = self.sendcmd('PWD') - return parse257(resp) - - # Quit, and close the connection - def quit(self): - self.voidcmd('QUIT') - self.close() - - # Close the connection without assuming anything about it - def close(self): - self.file.close() - self.sock.close() - del self.file, self.sock - - -# Parse a response type 257 -def parse257(resp): - if resp[:3] <> '257': - raise error_reply, resp - if resp[3:5] <> ' "': - return '' # Not compliant to RFC 959, but UNIX ftpd does this - dirname = '' - i = 5 - n = len(resp) - while i < n: - c = resp[i] - i = i+1 - if c == '"': - if i >= n or resp[i] <> '"': - break - i = i+1 - dirname = dirname + c - return dirname - -# Default retrlines callback to print a line -def print_line(line): - print line - - -# Test program. -# Usage: ftp [-d] host [-l[dir]] [-d[dir]] [file] ... -def test(): - import marshal - global nextport - try: - nextport = marshal.load(open('.@nextport', 'r')) - except IOError: - pass - try: - debugging = 0 - while sys.argv[1] == '-d': - debugging = debugging+1 - del sys.argv[1] - host = sys.argv[1] - ftp = FTP(host) - ftp.set_debuglevel(debugging) - ftp.login() - for file in sys.argv[2:]: - if file[:2] == '-l': - ftp.dir(file[2:]) - elif file[:2] == '-d': - cmd = 'CWD' - if file[2:]: cmd = cmd + ' ' + file[2:] - resp = ftp.sendcmd(cmd) - else: - ftp.retrbinary('RETR ' + file, \ - sys.stdout.write, 1024) - ftp.quit() - finally: - marshal.dump(nextport, open('.@nextport', 'w')) diff --git a/Lib/getopt.py b/Lib/getopt.py deleted file mode 100644 index 7feaf9d525..0000000000 --- a/Lib/getopt.py +++ /dev/null @@ -1,47 +0,0 @@ -# module getopt -- Standard command line processing. - -# Function getopt.getopt() has a different interface but provides the -# same functionality as the Unix getopt() function. - -# It has two arguments: the first should be argv[1:] (it doesn't want -# the script name), the second the string of option letters as passed -# to Unix getopt() (i.e., a string of allowable option letters, with -# options requiring an argument followed by a colon). - -# It raises the exception getopt.error with a string argument if it -# detects an error. - -# It returns two items: -# (1) a list of pairs (option, option_argument) giving the options in -# the order in which they were specified. (I'd use a dictionary -# but applications may depend on option order or multiple -# occurrences.) Boolean options have '' as option_argument. -# (2) the list of remaining arguments (may be empty). - -error = 'getopt error' - -def getopt(args, options): - list = [] - while args and args[0][:1] == '-' and args[0] <> '-': - if args[0] == '--': - args = args[1:] - break - optstring, args = args[0][1:], args[1:] - while optstring <> '': - opt, optstring = optstring[0], optstring[1:] - if classify(opt, options): # May raise exception as well - if optstring == '': - if not args: - raise error, 'option -' + opt + ' requires argument' - optstring, args = args[0], args[1:] - optarg, optstring = optstring, '' - else: - optarg = '' - list.append('-' + opt, optarg) - return list, args - -def classify(opt, options): # Helper to check type of option - for i in range(len(options)): - if opt == options[i] <> ':': - return options[i+1:i+2] == ':' - raise error, 'option -' + opt + ' not recognized' diff --git a/Lib/glob.py b/Lib/glob.py deleted file mode 100644 index bacaf183e1..0000000000 --- a/Lib/glob.py +++ /dev/null @@ -1,51 +0,0 @@ -# Module 'glob' -- filename globbing. - -import os -import fnmatch -import regex - - -def glob(pathname): - if not has_magic(pathname): - if os.path.exists(pathname): - return [pathname] - else: - return [] - dirname, basename = os.path.split(pathname) - if has_magic(dirname): - list = glob(dirname) - else: - list = [dirname] - if not has_magic(basename): - result = [] - for dirname in list: - if basename or os.path.isdir(dirname): - name = os.path.join(dirname, basename) - if os.path.exists(name): - result.append(name) - else: - result = [] - for dirname in list: - sublist = glob1(dirname, basename) - for name in sublist: - result.append(os.path.join(dirname, name)) - return result - -def glob1(dirname, pattern): - if not dirname: dirname = os.curdir - try: - names = os.listdir(dirname) - except os.error: - return [] - result = [] - for name in names: - if name[0] != '.' or pattern[0] == '.': - if fnmatch.fnmatch(name, pattern): - result.append(name) - return result - - -magic_check = regex.compile('[*?[]') - -def has_magic(s): - return magic_check.search(s) >= 0 diff --git a/Lib/grep.py b/Lib/grep.py deleted file mode 100644 index f4666512b7..0000000000 --- a/Lib/grep.py +++ /dev/null @@ -1,62 +0,0 @@ -# 'grep' - -import regex -from regex_syntax import * -import string - -opt_show_where = 0 -opt_show_filename = 0 -opt_show_lineno = 1 - -def grep(pat, *files): - return ggrep(RE_SYNTAX_GREP, pat, files) - -def egrep(pat, *files): - return ggrep(RE_SYNTAX_EGREP, pat, files) - -def emgrep(pat, *files): - return ggrep(RE_SYNTAX_EMACS, pat, files) - -def ggrep(syntax, pat, files): - if len(files) == 1 and type(files[0]) == type([]): - files = files[0] - global opt_show_filename - opt_show_filename = (len(files) != 1) - syntax = regex.set_syntax(syntax) - try: - prog = regex.compile(pat) - finally: - syntax = regex.set_syntax(syntax) - for filename in files: - fp = open(filename, 'r') - lineno = 0 - while 1: - line = fp.readline() - if not line: break - lineno = lineno + 1 - if prog.search(line) >= 0: - showline(filename, lineno, line, prog) - fp.close() - -def showline(filename, lineno, line, prog): - if line[-1:] == '\n': line = line[:-1] - if opt_show_lineno: - prefix = string.rjust(`lineno`, 3) + ': ' - else: - prefix = '' - if opt_show_filename: - prefix = filename + ': ' + prefix - print prefix + line - if opt_show_where: - start, end = prog.regs()[0] - line = line[:start] - if '\t' not in line: - prefix = ' ' * (len(prefix) + start) - else: - prefix = ' ' * len(prefix) - for c in line: - if c <> '\t': c = ' ' - prefix = prefix + c - if start == end: prefix = prefix + '\\' - else: prefix = prefix + '^'*(end-start) - print prefix diff --git a/Lib/imghdr.py b/Lib/imghdr.py deleted file mode 100644 index 62518b5f36..0000000000 --- a/Lib/imghdr.py +++ /dev/null @@ -1,129 +0,0 @@ -# Recognizing image files based on their first few bytes. - - -#-------------------------# -# Recognize sound headers # -#-------------------------# - -def what(filename): - f = open(filename, 'r') - h = f.read(32) - for tf in tests: - res = tf(h, f) - if res: - return res - return None - - -#---------------------------------# -# Subroutines per image file type # -#---------------------------------# - -tests = [] - -def test_rgb(h, f): - # SGI image library - if h[:2] == '\001\332': - return 'rgb' - -tests.append(test_rgb) - -def test_gif(h, f): - # GIF ('87 and '89 variants) - if h[:6] in ('GIF87a', 'GIF89a'): - return 'gif' - -tests.append(test_gif) - -def test_pbm(h, f): - # PBM (portable bitmap) - if len(h) >= 3 and \ - h[0] == 'P' and h[1] in '14' and h[2] in ' \t\n\r': - return 'pbm' - -tests.append(test_pbm) - -def test_pgm(h, f): - # PGM (portable graymap) - if len(h) >= 3 and \ - h[0] == 'P' and h[1] in '25' and h[2] in ' \t\n\r': - return 'pgm' - -tests.append(test_pgm) - -def test_ppm(h, f): - # PPM (portable pixmap) - if len(h) >= 3 and \ - h[0] == 'P' and h[1] in '36' and h[2] in ' \t\n\r': - return 'ppm' - -tests.append(test_ppm) - -def test_tiff(h, f): - # TIFF (can be in Motorola or Intel byte order) - if h[:2] in ('MM', 'II'): - return 'tiff' - -tests.append(test_tiff) - -def test_rast(h, f): - # Sun raster file - if h[:4] == '\x59\xA6\x6A\x95': - return 'rast' - -tests.append(test_rast) - -def test_xbm(h, f): - # X bitmap (X10 or X11) - s = '#define ' - if h[:len(s)] == s: - return 'xbm' - -tests.append(test_xbm) - -def test_jpeg(h, f): - # JPEG data in JFIF format - if h[6:10] == 'JFIF': - return 'jpeg' - -tests.append(test_jpeg) - -#--------------------# -# Small test program # -#--------------------# - -def test(): - import sys - recursive = 0 - if sys.argv[1:] and sys.argv[1] == '-r': - del sys.argv[1:2] - recursive = 1 - try: - if sys.argv[1:]: - testall(sys.argv[1:], recursive, 1) - else: - testall(['.'], recursive, 1) - except KeyboardInterrupt: - sys.stderr.write('\n[Interrupted]\n') - sys.exit(1) - -def testall(list, recursive, toplevel): - import sys - import os - for filename in list: - if os.path.isdir(filename): - print filename + '/:', - if recursive or toplevel: - print 'recursing down:' - import glob - names = glob.glob(os.path.join(filename, '*')) - testall(names, recursive, 0) - else: - print '*** directory (use -r) ***' - else: - print filename + ':', - sys.stdout.flush() - try: - print what(filename) - except IOError: - print '*** not found ***' diff --git a/Lib/importall.py b/Lib/importall.py deleted file mode 100755 index 1d20377105..0000000000 --- a/Lib/importall.py +++ /dev/null @@ -1,34 +0,0 @@ -# Utility module to import all modules in the path, in the hope -# that this will update their ".pyc" files. - -import os -import sys - -# Sabotage 'gl' and 'stdwin' to prevent windows popping up... -for m in 'gl', 'stdwin', 'fl', 'fm': - sys.modules[m] = sys - -exceptions = ['importall'] - -for dir in sys.path: - print 'Listing', dir - try: - names = os.listdir(dir) - except os.error: - print 'Can\'t list', dir - names = [] - names.sort() - for name in names: - head, tail = name[:-3], name[-3:] - if tail == '.py' and head not in exceptions: - s = 'import ' + head - print s - try: - exec(s + '\n') - except KeyboardInterrupt: - del names[:] - print '\n[interrupt]' - break - except: - print 'Sorry:', sys.exc_type + ':', - print sys.exc_value diff --git a/Lib/irix5/AL.py b/Lib/irix5/AL.py deleted file mode 100755 index c4497ab4a8..0000000000 --- a/Lib/irix5/AL.py +++ /dev/null @@ -1,60 +0,0 @@ -RATE_48000 = 48000 -RATE_44100 = 44100 -RATE_32000 = 32000 -RATE_22050 = 22050 -RATE_16000 = 16000 -RATE_11025 = 11025 -RATE_8000 = 8000 - -SAMPFMT_TWOSCOMP= 1 -SAMPFMT_FLOAT = 32 -SAMPFMT_DOUBLE = 64 - -SAMPLE_8 = 1 -SAMPLE_16 = 2 - # SAMPLE_24 is the low 24 bits of a long, sign extended to 32 bits -SAMPLE_24 = 4 - -MONO = 1 -STEREO = 2 - -INPUT_LINE = 0 -INPUT_MIC = 1 -INPUT_DIGITAL = 2 - -MONITOR_OFF = 0 -MONITOR_ON = 1 - -ERROR_NUMBER = 0 -ERROR_TYPE = 1 -ERROR_LOCATION_LSP = 2 -ERROR_LOCATION_MSP = 3 -ERROR_LENGTH = 4 - -ERROR_INPUT_UNDERFLOW = 0 -ERROR_OUTPUT_OVERFLOW = 1 - -# These seem to be not supported anymore: -##HOLD, RELEASE = 0, 1 -##ATTAIL, ATHEAD, ATMARK, ATTIME = 0, 1, 2, 3 - -DEFAULT_DEVICE = 1 - -INPUT_SOURCE = 0 -LEFT_INPUT_ATTEN = 1 -RIGHT_INPUT_ATTEN = 2 -INPUT_RATE = 3 -OUTPUT_RATE = 4 -LEFT_SPEAKER_GAIN = 5 -RIGHT_SPEAKER_GAIN = 6 -INPUT_COUNT = 7 -OUTPUT_COUNT = 8 -UNUSED_COUNT = 9 -SYNC_INPUT_TO_AES = 10 -SYNC_OUTPUT_TO_AES = 11 -MONITOR_CTL = 12 -LEFT_MONITOR_ATTEN = 13 -RIGHT_MONITOR_ATTEN = 14 - -ENUM_VALUE = 0 # only certain values are valid -RANGE_VALUE = 1 # any value in range is valid diff --git a/Lib/irix5/AWARE.py b/Lib/irix5/AWARE.py deleted file mode 100755 index 30be50b8ee..0000000000 --- a/Lib/irix5/AWARE.py +++ /dev/null @@ -1,54 +0,0 @@ -# -# Copyright (c) 1992 Aware, Inc. All rights reserved. -# -# Copyright Unpublished, Aware Inc. All Rights Reserved. -# This software contains proprietary and confidential -# information of Aware, Inc. Use, disclosure or -# reproduction is prohibited without the prior express -# written consent of Aware, Inc. -# -# - -# -# awareAudio.h - Aware Compression Library Parameter Header -# -# 01/21/92 Original Version by Brian Knittel and Jonathon Devine -# - -import CL - -# Aware Audio Specific Parameters - For both MPEG Audio and Multirate -CL.CHANNEL_POLICY = CL.NUMBER_OF_PARAMS + 0 -CL.NOISE_MARGIN = CL.NUMBER_OF_PARAMS + 1 -CL.BITRATE_POLICY = CL.NUMBER_OF_PARAMS + 2 - -# Additional parameters for MPEG Audio -CL.BITRATE_TARGET = CL.NUMBER_OF_PARAMS + 3 -CL.LAYER = CL.NUMBER_OF_PARAMS + 4 - -# read/write for compression configuration -# read for state during compression/decompression - -# -# Channel Policy -# -AWCMP_STEREO = 1 -AWCMP_JOINT_STEREO = 2 -AWCMP_INDEPENDENT = 3 - -# -# read/write for compression configuration, -# read for state during compression -# -# -# Bit-rate Policy -# -AWCMP_FIXED_RATE = 1 -AWCMP_CONST_QUAL = 2 -AWCMP_LOSSLESS = 4 - -# -# Layer values -# -AWCMP_MPEG_LAYER_I = 1 -AWCMP_MPEG_LAYER_II = 2 diff --git a/Lib/irix5/CD.py b/Lib/irix5/CD.py deleted file mode 100755 index ad56561235..0000000000 --- a/Lib/irix5/CD.py +++ /dev/null @@ -1,34 +0,0 @@ -ERROR = 0 -NODISC = 1 -READY = 2 -PLAYING = 3 -PAUSED = 4 -STILL = 5 - -AUDIO = 0 -PNUM = 1 -INDEX = 2 -PTIME = 3 -ATIME = 4 -CATALOG = 5 -IDENT = 6 -CONTROL = 7 - -CDDA_DATASIZE = 2352 - -##CDDA_SUBCODESIZE = (sizeof(struct subcodeQ)) -##CDDA_BLOCKSIZE = (sizeof(struct cdframe)) -##CDDA_NUMSAMPLES = (CDDA_DATASIZE/2) -## -##CDQ_PREEMP_MASK = 0xd -##CDQ_COPY_MASK = 0xb -##CDQ_DDATA_MASK = 0xd -##CDQ_BROADCAST_MASK = 0x8 -##CDQ_PREEMPHASIS = 0x1 -##CDQ_COPY_PERMITTED = 0x2 -##CDQ_DIGITAL_DATA = 0x4 -##CDQ_BROADCAST_USE = 0x8 -## -##CDQ_MODE1 = 0x1 -##CDQ_MODE2 = 0x2 -##CDQ_MODE3 = 0x3 diff --git a/Lib/irix5/CL.py b/Lib/irix5/CL.py deleted file mode 100755 index 41c56e0cca..0000000000 --- a/Lib/irix5/CL.py +++ /dev/null @@ -1,236 +0,0 @@ -# -# cl.h - Compression Library typedefs and prototypes -# -# 01/07/92 Cleanup by Brian Knittel -# 02/18/92 Original Version by Brian Knittel -# - -# -# originalFormat parameter values -# -MAX_NUMBER_OF_ORIGINAL_FORMATS = 32 - -# Audio -MONO = 0 -STEREO_INTERLEAVED = 1 - -# Video -# YUV is defined to be the same thing as YCrCb (luma and two chroma components). -# 422 is appended to YUV (or YCrCb) if the chroma is sub-sampled by 2 -# horizontally, packed as U Y1 V Y2 (byte order). -# 422HC is appended to YUV (or YCrCb) if the chroma is sub-sampled by 2 -# vertically in addition to horizontally, and is packed the same as -# 422 except that U & V are not valid on the second line. -# -RGB = 0 -RGBX = 1 -RGBA = 2 -RGB332 = 3 - -GRAYSCALE = 4 -Y = 4 -YUV = 5 -YCbCr = 5 -YUV422 = 6 # 4:2:2 sampling -YCbCr422 = 6 # 4:2:2 sampling -YUV422HC = 7 # 4:1:1 sampling -YCbCr422HC = 7 # 4:1:1 sampling -YUV422DC = 7 # 4:1:1 sampling -YCbCr422DC = 7 # 4:1:1 sampling - -BEST_FIT = -1 - -def BytesPerSample(s): - if s in (MONO, YUV): - return 2 - elif s == STEREO_INTERLEAVED: - return 4 - else: - return 0 - -def BytesPerPixel(f): - if f in (RGB, YUV): - return 3 - elif f in (RGBX, RGBA): - return 4 - elif f in (RGB332, GRAYSCALE): - return 1 - else: - return 2 - -def AudioFormatName(f): - if f == MONO: - return 'MONO' - elif f == STEREO_INTERLEAVED: - return 'STEREO_INTERLEAVED' - else: - return 'Not a valid format' - -def VideoFormatName(f): - if f == RGB: - return 'RGB' - elif f == RGBX: - return 'RGBX' - elif f == RGBA: - return 'RGBA' - elif f == RGB332: - return 'RGB332' - elif f == GRAYSCALE: - return 'GRAYSCALE' - elif f == YUV: - return 'YUV' - elif f == YUV422: - return 'YUV422' - elif f == YUV422DC: - return 'YUV422DC' - else: - return 'Not a valid format' - -MAX_NUMBER_OF_AUDIO_ALGORITHMS = 32 -MAX_NUMBER_OF_VIDEO_ALGORITHMS = 32 - -# -# Algorithm types -# -AUDIO = 0 -VIDEO = 1 - -def AlgorithmNumber(scheme): - return scheme & 0x7fff -def AlgorithmType(scheme): - return (scheme >> 15) & 1 -def Algorithm(type, n): - return n | ((type & 1) << 15) - -# -# "compressionScheme" argument values -# -UNKNOWN_SCHEME = -1 - -UNCOMPRESSED_AUDIO = Algorithm(AUDIO, 0) -G711_ULAW = Algorithm(AUDIO, 1) -ULAW = Algorithm(AUDIO, 1) -G711_ALAW = Algorithm(AUDIO, 2) -ALAW = Algorithm(AUDIO, 2) -AWARE_MPEG_AUDIO = Algorithm(AUDIO, 3) -AWARE_MULTIRATE = Algorithm(AUDIO, 4) - -UNCOMPRESSED = Algorithm(VIDEO, 0) -UNCOMPRESSED_VIDEO = Algorithm(VIDEO, 0) -RLE = Algorithm(VIDEO, 1) -JPEG = Algorithm(VIDEO, 2) -MPEG_VIDEO = Algorithm(VIDEO, 3) -MVC1 = Algorithm(VIDEO, 4) -RTR = Algorithm(VIDEO, 5) -RTR1 = Algorithm(VIDEO, 5) - -# -# Parameters -# -MAX_NUMBER_OF_PARAMS = 256 -# Default Parameters -IMAGE_WIDTH = 0 -IMAGE_HEIGHT = 1 -ORIGINAL_FORMAT = 2 -INTERNAL_FORMAT = 3 -COMPONENTS = 4 -BITS_PER_COMPONENT = 5 -FRAME_RATE = 6 -COMPRESSION_RATIO = 7 -EXACT_COMPRESSION_RATIO = 8 -FRAME_BUFFER_SIZE = 9 -COMPRESSED_BUFFER_SIZE = 10 -BLOCK_SIZE = 11 -PREROLL = 12 -FRAME_TYPE = 13 -ALGORITHM_ID = 14 -ALGORITHM_VERSION = 15 -ORIENTATION = 16 -NUMBER_OF_FRAMES = 17 -SPEED = 18 -LAST_FRAME_INDEX = 19 -NUMBER_OF_PARAMS = 20 - -# JPEG Specific Parameters -QUALITY_FACTOR = NUMBER_OF_PARAMS + 0 - -# MPEG Specific Parameters -END_OF_SEQUENCE = NUMBER_OF_PARAMS + 0 - -# RTR Specific Parameters -QUALITY_LEVEL = NUMBER_OF_PARAMS + 0 -ZOOM_X = NUMBER_OF_PARAMS + 1 -ZOOM_Y = NUMBER_OF_PARAMS + 2 - -# -# Parameter value types -# -ENUM_VALUE = 0 # only certain constant values are valid -RANGE_VALUE = 1 # any value in a given range is valid -FLOATING_ENUM_VALUE = 2 # only certain constant floating point values are valid -FLOATING_RANGE_VALUE = 3 # any value in a given floating point range is valid - -# -# Algorithm Functionality -# -DECOMPRESSOR = 1 -COMPRESSOR = 2 -CODEC = 3 - -# -# Buffer types -# -NONE = 0 -FRAME = 1 -DATA = 2 - -# -# Frame types -# -NONE = 0 -KEYFRAME = 1 -INTRA = 1 -PREDICTED = 2 -BIDIRECTIONAL = 3 - -# -# Orientations -# -TOP_DOWN = 0 -BOTTOM_UP = 1 - -# -# SGI Proprietaty Algorithm Header Start Code -# -HEADER_START_CODE = 0xc1C0DEC - -# -# error codes -# - -BAD_NO_BUFFERSPACE = -2 # no space for internal buffers -BAD_PVBUFFER = -3 # param/val buffer doesn't make sense -BAD_BUFFERLENGTH_NEG = -4 # negative buffer length -BAD_BUFFERLENGTH_ODD = -5 # odd length parameter/value buffer -BAD_PARAM = -6 # invalid parameter -BAD_COMPRESSION_SCHEME = -7 # compression scheme parameter invalid -BAD_COMPRESSOR_HANDLE = -8 # compression handle parameter invalid -BAD_COMPRESSOR_HANDLE_POINTER = -9 # compression handle pointer invalid -BAD_BUFFER_HANDLE = -10 # buffer handle invalid -BAD_BUFFER_QUERY_SIZE = -11 # buffer query size too large -JPEG_ERROR = -12 # error from libjpeg -BAD_FRAME_SIZE = -13 # frame size invalid -PARAM_OUT_OF_RANGE = -14 # parameter out of range -ADDED_ALGORITHM_ERROR = -15 # added algorithm had a unique error -BAD_ALGORITHM_TYPE = -16 # bad algorithm type -BAD_ALGORITHM_NAME = -17 # bad algorithm name -BAD_BUFFERING = -18 # bad buffering calls -BUFFER_NOT_CREATED = -19 # buffer not created -BAD_BUFFER_EXISTS = -20 # buffer already created -BAD_INTERNAL_FORMAT = -21 # invalid internal format -BAD_BUFFER_POINTER = -22 # invalid buffer pointer -FRAME_BUFFER_SIZE_ZERO = -23 # frame buffer has zero size -BAD_STREAM_HEADER = -24 # invalid stream header - -BAD_LICENSE = -25 # netls license not valid -AWARE_ERROR = -26 # error from libawcmp diff --git a/Lib/irix5/DEVICE.py b/Lib/irix5/DEVICE.py deleted file mode 100755 index 7ace8cb0b6..0000000000 --- a/Lib/irix5/DEVICE.py +++ /dev/null @@ -1,400 +0,0 @@ -NULLDEV = 0 -BUTOFFSET = 1 -VALOFFSET = 256 -PSEUDOFFSET = 512 -BUT2OFFSET = 3840 -TIMOFFSET = 515 -XKBDOFFSET = 143 -BUTCOUNT = 255 -VALCOUNT = 256 -TIMCOUNT = 4 -XKBDCOUNT = 28 -USERBUTOFFSET = 4096 -USERVALOFFSET = 12288 -USERPSEUDOFFSET = 16384 -BUT0 = 1 -BUT1 = 2 -BUT2 = 3 -BUT3 = 4 -BUT4 = 5 -BUT5 = 6 -BUT6 = 7 -BUT7 = 8 -BUT8 = 9 -BUT9 = 10 -BUT10 = 11 -BUT11 = 12 -BUT12 = 13 -BUT13 = 14 -BUT14 = 15 -BUT15 = 16 -BUT16 = 17 -BUT17 = 18 -BUT18 = 19 -BUT19 = 20 -BUT20 = 21 -BUT21 = 22 -BUT22 = 23 -BUT23 = 24 -BUT24 = 25 -BUT25 = 26 -BUT26 = 27 -BUT27 = 28 -BUT28 = 29 -BUT29 = 30 -BUT30 = 31 -BUT31 = 32 -BUT32 = 33 -BUT33 = 34 -BUT34 = 35 -BUT35 = 36 -BUT36 = 37 -BUT37 = 38 -BUT38 = 39 -BUT39 = 40 -BUT40 = 41 -BUT41 = 42 -BUT42 = 43 -BUT43 = 44 -BUT44 = 45 -BUT45 = 46 -BUT46 = 47 -BUT47 = 48 -BUT48 = 49 -BUT49 = 50 -BUT50 = 51 -BUT51 = 52 -BUT52 = 53 -BUT53 = 54 -BUT54 = 55 -BUT55 = 56 -BUT56 = 57 -BUT57 = 58 -BUT58 = 59 -BUT59 = 60 -BUT60 = 61 -BUT61 = 62 -BUT62 = 63 -BUT63 = 64 -BUT64 = 65 -BUT65 = 66 -BUT66 = 67 -BUT67 = 68 -BUT68 = 69 -BUT69 = 70 -BUT70 = 71 -BUT71 = 72 -BUT72 = 73 -BUT73 = 74 -BUT74 = 75 -BUT75 = 76 -BUT76 = 77 -BUT77 = 78 -BUT78 = 79 -BUT79 = 80 -BUT80 = 81 -BUT81 = 82 -BUT82 = 83 -MAXKBDBUT = 83 -BUT100 = 101 -BUT101 = 102 -BUT102 = 103 -BUT103 = 104 -BUT104 = 105 -BUT105 = 106 -BUT106 = 107 -BUT107 = 108 -BUT108 = 109 -BUT109 = 110 -BUT110 = 111 -BUT111 = 112 -BUT112 = 113 -BUT113 = 114 -BUT114 = 115 -BUT115 = 116 -BUT116 = 117 -BUT117 = 118 -BUT118 = 119 -BUT119 = 120 -BUT120 = 121 -BUT121 = 122 -BUT122 = 123 -BUT123 = 124 -BUT124 = 125 -BUT125 = 126 -BUT126 = 127 -BUT127 = 128 -BUT128 = 129 -BUT129 = 130 -BUT130 = 131 -BUT131 = 132 -BUT132 = 133 -BUT133 = 134 -BUT134 = 135 -BUT135 = 136 -BUT136 = 137 -BUT137 = 138 -BUT138 = 139 -BUT139 = 140 -BUT140 = 141 -BUT141 = 142 -BUT142 = 143 -BUT143 = 144 -BUT144 = 145 -BUT145 = 146 -BUT146 = 147 -BUT147 = 148 -BUT148 = 149 -BUT149 = 150 -BUT150 = 151 -BUT151 = 152 -BUT152 = 153 -BUT153 = 154 -BUT154 = 155 -BUT155 = 156 -BUT156 = 157 -BUT157 = 158 -BUT158 = 159 -BUT159 = 160 -BUT160 = 161 -BUT161 = 162 -BUT162 = 163 -BUT163 = 164 -BUT164 = 165 -BUT165 = 166 -BUT166 = 167 -BUT167 = 168 -BUT168 = 169 -BUT181 = 182 -BUT182 = 183 -BUT183 = 184 -BUT184 = 185 -BUT185 = 186 -BUT186 = 187 -BUT187 = 188 -BUT188 = 189 -BUT189 = 190 -MOUSE1 = 101 -MOUSE2 = 102 -MOUSE3 = 103 -LEFTMOUSE = 103 -MIDDLEMOUSE = 102 -RIGHTMOUSE = 101 -LPENBUT = 104 -BPAD0 = 105 -BPAD1 = 106 -BPAD2 = 107 -BPAD3 = 108 -LPENVALID = 109 -SWBASE = 111 -SW0 = 111 -SW1 = 112 -SW2 = 113 -SW3 = 114 -SW4 = 115 -SW5 = 116 -SW6 = 117 -SW7 = 118 -SW8 = 119 -SW9 = 120 -SW10 = 121 -SW11 = 122 -SW12 = 123 -SW13 = 124 -SW14 = 125 -SW15 = 126 -SW16 = 127 -SW17 = 128 -SW18 = 129 -SW19 = 130 -SW20 = 131 -SW21 = 132 -SW22 = 133 -SW23 = 134 -SW24 = 135 -SW25 = 136 -SW26 = 137 -SW27 = 138 -SW28 = 139 -SW29 = 140 -SW30 = 141 -SW31 = 142 -SBBASE = 182 -SBPICK = 182 -SBBUT1 = 183 -SBBUT2 = 184 -SBBUT3 = 185 -SBBUT4 = 186 -SBBUT5 = 187 -SBBUT6 = 188 -SBBUT7 = 189 -SBBUT8 = 190 -AKEY = 11 -BKEY = 36 -CKEY = 28 -DKEY = 18 -EKEY = 17 -FKEY = 19 -GKEY = 26 -HKEY = 27 -IKEY = 40 -JKEY = 34 -KKEY = 35 -LKEY = 42 -MKEY = 44 -NKEY = 37 -OKEY = 41 -PKEY = 48 -QKEY = 10 -RKEY = 24 -SKEY = 12 -TKEY = 25 -UKEY = 33 -VKEY = 29 -WKEY = 16 -XKEY = 21 -YKEY = 32 -ZKEY = 20 -ZEROKEY = 46 -ONEKEY = 8 -TWOKEY = 14 -THREEKEY = 15 -FOURKEY = 22 -FIVEKEY = 23 -SIXKEY = 30 -SEVENKEY = 31 -EIGHTKEY = 38 -NINEKEY = 39 -BREAKKEY = 1 -SETUPKEY = 2 -CTRLKEY = 3 -LEFTCTRLKEY = CTRLKEY -CAPSLOCKKEY = 4 -RIGHTSHIFTKEY = 5 -LEFTSHIFTKEY = 6 -NOSCRLKEY = 13 -ESCKEY = 7 -TABKEY = 9 -RETKEY = 51 -SPACEKEY = 83 -LINEFEEDKEY = 60 -BACKSPACEKEY = 61 -DELKEY = 62 -SEMICOLONKEY = 43 -PERIODKEY = 52 -COMMAKEY = 45 -QUOTEKEY = 50 -ACCENTGRAVEKEY = 55 -MINUSKEY = 47 -VIRGULEKEY = 53 -BACKSLASHKEY = 57 -EQUALKEY = 54 -LEFTBRACKETKEY = 49 -RIGHTBRACKETKEY = 56 -LEFTARROWKEY = 73 -DOWNARROWKEY = 74 -RIGHTARROWKEY = 80 -UPARROWKEY = 81 -PAD0 = 59 -PAD1 = 58 -PAD2 = 64 -PAD3 = 65 -PAD4 = 63 -PAD5 = 69 -PAD6 = 70 -PAD7 = 67 -PAD8 = 68 -PAD9 = 75 -PADPF1 = 72 -PADPF2 = 71 -PADPF3 = 79 -PADPF4 = 78 -PADPERIOD = 66 -PADMINUS = 76 -PADCOMMA = 77 -PADENTER = 82 -LEFTALTKEY = 143 -RIGHTALTKEY = 144 -RIGHTCTRLKEY = 145 -F1KEY = 146 -F2KEY = 147 -F3KEY = 148 -F4KEY = 149 -F5KEY = 150 -F6KEY = 151 -F7KEY = 152 -F8KEY = 153 -F9KEY = 154 -F10KEY = 155 -F11KEY = 156 -F12KEY = 157 -PRINTSCREENKEY = 158 -SCROLLLOCKKEY = 159 -PAUSEKEY = 160 -INSERTKEY = 161 -HOMEKEY = 162 -PAGEUPKEY = 163 -ENDKEY = 164 -PAGEDOWNKEY = 165 -NUMLOCKKEY = 166 -PADVIRGULEKEY = 167 -PADASTERKEY = 168 -PADPLUSKEY = 169 -SGIRESERVED = 256 -DIAL0 = 257 -DIAL1 = 258 -DIAL2 = 259 -DIAL3 = 260 -DIAL4 = 261 -DIAL5 = 262 -DIAL6 = 263 -DIAL7 = 264 -DIAL8 = 265 -MOUSEX = 266 -MOUSEY = 267 -LPENX = 268 -LPENY = 269 -BPADX = 270 -BPADY = 271 -CURSORX = 272 -CURSORY = 273 -GHOSTX = 274 -GHOSTY = 275 -SBTX = 276 -SBTY = 277 -SBTZ = 278 -SBRX = 279 -SBRY = 280 -SBRZ = 281 -SBPERIOD = 282 -TIMER0 = 515 -TIMER1 = 516 -TIMER2 = 517 -TIMER3 = 518 -KEYBD = 513 -RAWKEYBD = 514 -VALMARK = 523 -REDRAW = 528 -INPUTCHANGE = 534 -QFULL = 535 -QREADERROR = 538 -WINFREEZE = 539 -WINTHAW = 540 -REDRAWICONIC = 541 -WINQUIT = 542 -DEPTHCHANGE = 543 -WINSHUT = 546 -DRAWOVERLAY = 547 -VIDEO = 548 -MENUBUTTON = RIGHTMOUSE -WINCLOSE = 537 -KEYBDFNAMES = 544 -KEYBDFSTRINGS = 545 -MAXSGIDEVICE = 20000 -GERROR = 524 -WMSEND = 529 -WMREPLY = 530 -WMGFCLOSE = 531 -WMTXCLOSE = 532 -MODECHANGE = 533 -PIECECHANGE = 536 diff --git a/Lib/irix5/FL.py b/Lib/irix5/FL.py deleted file mode 100755 index f85237b85f..0000000000 --- a/Lib/irix5/FL.py +++ /dev/null @@ -1,289 +0,0 @@ -# Constants used by the FORMS library (module fl). -# This corresponds to "forms.h". -# Recommended use: import FL; ... FL.NORMAL_BOX ... etc. -# Alternate use: from FL import *; ... NORMAL_BOX ... etc. - -_v20 = 1 -_v21 = 1 -##import fl -##try: -## _v20 = (fl.get_rgbmode <> None) -##except: -## _v20 = 0 -##del fl - -NULL = 0 -FALSE = 0 -TRUE = 1 - -EVENT = -1 - -LABEL_SIZE = 64 -if _v20: - SHORTCUT_SIZE = 32 -PLACE_FREE = 0 -PLACE_SIZE = 1 -PLACE_ASPECT = 2 -PLACE_MOUSE = 3 -PLACE_CENTER = 4 -PLACE_POSITION = 5 -FL_PLACE_FULLSCREEN = 6 -FIND_INPUT = 0 -FIND_AUTOMATIC = 1 -FIND_MOUSE = 2 -BEGIN_GROUP = 10000 -END_GROUP = 20000 -ALIGN_TOP = 0 -ALIGN_BOTTOM = 1 -ALIGN_LEFT = 2 -ALIGN_RIGHT = 3 -ALIGN_CENTER = 4 -NO_BOX = 0 -UP_BOX = 1 -DOWN_BOX = 2 -FLAT_BOX = 3 -BORDER_BOX = 4 -SHADOW_BOX = 5 -FRAME_BOX = 6 -ROUNDED_BOX = 7 -RFLAT_BOX = 8 -RSHADOW_BOX = 9 -TOP_BOUND_COL = 51 -LEFT_BOUND_COL = 55 -BOT_BOUND_COL = 40 -RIGHT_BOUND_COL = 35 -COL1 = 47 -MCOL = 49 -LCOL = 0 -BOUND_WIDTH = 3.0 -DRAW = 0 -PUSH = 1 -RELEASE = 2 -ENTER = 3 -LEAVE = 4 -MOUSE = 5 -FOCUS = 6 -UNFOCUS = 7 -KEYBOARD = 8 -STEP = 9 -MOVE = 10 -FONT_NAME = 'Helvetica' -FONT_BOLDNAME = 'Helvetica-Bold' -FONT_ITALICNAME = 'Helvetica-Oblique' -FONT_FIXEDNAME = 'Courier' -FONT_ICONNAME = 'Icon' -SMALL_FONT = 8.0 -NORMAL_FONT = 11.0 -LARGE_FONT = 20.0 -NORMAL_STYLE = 0 -BOLD_STYLE = 1 -ITALIC_STYLE = 2 -FIXED_STYLE = 3 -ENGRAVED_STYLE = 4 -ICON_STYLE = 5 -BITMAP = 3 -NORMAL_BITMAP = 0 -BITMAP_BOXTYPE = NO_BOX -BITMAP_COL1 = 0 -BITMAP_COL2 = COL1 -BITMAP_LCOL = LCOL -BITMAP_ALIGN = ALIGN_BOTTOM -BITMAP_MAXSIZE = 128*128 -BITMAP_BW = BOUND_WIDTH -BOX = 1 -BOX_BOXTYPE = UP_BOX -BOX_COL1 = COL1 -BOX_LCOL = LCOL -BOX_ALIGN = ALIGN_CENTER -BOX_BW = BOUND_WIDTH -BROWSER = 71 -NORMAL_BROWSER = 0 -SELECT_BROWSER = 1 -HOLD_BROWSER = 2 -MULTI_BROWSER = 3 -BROWSER_BOXTYPE = DOWN_BOX -BROWSER_COL1 = COL1 -BROWSER_COL2 = 3 -BROWSER_LCOL = LCOL -BROWSER_ALIGN = ALIGN_BOTTOM -BROWSER_SLCOL = COL1 -BROWSER_BW = BOUND_WIDTH -BROWSER_LINELENGTH = 128 -BROWSER_MAXLINE = 512 -BUTTON = 11 -NORMAL_BUTTON = 0 -PUSH_BUTTON = 1 -RADIO_BUTTON = 2 -HIDDEN_BUTTON = 3 -TOUCH_BUTTON = 4 -INOUT_BUTTON = 5 -RETURN_BUTTON = 6 -if _v20: - HIDDEN_RET_BUTTON = 7 -BUTTON_BOXTYPE = UP_BOX -BUTTON_COL1 = COL1 -BUTTON_COL2 = COL1 -BUTTON_LCOL = LCOL -BUTTON_ALIGN = ALIGN_CENTER -BUTTON_MCOL1 = MCOL -BUTTON_MCOL2 = MCOL -BUTTON_BW = BOUND_WIDTH -if _v20: - CHART = 4 - BAR_CHART = 0 - HORBAR_CHART = 1 - LINE_CHART = 2 - FILLED_CHART = 3 - SPIKE_CHART = 4 - PIE_CHART = 5 - SPECIALPIE_CHART = 6 - CHART_BOXTYPE = BORDER_BOX - CHART_COL1 = COL1 - CHART_LCOL = LCOL - CHART_ALIGN = ALIGN_BOTTOM - CHART_BW = BOUND_WIDTH - CHART_MAX = 128 -CHOICE = 42 -NORMAL_CHOICE = 0 -CHOICE_BOXTYPE = DOWN_BOX -CHOICE_COL1 = COL1 -CHOICE_COL2 = LCOL -CHOICE_LCOL = LCOL -CHOICE_ALIGN = ALIGN_LEFT -CHOICE_BW = BOUND_WIDTH -CHOICE_MCOL = MCOL -CHOICE_MAXITEMS = 128 -CHOICE_MAXSTR = 64 -CLOCK = 61 -SQUARE_CLOCK = 0 -ROUND_CLOCK = 1 -CLOCK_BOXTYPE = UP_BOX -CLOCK_COL1 = 37 -CLOCK_COL2 = 42 -CLOCK_LCOL = LCOL -CLOCK_ALIGN = ALIGN_BOTTOM -CLOCK_TOPCOL = COL1 -CLOCK_BW = BOUND_WIDTH -COUNTER = 25 -NORMAL_COUNTER = 0 -SIMPLE_COUNTER = 1 -COUNTER_BOXTYPE = UP_BOX -COUNTER_COL1 = COL1 -COUNTER_COL2 = 4 -COUNTER_LCOL = LCOL -COUNTER_ALIGN = ALIGN_BOTTOM -if _v20: - COUNTER_BW = BOUND_WIDTH -else: - DEFAULT = 51 - RETURN_DEFAULT = 0 - ALWAYS_DEFAULT = 1 -DIAL = 22 -NORMAL_DIAL = 0 -LINE_DIAL = 1 -DIAL_BOXTYPE = NO_BOX -DIAL_COL1 = COL1 -DIAL_COL2 = 37 -DIAL_LCOL = LCOL -DIAL_ALIGN = ALIGN_BOTTOM -DIAL_TOPCOL = COL1 -DIAL_BW = BOUND_WIDTH -FREE = 101 -NORMAL_FREE = 1 -SLEEPING_FREE = 2 -INPUT_FREE = 3 -CONTINUOUS_FREE = 4 -ALL_FREE = 5 -INPUT = 31 -NORMAL_INPUT = 0 -if _v20: - FLOAT_INPUT = 1 - INT_INPUT = 2 - HIDDEN_INPUT = 3 - if _v21: - MULTILINE_INPUT = 4 - SECRET_INPUT = 5 -else: - ALWAYS_INPUT = 1 -INPUT_BOXTYPE = DOWN_BOX -INPUT_COL1 = 13 -INPUT_COL2 = 5 -INPUT_LCOL = LCOL -INPUT_ALIGN = ALIGN_LEFT -INPUT_TCOL = LCOL -INPUT_CCOL = 4 -INPUT_BW = BOUND_WIDTH -INPUT_MAX = 128 -LIGHTBUTTON = 12 -LIGHTBUTTON_BOXTYPE = UP_BOX -LIGHTBUTTON_COL1 = 39 -LIGHTBUTTON_COL2 = 3 -LIGHTBUTTON_LCOL = LCOL -LIGHTBUTTON_ALIGN = ALIGN_CENTER -LIGHTBUTTON_TOPCOL = COL1 -LIGHTBUTTON_MCOL = MCOL -LIGHTBUTTON_BW1 = BOUND_WIDTH -LIGHTBUTTON_BW2 = BOUND_WIDTH/2.0 -LIGHTBUTTON_MINSIZE = 12.0 -MENU = 41 -TOUCH_MENU = 0 -PUSH_MENU = 1 -MENU_BOXTYPE = BORDER_BOX -MENU_COL1 = 55 -MENU_COL2 = 37 -MENU_LCOL = LCOL -MENU_ALIGN = ALIGN_CENTER -MENU_BW = BOUND_WIDTH -MENU_MAX = 300 -POSITIONER = 23 -NORMAL_POSITIONER = 0 -POSITIONER_BOXTYPE = DOWN_BOX -POSITIONER_COL1 = COL1 -POSITIONER_COL2 = 1 -POSITIONER_LCOL = LCOL -POSITIONER_ALIGN = ALIGN_BOTTOM -POSITIONER_BW = BOUND_WIDTH -ROUNDBUTTON = 13 -ROUNDBUTTON_BOXTYPE = NO_BOX -ROUNDBUTTON_COL1 = 7 -ROUNDBUTTON_COL2 = 3 -ROUNDBUTTON_LCOL = LCOL -ROUNDBUTTON_ALIGN = ALIGN_CENTER -ROUNDBUTTON_TOPCOL = COL1 -ROUNDBUTTON_MCOL = MCOL -ROUNDBUTTON_BW = BOUND_WIDTH -SLIDER = 21 -VALSLIDER = 24 -VERT_SLIDER = 0 -HOR_SLIDER = 1 -VERT_FILL_SLIDER = 2 -HOR_FILL_SLIDER = 3 -VERT_NICE_SLIDER = 4 -HOR_NICE_SLIDER = 5 -SLIDER_BOXTYPE = DOWN_BOX -SLIDER_COL1 = COL1 -SLIDER_COL2 = COL1 -SLIDER_LCOL = LCOL -SLIDER_ALIGN = ALIGN_BOTTOM -SLIDER_BW1 = BOUND_WIDTH -SLIDER_BW2 = BOUND_WIDTH*0.75 -SLIDER_FINE = 0.05 -SLIDER_WIDTH = 0.08 -TEXT = 2 -NORMAL_TEXT = 0 -TEXT_BOXTYPE = NO_BOX -TEXT_COL1 = COL1 -TEXT_LCOL = LCOL -TEXT_ALIGN = ALIGN_LEFT -TEXT_BW = BOUND_WIDTH -TIMER = 62 -NORMAL_TIMER = 0 -VALUE_TIMER = 1 -HIDDEN_TIMER = 2 -TIMER_BOXTYPE = DOWN_BOX -TIMER_COL1 = COL1 -TIMER_COL2 = 1 -TIMER_LCOL = LCOL -TIMER_ALIGN = ALIGN_CENTER -TIMER_BW = BOUND_WIDTH -TIMER_BLINKRATE = 0.2 diff --git a/Lib/irix5/GET.py b/Lib/irix5/GET.py deleted file mode 100755 index 9c3d7d6952..0000000000 --- a/Lib/irix5/GET.py +++ /dev/null @@ -1,59 +0,0 @@ -# Symbols from - -BCKBUFFER = 0x1 -FRNTBUFFER = 0x2 -DRAWZBUFFER = 0x4 -DMRGB = 0 -DMSINGLE = 1 -DMDOUBLE = 2 -DMRGBDOUBLE = 5 -HZ30 = 0 -HZ60 = 1 -NTSC = 2 -HDTV = 3 -VGA = 4 -IRIS3K = 5 -PR60 = 6 -PAL = 9 -HZ30_SG = 11 -A343 = 14 -STR_RECT = 15 -VOF0 = 16 -VOF1 = 17 -VOF2 = 18 -VOF3 = 19 -SGI0 = 20 -SGI1 = 21 -SGI2 = 22 -HZ72 = 23 -GL_VIDEO_REG = 0x00800000 -GLV_GENLOCK = 0x00000001 -GLV_UNBLANK = 0x00000002 -GLV_SRED = 0x00000004 -GLV_SGREEN = 0x00000008 -GLV_SBLUE = 0x00000010 -GLV_SALPHA = 0x00000020 -GLV_TTLGENLOCK = 0x00000080 -GLV_TTLSYNC = GLV_TTLGENLOCK -GLV_GREENGENLOCK = 0x0000100 -LEFTPLANE = 0x0001 -RIGHTPLANE = 0x0002 -BOTTOMPLANE = 0x0004 -TOPPLANE = 0x0008 -NEARPLANE = 0x0010 -FARPLANE = 0x0020 -## GETDEF = __GL_GET_H__ -NOBUFFER = 0x0 -BOTHBUFFERS = 0x3 -DMINTENSITYSINGLE = 3 -DMINTENSITYDOUBLE = 4 -MONSPECIAL = 0x20 -HZ50 = 3 -MONA = 5 -MONB = 6 -MONC = 7 -MOND = 8 -MON_ALL = 12 -MON_GEN_ALL = 13 -CMAPMULTI = 0 -CMAPONE = 1 diff --git a/Lib/irix5/GL.py b/Lib/irix5/GL.py deleted file mode 100755 index 9f02f65f3a..0000000000 --- a/Lib/irix5/GL.py +++ /dev/null @@ -1,393 +0,0 @@ -NULL = 0 -FALSE = 0 -TRUE = 1 -ATTRIBSTACKDEPTH = 10 -VPSTACKDEPTH = 8 -MATRIXSTACKDEPTH = 32 -NAMESTACKDEPTH = 1025 -STARTTAG = -2 -ENDTAG = -3 -BLACK = 0 -RED = 1 -GREEN = 2 -YELLOW = 3 -BLUE = 4 -MAGENTA = 5 -CYAN = 6 -WHITE = 7 -PUP_CLEAR = 0 -PUP_COLOR = 1 -PUP_BLACK = 2 -PUP_WHITE = 3 -NORMALDRAW = 0x010 -PUPDRAW = 0x020 -OVERDRAW = 0x040 -UNDERDRAW = 0x080 -CURSORDRAW = 0x100 -DUALDRAW = 0x200 -PATTERN_16 = 16 -PATTERN_32 = 32 -PATTERN_64 = 64 -PATTERN_16_SIZE = 16 -PATTERN_32_SIZE = 64 -PATTERN_64_SIZE = 256 -SRC_AUTO = 0 -SRC_FRONT = 1 -SRC_BACK = 2 -SRC_ZBUFFER = 3 -SRC_PUP = 4 -SRC_OVER = 5 -SRC_UNDER = 6 -SRC_FRAMEGRABBER = 7 -BF_ZERO = 0 -BF_ONE = 1 -BF_DC = 2 -BF_SC = 2 -BF_MDC = 3 -BF_MSC = 3 -BF_SA = 4 -BF_MSA = 5 -BF_DA = 6 -BF_MDA = 7 -BF_MIN_SA_MDA = 8 -AF_NEVER = 0 -AF_LESS = 1 -AF_EQUAL = 2 -AF_LEQUAL = 3 -AF_GREATER = 4 -AF_NOTEQUAL = 5 -AF_GEQUAL = 6 -AF_ALWAYS = 7 -ZF_NEVER = 0 -ZF_LESS = 1 -ZF_EQUAL = 2 -ZF_LEQUAL = 3 -ZF_GREATER = 4 -ZF_NOTEQUAL = 5 -ZF_GEQUAL = 6 -ZF_ALWAYS = 7 -ZSRC_DEPTH = 0 -ZSRC_COLOR = 1 -SMP_OFF = 0x0 -SMP_ON = 0x1 -SMP_SMOOTHER = 0x2 -SML_OFF = 0x0 -SML_ON = 0x1 -SML_SMOOTHER = 0x2 -SML_END_CORRECT = 0x4 -PYSM_OFF = 0 -PYSM_ON = 1 -PYSM_SHRINK = 2 -DT_OFF = 0 -DT_ON = 1 -PUP_NONE = 0 -PUP_GREY = 0x1 -PUP_BOX = 0x2 -PUP_CHECK = 0x4 -GLC_OLDPOLYGON = 0 -GLC_ZRANGEMAP = 1 -GLC_MQUEUERATE = 2 -GLC_SOFTATTACH = 3 -GLC_MANAGEBG = 4 -GLC_SLOWMAPCOLORS = 5 -GLC_INPUTCHANGEBUG = 6 -GLC_NOBORDERBUG = 7 -GLC_SET_VSYNC = 8 -GLC_GET_VSYNC = 9 -GLC_VSYNC_SLEEP = 10 -GLC_COMPATRATE = 15 -C16X1 = 0 -C16X2 = 1 -C32X1 = 2 -C32X2 = 3 -CCROSS = 4 -FLAT = 0 -GOURAUD = 1 -LO_ZERO = 0x0 -LO_AND = 0x1 -LO_ANDR = 0x2 -LO_SRC = 0x3 -LO_ANDI = 0x4 -LO_DST = 0x5 -LO_XOR = 0x6 -LO_OR = 0x7 -LO_NOR = 0x8 -LO_XNOR = 0x9 -LO_NDST = 0xa -LO_ORR = 0xb -LO_NSRC = 0xc -LO_ORI = 0xd -LO_NAND = 0xe -LO_ONE = 0xf -INFOCUSSCRN = -2 -ST_KEEP = 0 -ST_ZERO = 1 -ST_REPLACE = 2 -ST_INCR = 3 -ST_DECR = 4 -ST_INVERT = 5 -SF_NEVER = 0 -SF_LESS = 1 -SF_EQUAL = 2 -SF_LEQUAL = 3 -SF_GREATER = 4 -SF_NOTEQUAL = 5 -SF_GEQUAL = 6 -SF_ALWAYS = 7 -SS_OFF = 0 -SS_DEPTH = 1 -PYM_FILL = 1 -PYM_POINT = 2 -PYM_LINE = 3 -PYM_HOLLOW = 4 -PYM_LINE_FAST = 5 -FG_OFF = 0 -FG_ON = 1 -FG_DEFINE = 2 -FG_VTX_EXP = 2 -FG_VTX_LIN = 3 -FG_PIX_EXP = 4 -FG_PIX_LIN = 5 -FG_VTX_EXP2 = 6 -FG_PIX_EXP2 = 7 -PM_SHIFT = 0 -PM_EXPAND = 1 -PM_C0 = 2 -PM_C1 = 3 -PM_ADD24 = 4 -PM_SIZE = 5 -PM_OFFSET = 6 -PM_STRIDE = 7 -PM_TTOB = 8 -PM_RTOL = 9 -PM_ZDATA = 10 -PM_WARP = 11 -PM_RDX = 12 -PM_RDY = 13 -PM_CDX = 14 -PM_CDY = 15 -PM_XSTART = 16 -PM_YSTART = 17 -PM_VO1 = 1000 -NAUTO = 0 -NNORMALIZE = 1 -AC_CLEAR = 0 -AC_ACCUMULATE = 1 -AC_CLEAR_ACCUMULATE = 2 -AC_RETURN = 3 -AC_MULT = 4 -AC_ADD = 5 -CP_OFF = 0 -CP_ON = 1 -CP_DEFINE = 2 -SB_RESET = 0 -SB_TRACK = 1 -SB_HOLD = 2 -RD_FREEZE = 0x00000001 -RD_ALPHAONE = 0x00000002 -RD_IGNORE_UNDERLAY = 0x00000004 -RD_IGNORE_OVERLAY = 0x00000008 -RD_IGNORE_PUP = 0x00000010 -RD_OFFSCREEN = 0x00000020 -GD_XPMAX = 0 -GD_YPMAX = 1 -GD_XMMAX = 2 -GD_YMMAX = 3 -GD_ZMIN = 4 -GD_ZMAX = 5 -GD_BITS_NORM_SNG_RED = 6 -GD_BITS_NORM_SNG_GREEN = 7 -GD_BITS_NORM_SNG_BLUE = 8 -GD_BITS_NORM_DBL_RED = 9 -GD_BITS_NORM_DBL_GREEN = 10 -GD_BITS_NORM_DBL_BLUE = 11 -GD_BITS_NORM_SNG_CMODE = 12 -GD_BITS_NORM_DBL_CMODE = 13 -GD_BITS_NORM_SNG_MMAP = 14 -GD_BITS_NORM_DBL_MMAP = 15 -GD_BITS_NORM_ZBUFFER = 16 -GD_BITS_OVER_SNG_CMODE = 17 -GD_BITS_UNDR_SNG_CMODE = 18 -GD_BITS_PUP_SNG_CMODE = 19 -GD_BITS_NORM_SNG_ALPHA = 21 -GD_BITS_NORM_DBL_ALPHA = 22 -GD_BITS_CURSOR = 23 -GD_OVERUNDER_SHARED = 24 -GD_BLEND = 25 -GD_CIFRACT = 26 -GD_CROSSHAIR_CINDEX = 27 -GD_DITHER = 28 -GD_LINESMOOTH_CMODE = 30 -GD_LINESMOOTH_RGB = 31 -GD_LOGICOP = 33 -GD_NSCRNS = 35 -GD_NURBS_ORDER = 36 -GD_NBLINKS = 37 -GD_NVERTEX_POLY = 39 -GD_PATSIZE_64 = 40 -GD_PNTSMOOTH_CMODE = 41 -GD_PNTSMOOTH_RGB = 42 -GD_PUP_TO_OVERUNDER = 43 -GD_READSOURCE = 44 -GD_READSOURCE_ZBUFFER = 48 -GD_STEREO = 50 -GD_SUBPIXEL_LINE = 51 -GD_SUBPIXEL_PNT = 52 -GD_SUBPIXEL_POLY = 53 -GD_TRIMCURVE_ORDER = 54 -GD_WSYS = 55 -GD_ZDRAW_GEOM = 57 -GD_ZDRAW_PIXELS = 58 -GD_SCRNTYPE = 61 -GD_TEXTPORT = 62 -GD_NMMAPS = 63 -GD_FRAMEGRABBER = 64 -GD_TIMERHZ = 66 -GD_DBBOX = 67 -GD_AFUNCTION = 68 -GD_ALPHA_OVERUNDER = 69 -GD_BITS_ACBUF = 70 -GD_BITS_ACBUF_HW = 71 -GD_BITS_STENCIL = 72 -GD_CLIPPLANES = 73 -GD_FOGVERTEX = 74 -GD_LIGHTING_TWOSIDE = 76 -GD_POLYMODE = 77 -GD_POLYSMOOTH = 78 -GD_SCRBOX = 79 -GD_TEXTURE = 80 -GD_FOGPIXEL = 81 -GD_TEXTURE_PERSP = 82 -GD_MUXPIPES = 83 -GD_NOLIMIT = -2 -GD_WSYS_NONE = 0 -GD_WSYS_4S = 1 -GD_SCRNTYPE_WM = 0 -GD_SCRNTYPE_NOWM = 1 -N_PIXEL_TOLERANCE = 1 -N_CULLING = 2 -N_DISPLAY = 3 -N_ERRORCHECKING = 4 -N_SUBDIVISIONS = 5 -N_S_STEPS = 6 -N_T_STEPS = 7 -N_TILES = 8 -N_TMP1 = 9 -N_TMP2 = 10 -N_TMP3 = 11 -N_TMP4 = 12 -N_TMP5 = 13 -N_TMP6 = 14 -N_FILL = 1.0 -N_OUTLINE_POLY = 2.0 -N_OUTLINE_PATCH = 5.0 -N_ISOLINE_S = 12.0 -N_ST = 0x8 -N_STW = 0xd -N_XYZ = 0x4c -N_XYZW = 0x51 -N_TEX = 0x88 -N_TEXW = 0x8d -N_RGBA = 0xd0 -N_RGBAW = 0xd5 -N_P2D = 0x8 -N_P2DR = 0xd -N_V3D = 0x4c -N_V3DR = 0x51 -N_T2D = 0x88 -N_T2DR = 0x8d -N_C4D = 0xd0 -N_C4DR = 0xd5 -LMNULL = 0.0 -MSINGLE = 0 -MPROJECTION = 1 -MVIEWING = 2 -MTEXTURE = 3 -MAXLIGHTS = 8 -MAXRESTRICTIONS = 4 -DEFMATERIAL = 0 -EMISSION = 1 -AMBIENT = 2 -DIFFUSE = 3 -SPECULAR = 4 -SHININESS = 5 -COLORINDEXES = 6 -ALPHA = 7 -DEFLIGHT = 100 -LCOLOR = 101 -POSITION = 102 -SPOTDIRECTION = 103 -SPOTLIGHT = 104 -DEFLMODEL = 200 -LOCALVIEWER = 201 -ATTENUATION = 202 -ATTENUATION2 = 203 -TWOSIDE = 204 -MATERIAL = 1000 -BACKMATERIAL = 1001 -LIGHT0 = 1100 -LIGHT1 = 1101 -LIGHT2 = 1102 -LIGHT3 = 1103 -LIGHT4 = 1104 -LIGHT5 = 1105 -LIGHT6 = 1106 -LIGHT7 = 1107 -LMODEL = 1200 -LMC_COLOR = 0 -LMC_EMISSION = 1 -LMC_AMBIENT = 2 -LMC_DIFFUSE = 3 -LMC_SPECULAR = 4 -LMC_AD = 5 -LMC_NULL = 6 -TX_MINFILTER = 0x100 -TX_MAGFILTER = 0x200 -TX_WRAP = 0x300 -TX_WRAP_S = 0x310 -TX_WRAP_T = 0x320 -TX_TILE = 0x400 -TX_BORDER = 0x500 -TX_NULL = 0x000 -TX_POINT = 0x110 -TX_BILINEAR = 0x220 -TX_MIPMAP = 0x120 -TX_MIPMAP_POINT = 0x121 -TX_MIPMAP_LINEAR = 0x122 -TX_MIPMAP_BILINEAR = 0x123 -TX_MIPMAP_TRILINEAR = 0x124 -TX_REPEAT = 0x301 -TX_CLAMP = 0x302 -TX_SELECT = 0x303 -TX_TEXTURE_0 = 0 -TV_MODULATE = 0x101 -TV_BLEND = 0x102 -TV_DECAL = 0x103 -TV_COLOR = 0x200 -TV_NULL = 0x000 -TV_ENV0 = 0 -TX_S = 0 -TX_T = 1 -TG_OFF = 0 -TG_ON = 1 -TG_CONTOUR = 2 -TG_LINEAR = 3 -TG_SPHEREMAP = 4 -TG_REFRACTMAP = 5 -DGLSINK = 0 -DGLLOCAL = 1 -DGLTSOCKET = 2 -DGL4DDN = 3 -PUP_CURSOR = PUP_COLOR -FATAL = 1 -WARNING = 2 -ASK_CONT = 3 -ASK_RESTART = 4 -XMAXSCREEN = 1279 -YMAXSCREEN = 1023 -XMAXMEDIUM = 1023 -YMAXMEDIUM = 767 -XMAX170 = 645 -YMAX170 = 484 -XMAXPAL = 779 -YMAXPAL = 574 diff --git a/Lib/irix5/GLWS.py b/Lib/irix5/GLWS.py deleted file mode 100755 index 69dab7143f..0000000000 --- a/Lib/irix5/GLWS.py +++ /dev/null @@ -1,12 +0,0 @@ -NOERROR = 0 -NOCONTEXT = -1 -NODISPLAY = -2 -NOWINDOW = -3 -NOGRAPHICS = -4 -NOTTOP = -5 -NOVISUAL = -6 -BUFSIZE = -7 -BADWINDOW = -8 -ALREADYBOUND = -100 -BINDFAILED = -101 -SETFAILED = -102 diff --git a/Lib/irix5/SV.py b/Lib/irix5/SV.py deleted file mode 100755 index 08fb91798a..0000000000 --- a/Lib/irix5/SV.py +++ /dev/null @@ -1,120 +0,0 @@ -NTSC_XMAX = 640 -NTSC_YMAX = 480 -PAL_XMAX = 768 -PAL_YMAX = 576 -BLANKING_BUFFER_SIZE = 2 - -MAX_SOURCES = 2 - -# mode parameter for Bind calls -IN_OFF = 0 # No Video -IN_OVER = 1 # Video over graphics -IN_UNDER = 2 # Video under graphics -IN_REPLACE = 3 # Video replaces entire win - -# mode parameters for LoadMap calls. Specifies buffer, always 256 entries -INPUT_COLORMAP = 0 # tuples of 8-bit RGB -CHROMA_KEY_MAP = 1 # tuples of 8-bit RGB -COLOR_SPACE_MAP = 2 # tuples of 8-bit RGB -GAMMA_MAP = 3 # tuples of 24-bit red values - -# mode parameters for UseExclusive calls -INPUT = 0 -OUTPUT = 1 -IN_OUT = 2 - -# Format constants for the capture routines -RGB8_FRAMES = 0 # noninterleaved 8 bit 3:2:3 RBG fields -RGB32_FRAMES = 1 # 32-bit 8:8:8 RGB frames -YUV411_FRAMES = 2 # interleaved, 8:2:2 YUV format -YUV411_FRAMES_AND_BLANKING_BUFFER = 3 - -# -# sv.SetParam is passed variable length argument lists, -# consisting of pairs. The following -# constants identify argument names. -# -_NAME_BASE = 1000 -SOURCE = (_NAME_BASE + 0) -SOURCE1 = 0 -SOURCE2 = 1 -SOURCE3 = 2 -COLOR = (_NAME_BASE + 1) -DEFAULT_COLOR = 0 -USER_COLOR = 1 -MONO = 2 -OUTPUTMODE = (_NAME_BASE + 2) -LIVE_OUTPUT = 0 -STILL24_OUT = 1 -FREEZE = (_NAME_BASE + 3) -DITHER = (_NAME_BASE + 4) -OUTPUT_FILTER = (_NAME_BASE + 5) -HUE = (_NAME_BASE + 6) -GENLOCK = (_NAME_BASE + 7) -GENLOCK_OFF = 0 -GENLOCK_ON = 1 -GENLOCK_HOUSE = 2 -BROADCAST = (_NAME_BASE + 8) -NTSC = 0 -PAL = 1 -VIDEO_MODE = (_NAME_BASE + 9) -COMP = 0 -SVIDEO = 1 -INPUT_BYPASS = (_NAME_BASE + 10) -FIELDDROP = (_NAME_BASE + 11) -SLAVE = (_NAME_BASE + 12) -APERTURE_FACTOR = (_NAME_BASE + 13) -AFACTOR_0 = 0 -AFACTOR_QTR = 1 -AFACTOR_HLF = 2 -AFACTOR_ONE = 3 -CORING = (_NAME_BASE + 14) -COR_OFF = 0 -COR_1LSB = 1 -COR_2LSB = 2 -COR_3LSB = 3 -APERTURE_BANDPASS = (_NAME_BASE + 15) -ABAND_F0 = 0 -ABAND_F1 = 1 -ABAND_F2 = 2 -ABAND_F3 = 3 -PREFILTER = (_NAME_BASE + 16) -CHROMA_TRAP = (_NAME_BASE + 17) -CK_THRESHOLD = (_NAME_BASE + 18) -PAL_SENSITIVITY = (_NAME_BASE + 19) -GAIN_CONTROL = (_NAME_BASE + 20) -GAIN_SLOW = 0 -GAIN_MEDIUM = 1 -GAIN_FAST = 2 -GAIN_FROZEN = 3 -AUTO_CKILL = (_NAME_BASE + 21) -VTR_MODE = (_NAME_BASE + 22) -VTR_INPUT = 0 -CAMERA_INPUT = 1 -LUMA_DELAY = (_NAME_BASE + 23) -VNOISE = (_NAME_BASE + 24) -VNOISE_NORMAL = 0 -VNOISE_SEARCH = 1 -VNOISE_AUTO = 2 -VNOISE_BYPASS = 3 -CHCV_PAL = (_NAME_BASE + 25) -CHCV_NTSC = (_NAME_BASE + 26) -CCIR_LEVELS = (_NAME_BASE + 27) -STD_CHROMA = (_NAME_BASE + 28) -DENC_VTBYPASS = (_NAME_BASE + 29) -FAST_TIMECONSTANT = (_NAME_BASE + 30) -GENLOCK_DELAY = (_NAME_BASE + 31) -PHASE_SYNC = (_NAME_BASE + 32) -VIDEO_OUTPUT = (_NAME_BASE + 33) -CHROMA_PHASEOUT = (_NAME_BASE + 34) -CHROMA_CENTER = (_NAME_BASE + 35) -YUV_TO_RGB_INVERT = (_NAME_BASE + 36) -SOURCE1_BROADCAST = (_NAME_BASE + 37) -SOURCE1_MODE = (_NAME_BASE + 38) -SOURCE2_BROADCAST = (_NAME_BASE + 39) -SOURCE2_MODE = (_NAME_BASE + 40) -SOURCE3_BROADCAST = (_NAME_BASE + 41) -SOURCE3_MODE = (_NAME_BASE + 42) -SIGNAL_STD = (_NAME_BASE + 43) -NOSIGNAL = 2 -SIGNAL_COLOR = (_NAME_BASE + 44) diff --git a/Lib/irix5/auds.py b/Lib/irix5/auds.py deleted file mode 100755 index fb992a9594..0000000000 --- a/Lib/irix5/auds.py +++ /dev/null @@ -1,106 +0,0 @@ -import audio - -RATE = 8192 - -# Initialize the audio stuff -audio.setrate(3) -audio.setoutgain(100) # for speaker - -play = audio.write - -def samp(n): - savegain = audio.getoutgain() - try: - audio.setoutgain(0) - x = raw_input('Hit Enter to sample ' + `n` + ' seconds: ') - return audio.read(n*RATE) - finally: - audio.setoutgain(savegain) - -def echo(s, delay, gain): - return s[:delay] + audio.add(s[delay:], audio.amplify(s, gain, gain)) - -def save(s, file): - f = open(file, 'w') - f.write(s) - -def load(file): - return loadfp(open(file, 'r')) - -def loadfp(fp): - s = '' - while 1: - buf = fp.read(16*1024) - if not buf: break - s = s + buf - return s - -def unbias(s): - if not s: return s - a = audio.chr2num(s) - sum = 0 - for i in a: sum = sum + i - bias = (sum + len(a)/2) / len(a) - print 'Bias value:', bias - if bias: - for i in range(len(a)): - a[i] = a[i] - bias - s = audio.num2chr(a) - return s - -# Stretch by a/b. -# Think of this as converting the sampling rate from a samples/sec -# to b samples/sec. Or, if the input is a bytes long, the output -# will be b bytes long. -# -def stretch(s, a, b): - y = audio.chr2num(s) - m = len(y) - out = [] - n = m * b / a - # i, j will walk through y and out (step 1) - # ib, ja are i*b, j*a and are kept as close together as possible - i, ib = 0, 0 - j, ja = 0, 0 - for j in range(n): - ja = ja+a - while ib < ja: - i = i+1 - ib = ib+b - if i >= m: - break - if ib == ja: - out.append(y[i]) - else: - out.append((y[i]*(ja-(ib-b)) + y[i-1]*(ib-ja)) / b) - return audio.num2chr(out) - -def sinus(freq): # return a 1-second sine wave - from math import sin, pi - factor = 2.0*pi*float(freq)/float(RATE) - list = range(RATE) - for i in list: - list[i] = int(sin(float(i) * factor) * 127.0) - return audio.num2chr(list) - -def softclip(s): - if '\177' not in s and '\200' not in s: - return s - num = audio.chr2num(s) - extremes = (-128, 127) - for i in range(1, len(num)-1): - if num[i] in extremes: - num[i] = (num[i-1] + num[i+1]) / 2 - return audio.num2chr(num) - -def demo(): - gday = load('gday')[1000:6000] - save(gday, 'gday0') - gg = [gday] - for i in range(1, 10): - for g in gg: play(g) - g = stretch(gday, 10, 10-i) - save(g, 'gday' + `i`) - gg.append(g) - while 1: - for g in gg: play(g) diff --git a/Lib/irix5/cddb.py b/Lib/irix5/cddb.py deleted file mode 100755 index d7fdc96e96..0000000000 --- a/Lib/irix5/cddb.py +++ /dev/null @@ -1,158 +0,0 @@ -# This file implements a class which forms an interface to the .cddb -# directory that is maintained by SGI's cdman program. -# -# Usage is as follows: -# -# import readcd -# r = readcd.Readcd() -# c = Cddb(r.gettrackinfo()) -# -# Now you can use c.artist, c.title and c.track[trackno] (where trackno -# starts at 1). When the CD is not recognized, all values will be the empty -# string. -# It is also possible to set the above mentioned variables to new values. -# You can then use c.write() to write out the changed values to the -# .cdplayerrc file. - -import string, posix - -_cddbrc = '.cddb' -_DB_ID_NTRACKS = 5 -_dbid_map = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@_=+abcdefghijklmnopqrstuvwxyz' -def _dbid(v): - if v >= len(_dbid_map): - return string.zfill(v, 2) - else: - return _dbid_map[v] - -def tochash(toc): - if type(toc) == type(''): - tracklist = [] - for i in range(2, len(toc), 4): - tracklist.append((None, - (string.atoi(toc[i:i+2]), - string.atoi(toc[i+2:i+4])))) - else: - tracklist = toc - ntracks = len(tracklist) - hash = _dbid((ntracks >> 4) & 0xF) + _dbid(ntracks & 0xF) - if ntracks <= _DB_ID_NTRACKS: - nidtracks = ntracks - else: - nidtracks = _DB_ID_NTRACKS - 1 - min = 0 - sec = 0 - for track in tracklist: - start, length = track - min = min + length[0] - sec = sec + length[1] - min = min + sec / 60 - sec = sec % 60 - hash = hash + _dbid(min) + _dbid(sec) - for i in range(nidtracks): - start, length = tracklist[i] - hash = hash + _dbid(length[0]) + _dbid(length[1]) - return hash - -class Cddb: - def __init__(self, tracklist): - if posix.environ.has_key('CDDB_PATH'): - path = posix.environ['CDDB_PATH'] - cddb_path = string.splitfields(path, ',') - else: - home = posix.environ['HOME'] - cddb_path = [home + '/' + _cddbrc] - self.artist = '' - self.title = '' - if type(tracklist) == type(''): - t = [] - for i in range(2, len(tracklist), 4): - t.append((None, \ - (string.atoi(tracklist[i:i+2]), \ - string.atoi(tracklist[i+2:i+4])))) - tracklist = t - ntracks = len(tracklist) - self.track = [None] + [''] * ntracks - self.id = _dbid((ntracks >> 4) & 0xF) + _dbid(ntracks & 0xF) - if ntracks <= _DB_ID_NTRACKS: - nidtracks = ntracks - else: - nidtracks = _DB_ID_NTRACKS - 1 - min = 0 - sec = 0 - for track in tracklist: - start, length = track - min = min + length[0] - sec = sec + length[1] - min = min + sec / 60 - sec = sec % 60 - self.id = self.id + _dbid(min) + _dbid(sec) - for i in range(nidtracks): - start, length = tracklist[i] - self.id = self.id + _dbid(length[0]) + _dbid(length[1]) - self.toc = string.zfill(ntracks, 2) - for track in tracklist: - start, length = track - self.toc = self.toc + string.zfill(length[0], 2) + \ - string.zfill(length[1], 2) - for dir in cddb_path: - file = dir + '/' + self.id + '.rdb' - try: - f = open(file, 'r') - self.file = file - break - except IOError: - pass - if not hasattr(self, 'file'): - return - import regex - reg = regex.compile('^\\([^.]*\\)\\.\\([^:]*\\):\t\\(.*\\)') - while 1: - line = f.readline() - if not line: - break - if reg.match(line) == -1: - print 'syntax error in ' + file - continue - name1 = line[reg.regs[1][0]:reg.regs[1][1]] - name2 = line[reg.regs[2][0]:reg.regs[2][1]] - value = line[reg.regs[3][0]:reg.regs[3][1]] - if name1 == 'album': - if name2 == 'artist': - self.artist = value - elif name2 == 'title': - self.title = value - elif name2 == 'toc': - if self.toc != value: - print 'toc\'s don\'t match' - elif name1[:5] == 'track': - try: - trackno = string.atoi(name1[5:]) - except strings.atoi_error: - print 'syntax error in ' + file - continue - if trackno > ntracks: - print 'track number ' + `trackno` + \ - ' in file ' + file + \ - ' out of range' - continue - self.track[trackno] = value - f.close() - - def write(self): - import posixpath - if posix.environ.has_key('CDDB_WRITE_DIR'): - dir = posix.environ['CDDB_WRITE_DIR'] - else: - dir = posix.environ['HOME'] + '/' + _cddbrc - file = dir + '/' + self.id + '.rdb' - if posixpath.exists(file): - # make backup copy - posix.rename(file, file + '~') - f = open(file, 'w') - f.write('album.title:\t' + self.title + '\n') - f.write('album.artist:\t' + self.artist + '\n') - f.write('album.toc:\t' + self.toc + '\n') - for i in range(1, len(self.track)): - f.write('track' + `i` + '.title:\t' + self.track[i] + '\n') - f.close() diff --git a/Lib/irix5/cdplayer.py b/Lib/irix5/cdplayer.py deleted file mode 100755 index 5c2c95aa7f..0000000000 --- a/Lib/irix5/cdplayer.py +++ /dev/null @@ -1,89 +0,0 @@ -# This file implements a class which forms an interface to the .cdplayerrc -# file that is maintained by SGI's cdplayer program. -# -# Usage is as follows: -# -# import readcd -# r = readcd.Readcd() -# c = Cdplayer(r.gettrackinfo()) -# -# Now you can use c.artist, c.title and c.track[trackno] (where trackno -# starts at 1). When the CD is not recognized, all values will be the empty -# string. -# It is also possible to set the above mentioned variables to new values. -# You can then use c.write() to write out the changed values to the -# .cdplayerrc file. - -cdplayerrc = '.cdplayerrc' - -class Cdplayer: - def __init__(self, tracklist): - import string - self.artist = '' - self.title = '' - if type(tracklist) == type(''): - t = [] - for i in range(2, len(tracklist), 4): - t.append((None, \ - (string.atoi(tracklist[i:i+2]), \ - string.atoi(tracklist[i+2:i+4])))) - tracklist = t - self.track = [None] + [''] * len(tracklist) - self.id = 'd' + string.zfill(len(tracklist), 2) - for track in tracklist: - start, length = track - self.id = self.id + string.zfill(length[0], 2) + \ - string.zfill(length[1], 2) - try: - import posix - f = open(posix.environ['HOME'] + '/' + cdplayerrc, 'r') - except IOError: - return - import regex - reg = regex.compile('^\\([^:]*\\):\t\\(.*\\)') - s = self.id + '.' - l = len(s) - while 1: - line = f.readline() - if line == '': - break - if line[:l] == s: - line = line[l:] - if reg.match(line) == -1: - print 'syntax error in ~/' + cdplayerrc - continue - name = line[reg.regs[1][0]:reg.regs[1][1]] - value = line[reg.regs[2][0]:reg.regs[2][1]] - if name == 'title': - self.title = value - elif name == 'artist': - self.artist = value - elif name[:5] == 'track': - trackno = string.atoi(name[6:]) - self.track[trackno] = value - f.close() - - def write(self): - import posix - filename = posix.environ['HOME'] + '/' + cdplayerrc - try: - old = open(filename, 'r') - except IOError: - old = open('/dev/null', 'r') - new = open(filename + '.new', 'w') - s = self.id + '.' - l = len(s) - while 1: - line = old.readline() - if line == '': - break - if line[:l] <> s: - new.write(line) - new.write(self.id + '.title:\t' + self.title + '\n') - new.write(self.id + '.artist:\t' + self.artist + '\n') - for i in range(1, len(self.track)): - new.write(self.id + '.track.' + `i` + ':\t' + \ - self.track[i] + '\n') - old.close() - new.close() - posix.rename(filename + '.new', filename) diff --git a/Lib/irix5/flp.doc b/Lib/irix5/flp.doc deleted file mode 100755 index 1a2f374ae7..0000000000 --- a/Lib/irix5/flp.doc +++ /dev/null @@ -1,117 +0,0 @@ -.SH -Module flp -.LP -The flp module loads fl-forms from fd files, as generated -by fdesign. The module is designed to be flexible enough to allow -almost anything to be done with the loaded form. -.LP -Loadform defines -two types of functions: functions to parse fd files and functions to -create the forms from the templates returned by the parse functions. -There are fairly low-level create functions that create single objects, -and convenience routines that create complete forms, including callbacks, -etc. -.LP -The exception flp.error is raised whenever an error occurs while parsing a forms -definition file or creating a form. -.SH 2 -Parsing functions -.LP -There are two parsing functions, parse_form() and parse_forms(). They -take the following form: -.LP -.ft C -ftuple = parse_form(filename, formname) -.br -ftdict = parse_forms(filename) -.IP -Parse_form parses a single form, and returns a tuple (ftmp, otmplist). -Ftmp is a template for a form, otmplist is a list of templates for -objects. See below for a description of these templates. -.IP -Parse_forms parses all forms in an fd file. It returns a dictionary of -(ftmp, otmplist) tuples, indexed by formname. -.IP -Filename is the name of the forms definition file to inspect. The functions -appends '.fd' if needed, and use 'sys.path' to locate the file. -.IP -formname is the name of the form to load. This argument is mandatory, -even if the file only contains one form. -.LP -The form template and object template are structures that contain all -the information read from the fd file, in 'natural' form. A form -template record contains the following fields: -.IP -.nf -"Name", the name of the form; -"Width", the width of the form; -"Height", the height of the form; and -"Numberofobjects", the number of objects in the form. -.LP -An object template contains the following fields: -.IP -.nf -"Class", the class of object (eg. FL.BUTTON); -"Type", the sub-class (eg. FL.NORMALBUTTON); -"Box", a list with four members: [x, y, width, height]; -"Boxtype", the type of box (eg. FL.DOWNBOX); -"Colors", a list with the two object colors; -"Alignment", the label alignment (eg. FL.ALIGNLEFT); -"Style", the label style (eg. FL.BOLDSTYLE); -"Lcol", the label color; -"Label", a string containing the label; -"Name", a string containing the name of the object; -"Callback", a string containing the callback routine name; and -"Argument", a string containing the callback routine extra argument. -.SH -Low-level create routines. -.LP -The three low-level creation routines are called as follows: -.LP -.ft C -form = create_form(form_template) -.IP -Create an fl form from a form template. Returns the form created. -.LP -.ft C -obj = create_object(form, obj_template) -.IP -Create an object in an fl form. Return the new object. -An error is raised if the object has a callback routine. -.SH -High-level create routines. -.LP -The 'standard' way to handle forms in python is to define a class -that contains the form and all the objects (insofar as they are named), -and that defines all the callback functions, and use an instance of -this class to handle the form interaction. -Flp contains three routines that simplify handling this paradigm: -.LP -.ft C -create_full_form(instance, ftuple) -.IP -This routine takes an instance of your form-handling class and an -ftuple (as returned by the parsing routines) as parameters. It inserts -the form into the instance, defines all object names and arranges that -the callback methods are called. All the names inserted into the -instance are the same as the names used for the objects, etc. in the -fd file. -.LP -.ft C -merge_full_form(instance, form, ftuple) -.IP -This function does the same as create_full_form, only it does not create -the form itself nor the 'background box' that fdesign automatically -adds to each form. This is useful if your class inherits a superclass -that already defines a skeleton form (with 'OK' and 'Cancel' buttons, -for instance), and you want to merge the new form into that existing -form. The 'form' parameter is the form to which the new objects are -added. -.LP -If you use the paradigm sketched here but need slightly more control -over object creation there is a routine that creates a single object -and inserts its name (and arranges for the callback routine to be -called): -.LP -.ft C -create_object_instance(instance, form, obj_template) diff --git a/Lib/irix5/flp.py b/Lib/irix5/flp.py deleted file mode 100755 index c3f6f3b2c5..0000000000 --- a/Lib/irix5/flp.py +++ /dev/null @@ -1,465 +0,0 @@ -# -# flp - Module to load fl forms from fd files -# -# Jack Jansen, December 1991 -# -import string -import os -import sys -import FL - -SPLITLINE = '--------------------' -FORMLINE = '=============== FORM ===============' -ENDLINE = '==============================' - -error = 'flp.error' - -################################################################## -# Part 1 - The parsing routines # -################################################################## - -# -# Externally visible function. Load form. -# -def parse_form(filename, formname): - forms = checkcache(filename) - if forms != None: - if forms.has_key(formname): - return forms[formname] - else: - forms = {} - fp = _open_formfile(filename) - nforms = _parse_fd_header(fp) - for i in range(nforms): - form = _parse_fd_form(fp, formname) - if form <> None: - break - else: - raise error, 'No such form in fd file' - forms[formname] = form - writecache(filename, forms) - return form - -# -# Externally visible function. Load all forms. -# -def parse_forms(filename): - forms = checkcache(filename) - if forms != None: return forms - fp = _open_formfile(filename) - nforms = _parse_fd_header(fp) - forms = {} - for i in range(nforms): - form = _parse_fd_form(fp, None) - forms[form[0].Name] = form - writecache(filename, forms) - return forms - -# -# Internal: see if a cached version of the file exists -# -MAGIC = '.fdc' -_internal_cache = {} # Used by frozen scripts only -def checkcache(filename): - if _internal_cache.has_key(filename): - altforms = _internal_cache[filename] - return _unpack_cache(altforms) - import marshal - fp, filename = _open_formfile2(filename) - fp.close() - cachename = filename + 'c' - try: - fp = open(cachename, 'r') - except IOError: - #print 'flp: no cache file', cachename - return None - try: - if fp.read(4) != MAGIC: - print 'flp: bad magic word in cache file', cachename - return None - cache_mtime = rdlong(fp) - file_mtime = getmtime(filename) - if cache_mtime != file_mtime: - #print 'flp: outdated cache file', cachename - return None - #print 'flp: valid cache file', cachename - altforms = marshal.load(fp) - return _unpack_cache(altforms) - finally: - fp.close() - -def _unpack_cache(altforms): - forms = {} - for name in altforms.keys(): - altobj, altlist = altforms[name] - obj = _newobj() - obj.make(altobj) - list = [] - for altobj in altlist: - nobj = _newobj() - nobj.make(altobj) - list.append(nobj) - forms[name] = obj, list - return forms - -def rdlong(fp): - s = fp.read(4) - if len(s) != 4: return None - a, b, c, d = s[0], s[1], s[2], s[3] - return ord(a)<<24 | ord(b)<<16 | ord(c)<<8 | ord(d) - -def wrlong(fp, x): - a, b, c, d = (x>>24)&0xff, (x>>16)&0xff, (x>>8)&0xff, x&0xff - fp.write(chr(a) + chr(b) + chr(c) + chr(d)) - -def getmtime(filename): - import os - from stat import ST_MTIME - try: - return os.stat(filename)[ST_MTIME] - except os.error: - return None - -# -# Internal: write cached version of the form (parsing is too slow!) -# -def writecache(filename, forms): - import marshal - fp, filename = _open_formfile2(filename) - fp.close() - cachename = filename + 'c' - try: - fp = open(cachename, 'w') - except IOError: - print 'flp: can\'t create cache file', cachename - return # Never mind - fp.write('\0\0\0\0') # Seek back and write MAGIC when done - wrlong(fp, getmtime(filename)) - altforms = _pack_cache(forms) - marshal.dump(altforms, fp) - fp.seek(0) - fp.write(MAGIC) - fp.close() - #print 'flp: wrote cache file', cachename - -# -# External: print some statements that set up the internal cache. -# This is for use with the "freeze" script. You should call -# flp.freeze(filename) for all forms used by the script, and collect -# the output on a file in a module file named "frozenforms.py". Then -# in the main program of the script import frozenforms. -# (Don't forget to take this out when using the unfrozen version of -# the script!) -# -def freeze(filename): - forms = parse_forms(filename) - altforms = _pack_cache(forms) - print 'import flp' - print 'flp._internal_cache[', `filename`, '] =', altforms - -# -# Internal: create the data structure to be placed in the cache -# -def _pack_cache(forms): - altforms = {} - for name in forms.keys(): - obj, list = forms[name] - altobj = obj.__dict__ - altlist = [] - for obj in list: altlist.append(obj.__dict__) - altforms[name] = altobj, altlist - return altforms - -# -# Internal: Locate form file (using PYTHONPATH) and open file -# -def _open_formfile(filename): - return _open_formfile2(filename)[0] - -def _open_formfile2(filename): - if filename[-3:] <> '.fd': - filename = filename + '.fd' - if filename[0] == '/': - try: - fp = open(filename,'r') - except IOError: - fp = None - else: - for pc in sys.path: - pn = os.path.join(pc, filename) - try: - fp = open(pn, 'r') - filename = pn - break - except IOError: - fp = None - if fp == None: - raise error, 'Cannot find forms file ' + filename - return fp, filename - -# -# Internal: parse the fd file header, return number of forms -# -def _parse_fd_header(file): - # First read the magic header line - datum = _parse_1_line(file) - if datum <> ('Magic', 12321): - raise error, 'Not a forms definition file' - # Now skip until we know number of forms - while 1: - datum = _parse_1_line(file) - if type(datum) == type(()) and datum[0] == 'Numberofforms': - break - return datum[1] -# -# Internal: parse fd form, or skip if name doesn't match. -# the special value None means 'allways parse it'. -# -def _parse_fd_form(file, name): - datum = _parse_1_line(file) - if datum <> FORMLINE: - raise error, 'Missing === FORM === line' - form = _parse_object(file) - if form.Name == name or name == None: - objs = [] - for j in range(form.Numberofobjects): - obj = _parse_object(file) - objs.append(obj) - return (form, objs) - else: - for j in range(form.Numberofobjects): - _skip_object(file) - return None - -# -# Internal class: a convient place to store object info fields -# -class _newobj: - def add(self, name, value): - self.__dict__[name] = value - def make(self, dict): - for name in dict.keys(): - self.add(name, dict[name]) - -# -# Internal parsing routines. -# -def _parse_string(str): - if '\\' in str: - s = '\'' + str + '\'' - try: - return eval(s) - except: - pass - return str - -def _parse_num(str): - return eval(str) - -def _parse_numlist(str): - slist = string.split(str) - nlist = [] - for i in slist: - nlist.append(_parse_num(i)) - return nlist - -# This dictionary maps item names to parsing routines. -# If no routine is given '_parse_num' is default. -_parse_func = { \ - 'Name': _parse_string, \ - 'Box': _parse_numlist, \ - 'Colors': _parse_numlist, \ - 'Label': _parse_string, \ - 'Name': _parse_string, \ - 'Callback': _parse_string, \ - 'Argument': _parse_string } - -# This function parses a line, and returns either -# a string or a tuple (name,value) - -import regex -prog = regex.compile('^\([^:]*\): *\(.*\)') - -def _parse_line(line): - if prog.match(line) < 0: - return line - a = prog.regs - name = line[:a[1][1]] - if name[0] == 'N': - name = string.joinfields(string.split(name),'') - name = string.lower(name) - name = string.upper(name[0]) + name[1:] - value = line[a[2][0]:] - try: - pf = _parse_func[name] - except KeyError: - pf = _parse_num - value = pf(value) - return (name, value) - -def _readline(file): - line = file.readline() - if not line: - raise EOFError - return line[:-1] - -def _parse_1_line(file): - line = _readline(file) - while line == '': - line = _readline(file) - return _parse_line(line) - -def _skip_object(file): - line = '' - while not line in (SPLITLINE, FORMLINE, ENDLINE): - pos = file.tell() - line = _readline(file) - if line == FORMLINE: - file.seek(pos) - -def _parse_object(file): - obj = _newobj() - while 1: - pos = file.tell() - datum = _parse_1_line(file) - if datum in (SPLITLINE, FORMLINE, ENDLINE): - if datum == FORMLINE: - file.seek(pos) - return obj - if type(datum) <> type(()) or len(datum) <> 2: - raise error, 'Parse error, illegal line in object: '+datum - obj.add(datum[0], datum[1]) - -################################################################# -# Part 2 - High-level object/form creation routines # -################################################################# - -# -# External - Create a form an link to an instance variable. -# -def create_full_form(inst, (fdata, odatalist)): - form = create_form(fdata) - exec('inst.'+fdata.Name+' = form\n') - for odata in odatalist: - create_object_instance(inst, form, odata) - -# -# External - Merge a form into an existing form in an instance -# variable. -# -def merge_full_form(inst, form, (fdata, odatalist)): - exec('inst.'+fdata.Name+' = form\n') - if odatalist[0].Class <> FL.BOX: - raise error, 'merge_full_form() expects FL.BOX as first obj' - for odata in odatalist[1:]: - create_object_instance(inst, form, odata) - - -################################################################# -# Part 3 - Low-level object/form creation routines # -################################################################# - -# -# External Create_form - Create form from parameters -# -def create_form(fdata): - import fl - return fl.make_form(FL.NO_BOX, fdata.Width, fdata.Height) - -# -# External create_object - Create an object. Make sure there are -# no callbacks. Returns the object created. -# -def create_object(form, odata): - obj = _create_object(form, odata) - if odata.Callback: - raise error, 'Creating free object with callback' - return obj -# -# External create_object_instance - Create object in an instance. -# -def create_object_instance(inst, form, odata): - obj = _create_object(form, odata) - if odata.Callback: - cbfunc = eval('inst.'+odata.Callback) - obj.set_call_back(cbfunc, odata.Argument) - if odata.Name: - exec('inst.' + odata.Name + ' = obj\n') -# -# Internal _create_object: Create the object and fill options -# -def _create_object(form, odata): - crfunc = _select_crfunc(form, odata.Class) - obj = crfunc(odata.Type, odata.Box[0], odata.Box[1], odata.Box[2], \ - odata.Box[3], odata.Label) - if not odata.Class in (FL.BEGIN_GROUP, FL.END_GROUP): - obj.boxtype = odata.Boxtype - obj.col1 = odata.Colors[0] - obj.col2 = odata.Colors[1] - obj.align = odata.Alignment - obj.lstyle = odata.Style - obj.lsize = odata.Size - obj.lcol = odata.Lcol - return obj -# -# Internal crfunc: helper function that returns correct create function -# -def _select_crfunc(fm, cl): - if cl == FL.BEGIN_GROUP: return fm.bgn_group - elif cl == FL.END_GROUP: return fm.end_group - elif cl == FL.BITMAP: return fm.add_bitmap - elif cl == FL.BOX: return fm.add_box - elif cl == FL.BROWSER: return fm.add_browser - elif cl == FL.BUTTON: return fm.add_button - elif cl == FL.CHART: return fm.add_chart - elif cl == FL.CHOICE: return fm.add_choice - elif cl == FL.CLOCK: return fm.add_clock - elif cl == FL.COUNTER: return fm.add_counter - elif cl == FL.DIAL: return fm.add_dial - elif cl == FL.FREE: return fm.add_free - elif cl == FL.INPUT: return fm.add_input - elif cl == FL.LIGHTBUTTON: return fm.add_lightbutton - elif cl == FL.MENU: return fm.add_menu - elif cl == FL.POSITIONER: return fm.add_positioner - elif cl == FL.ROUNDBUTTON: return fm.add_roundbutton - elif cl == FL.SLIDER: return fm.add_slider - elif cl == FL.VALSLIDER: return fm.add_valslider - elif cl == FL.TEXT: return fm.add_text - elif cl == FL.TIMER: return fm.add_timer - else: - raise error, 'Unknown object type: ' + `cl` - - -def test(): - import time - t0 = time.millitimer() - if len(sys.argv) == 2: - forms = parse_forms(sys.argv[1]) - t1 = time.millitimer() - print 'parse time:', 0.001*(t1-t0), 'sec.' - keys = forms.keys() - keys.sort() - for i in keys: - _printform(forms[i]) - elif len(sys.argv) == 3: - form = parse_form(sys.argv[1], sys.argv[2]) - t1 = time.millitimer() - print 'parse time:', 0.001*(t1-t0), 'sec.' - _printform(form) - else: - print 'Usage: test fdfile [form]' - -def _printform(form): - f = form[0] - objs = form[1] - print 'Form ', f.Name, ', size: ', f.Width, f.Height, ' Nobj ', f.Numberofobjects - for i in objs: - print ' Obj ', i.Name, ' type ', i.Class, i.Type - print ' Box ', i.Box, ' btype ', i.Boxtype - print ' Label ', i.Label, ' size/style/col/align ', i.Size,i.Style, i.Lcol, i.Alignment - print ' cols ', i.Colors - print ' cback ', i.Callback, i.Argument - -# Local variables: -# py-indent-offset: 4 -# end: diff --git a/Lib/irix5/panel.py b/Lib/irix5/panel.py deleted file mode 100755 index 21a17ba0ae..0000000000 --- a/Lib/irix5/panel.py +++ /dev/null @@ -1,281 +0,0 @@ -# Module 'panel' -# -# Support for the Panel library. -# Uses built-in module 'pnl'. -# Applciations should use 'panel.function' instead of 'pnl.function'; -# most 'pnl' functions are transparently exported by 'panel', -# but dopanel() is overridden and you have to use this version -# if you want to use callbacks. - - -import pnl - - -debug = 0 - - -# Test if an object is a list. -# -def is_list(x): - return type(x) == type([]) - - -# Reverse a list. -# -def reverse(list): - res = [] - for item in list: - res.insert(0, item) - return res - - -# Get an attribute of a list, which may itself be another list. -# Don't use 'prop' for name. -# -def getattrlist(list, name): - for item in list: - if item and is_list(item) and item[0] == name: - return item[1:] - return [] - - -# Get a property of a list, which may itself be another list. -# -def getproplist(list, name): - for item in list: - if item and is_list(item) and item[0] == 'prop': - if len(item) > 1 and item[1] == name: - return item[2:] - return [] - - -# Test if an actuator description contains the property 'end-of-group' -# -def is_endgroup(list): - x = getproplist(list, 'end-of-group') - return (x and x[0] == '#t') - - -# Neatly display an actuator definition given as S-expression -# the prefix string is printed before each line. -# -def show_actuator(prefix, a): - for item in a: - if not is_list(item): - print prefix, item - elif item and item[0] == 'al': - print prefix, 'Subactuator list:' - for a in item[1:]: - show_actuator(prefix + ' ', a) - elif len(item) == 2: - print prefix, item[0], '=>', item[1] - elif len(item) == 3 and item[0] == 'prop': - print prefix, 'Prop', item[1], '=>', - print item[2] - else: - print prefix, '?', item - - -# Neatly display a panel. -# -def show_panel(prefix, p): - for item in p: - if not is_list(item): - print prefix, item - elif item and item[0] == 'al': - print prefix, 'Actuator list:' - for a in item[1:]: - show_actuator(prefix + ' ', a) - elif len(item) == 2: - print prefix, item[0], '=>', item[1] - elif len(item) == 3 and item[0] == 'prop': - print prefix, 'Prop', item[1], '=>', - print item[2] - else: - print prefix, '?', item - - -# Exception raised by build_actuator or build_panel. -# -panel_error = 'panel error' - - -# Dummy callback used to initialize the callbacks. -# -def dummy_callback(arg): - pass - - -# Assign attributes to members of the target. -# Attribute names in exclist are ignored. -# The member name is the attribute name prefixed with the prefix. -# -def assign_members(target, attrlist, exclist, prefix): - for item in attrlist: - if is_list(item) and len(item) == 2 and item[0] not in exclist: - name, value = item[0], item[1] - ok = 1 - if value[0] in '-0123456789': - value = eval(value) - elif value[0] == '"': - value = value[1:-1] - elif value == 'move-then-resize': - # Strange default set by Panel Editor... - ok = 0 - else: - print 'unknown value', value, 'for', name - ok = 0 - if ok: - lhs = 'target.' + prefix + name - stmt = lhs + '=' + `value` - if debug: print 'exec', stmt - try: - exec(stmt + '\n') - except KeyboardInterrupt: # Don't catch this! - raise KeyboardInterrupt - except: - print 'assign failed:', stmt - - -# Build a real actuator from an actuator descriptior. -# Return a pair (actuator, name). -# -def build_actuator(descr): - namelist = getattrlist(descr, 'name') - if namelist: - # Assume it is a string - actuatorname = namelist[0][1:-1] - else: - actuatorname = '' - type = descr[0] - if type[:4] == 'pnl_': type = type[4:] - act = pnl.mkact(type) - act.downfunc = act.activefunc = act.upfunc = dummy_callback - # - assign_members(act, descr[1:], ['al', 'data', 'name'], '') - # - # Treat actuator-specific data - # - datalist = getattrlist(descr, 'data') - prefix = '' - if type[-4:] == 'puck': - prefix = 'puck_' - elif type == 'mouse': - prefix = 'mouse_' - assign_members(act, datalist, [], prefix) - # - return act, actuatorname - - -# Build all sub-actuators and add them to the super-actuator. -# The super-actuator must already have been added to the panel. -# Sub-actuators with defined names are added as members to the panel -# so they can be referenced as p.name. -# -# Note: I have no idea how panel.endgroup() works when applied -# to a sub-actuator. -# -def build_subactuators(panel, super_act, al): - # - # This is nearly the same loop as below in build_panel(), - # except a call is made to addsubact() instead of addact(). - # - for a in al: - act, name = build_actuator(a) - act.addsubact(super_act) - if name: - stmt = 'panel.' + name + ' = act' - if debug: print 'exec', stmt - exec(stmt + '\n') - if is_endgroup(a): - panel.endgroup() - sub_al = getattrlist(a, 'al') - if sub_al: - build_subactuators(panel, act, sub_al) - # - # Fix the actuator to which whe just added subactuators. - # This can't hurt (I hope) and is needed for the scroll actuator. - # - super_act.fixact() - - -# Build a real panel from a panel definition. -# Return a panel object p, where for each named actuator a, p.name is a -# reference to a. -# -def build_panel(descr): - # - # Sanity check - # - if (not descr) or descr[0] <> 'panel': - raise panel_error, 'panel description must start with "panel"' - # - if debug: show_panel('', descr) - # - # Create an empty panel - # - panel = pnl.mkpanel() - # - # Assign panel attributes - # - assign_members(panel, descr[1:], ['al'], '') - # - # Look for actuator list - # - al = getattrlist(descr, 'al') - # - # The order in which actuators are created is important - # because of the endgroup() operator. - # Unfortunately the Panel Editor outputs the actuator list - # in reverse order, so we reverse it here. - # - al = reverse(al) - # - for a in al: - act, name = build_actuator(a) - act.addact(panel) - if name: - stmt = 'panel.' + name + ' = act' - exec(stmt + '\n') - if is_endgroup(a): - panel.endgroup() - sub_al = getattrlist(a, 'al') - if sub_al: - build_subactuators(panel, act, sub_al) - # - return panel - - -# Wrapper around pnl.dopanel() which calls call-back functions. -# -def my_dopanel(): - # Extract only the first 4 elements to allow for future expansion - a, down, active, up = pnl.dopanel()[:4] - if down: - down.downfunc(down) - if active: - active.activefunc(active) - if up: - up.upfunc(up) - return a - - -# Create one or more panels from a description file (S-expressions) -# generated by the Panel Editor. -# -def defpanellist(file): - import panelparser - descrlist = panelparser.parse_file(open(file, 'r')) - panellist = [] - for descr in descrlist: - panellist.append(build_panel(descr)) - return panellist - - -# Import everything from built-in method pnl, so the user can always -# use panel.foo() instead of pnl.foo(). -# This gives *no* performance penalty once this module is imported. -# -from pnl import * # for export - -dopanel = my_dopanel # override pnl.dopanel diff --git a/Lib/irix5/panelparser.py b/Lib/irix5/panelparser.py deleted file mode 100755 index 1b069fa075..0000000000 --- a/Lib/irix5/panelparser.py +++ /dev/null @@ -1,128 +0,0 @@ -# Module 'parser' -# -# Parse S-expressions output by the Panel Editor -# (which is written in Scheme so it can't help writing S-expressions). -# -# See notes at end of file. - - -whitespace = ' \t\n' -operators = '()\'' -separators = operators + whitespace + ';' + '"' - - -# Tokenize a string. -# Return a list of tokens (strings). -# -def tokenize_string(s): - tokens = [] - while s: - c = s[:1] - if c in whitespace: - s = s[1:] - elif c == ';': - s = '' - elif c == '"': - n = len(s) - i = 1 - while i < n: - c = s[i] - i = i+1 - if c == '"': break - if c == '\\': i = i+1 - tokens.append(s[:i]) - s = s[i:] - elif c in operators: - tokens.append(c) - s = s[1:] - else: - n = len(s) - i = 1 - while i < n: - if s[i] in separators: break - i = i+1 - tokens.append(s[:i]) - s = s[i:] - return tokens - - -# Tokenize a whole file (given as file object, not as file name). -# Return a list of tokens (strings). -# -def tokenize_file(fp): - tokens = [] - while 1: - line = fp.readline() - if not line: break - tokens = tokens + tokenize_string(line) - return tokens - - -# Exception raised by parse_exr. -# -syntax_error = 'syntax error' - - -# Parse an S-expression. -# Input is a list of tokens as returned by tokenize_*(). -# Return a pair (expr, tokens) -# where expr is a list representing the s-expression, -# and tokens contains the remaining tokens. -# May raise syntax_error. -# -def parse_expr(tokens): - if (not tokens) or tokens[0] <> '(': - raise syntax_error, 'expected "("' - tokens = tokens[1:] - expr = [] - while 1: - if not tokens: - raise syntax_error, 'missing ")"' - if tokens[0] == ')': - return expr, tokens[1:] - elif tokens[0] == '(': - subexpr, tokens = parse_expr(tokens) - expr.append(subexpr) - else: - expr.append(tokens[0]) - tokens = tokens[1:] - - -# Parse a file (given as file object, not as file name). -# Return a list of parsed S-expressions found at the top level. -# -def parse_file(fp): - tokens = tokenize_file(fp) - exprlist = [] - while tokens: - expr, tokens = parse_expr(tokens) - exprlist.append(expr) - return exprlist - - -# EXAMPLE: -# -# The input -# '(hip (hop hur-ray))' -# -# passed to tokenize_string() returns the token list -# ['(', 'hip', '(', 'hop', 'hur-ray', ')', ')'] -# -# When this is passed to parse_expr() it returns the expression -# ['hip', ['hop', 'hur-ray']] -# plus an empty token list (because there are no tokens left. -# -# When a file containing the example is passed to parse_file() it returns -# a list whose only element is the output of parse_expr() above: -# [['hip', ['hop', 'hur-ray']]] - - -# TOKENIZING: -# -# Comments start with semicolon (;) and continue till the end of the line. -# -# Tokens are separated by whitespace, except the following characters -# always form a separate token (outside strings): -# ( ) ' -# Strings are enclosed in double quotes (") and backslash (\) is used -# as escape character in strings. diff --git a/Lib/irix5/readcd.doc b/Lib/irix5/readcd.doc deleted file mode 100755 index 1be549c790..0000000000 --- a/Lib/irix5/readcd.doc +++ /dev/null @@ -1,104 +0,0 @@ -Interface to CD-ROM player. - -This module implements an interface to the built-in cd module. The -intention is to provide a more user-friendly interface than the -built-in module. - -The module defines a class Readcd with several methods. The -initialization of the class will try to open the CD player. This -means that initialization will fail if the CD player is already in -use. A RuntimeError will be raised by the cd module in that case. - -The way to work with this module is as follows. The user specifies -the parts of the CD that are to be read and he specifies callback -functions which are to be called by the system. At some point he can -tell the system to play. The specified parts of the CD will then be -read and the callbacks will be called. - -Initialization. -=============== - -r = readcd.Readcd([cd-player [, mode]]) - -The optional arguments are the name of the CD device and the mode. -When "mode" is not specified, it defaults to 'r' (which is the only -possible value); when "cd-player" also isn't specified, it defaults -to "None" which indicates the default CD player. - -Methods. -======== - -eject() -- Eject the CD from the player. - -reset() -- Reset the list of data stretches to be played. - -appendtrack(track) -- Append the specified track to the list of music -stretches. - -appendstretch(first, last) -- Append the stretch from "first" to "last" -to the list of music stretches. Both "first" and "last" can be in one -of four forms. "None": for "first", the beginning of the CD, for -"last" the end of the CD; a single integer: a track number--playing -starts at the beginning of the track or ends at the end of the -specified track; a three-tuple: the absolute time from the start of -the CD in minutes, seconds, frames; a four-tuple: track number and -relative time within the track in minutes, seconds, frames. - -settracks(tracklist) -- The argument is a list of integers. The list -of stretches is set to argument list. The old list is discarded. - -setcallback(type, func, arg) -- Set a callback function for "type". -The function will be called as func(arg, type, data) where "arg" is -the third argument of setcallback, "type" is the type of callback, -"data" is type-dependent data. See the CDsetcallback(3) manual page -for more information. The possible "type" arguments are defined in -the CD module. - -removecallback(type) -- Remove the callback for "type". - -gettrackinfo([tracklist]) -- Return a list of tuples. Each tuple -consists of start and length information of a track. The start and -length information consist of three-tuples with minutes, seconds and -frames. The optional tracklist argument gives a list of interesting -track numbers. If no tracklist is specified, information about all -tracks is returned. - -getstatus() -- Return the status information of the CD. - -play() -- Play the preprogrammed stretches of music from the CD. When -nothing was programmed, the whole CD is played. - -Specifying stretches. -===================== - -There are three methods available to specify a stretch of music to be -played. The easiest way is to use "settracklist(tracklist)" with which -a list of tracks can be specified. "settracklist(tracklist)" is -equivalent to the sequence - reset() - for track in tracklist: - appendtrack(track) - -The next method is "appendtrack(track)" with which a whole track can be -added to the list of music to be played. "appendtrack(track)" is -equivalent to "appendstretch(track, track)". - -The most complete method is "appendstretch(first, last)". Using this -method, it is possible to specify any stretch of music. - -When two consecutive tracks are played, it is possible to choose -whether the pause that may be between the tracks is played as well or -whether the pause should be skipped. When the end of a stretch is -specified using a track number and the next stretch starts at the -beginning of the following track and that was also specified using the -track number (that is, both were specified as integers, not as tuples), -the pause is played. When either value was specified using absolute -time or track-relative time (that is, as three-tuple or as -four-tuple), the pause will not be played. - -Errors. -======= - -When an error occurs, an exception will be raised. Depending on where -the error occurs, the exception may either be "readcd.Error" or -"RuntimeError". diff --git a/Lib/irix5/readcd.py b/Lib/irix5/readcd.py deleted file mode 100755 index fffb6fe8c6..0000000000 --- a/Lib/irix5/readcd.py +++ /dev/null @@ -1,232 +0,0 @@ -# Class interface to the CD module. - -import cd, CD - -Error = 'Readcd.Error' -_Stop = 'Readcd.Stop' - -def _doatime(self, cb_type, data): - if ((data[0] * 60) + data[1]) * 75 + data[2] > self.end: -## print 'done with list entry',`self.listindex` - raise _Stop - func, arg = self.callbacks[cb_type] - if func: - func(arg, cb_type, data) - -def _dopnum(self, cb_type, data): - if data > self.end: -## print 'done with list entry',`self.listindex` - raise _Stop - func, arg = self.callbacks[cb_type] - if func: - func(arg, cb_type, data) - -class Readcd: - def __init__(self, *arg): - if len(arg) == 0: - self.player = cd.open() - elif len(arg) == 1: - self.player = cd.open(arg[0]) - elif len(arg) == 2: - self.player = cd.open(arg[0], arg[1]) - else: - raise Error, 'bad __init__ call' - self.list = [] - self.callbacks = [(None, None)] * 8 - self.parser = cd.createparser() - self.playing = 0 - self.end = 0 - self.status = None - self.trackinfo = None - - def eject(self): - self.player.eject() - self.list = [] - self.end = 0 - self.listindex = 0 - self.status = None - self.trackinfo = None - if self.playing: -## print 'stop playing from eject' - raise _Stop - - def pmsf2msf(self, track, min, sec, frame): - if not self.status: - self.cachestatus() - if track < self.status[5] or track > self.status[6]: - raise Error, 'track number out of range' - if not self.trackinfo: - self.cacheinfo() - start, total = self.trackinfo[track] - start = ((start[0] * 60) + start[1]) * 75 + start[2] - total = ((total[0] * 60) + total[1]) * 75 + total[2] - block = ((min * 60) + sec) * 75 + frame - if block > total: - raise Error, 'out of range' - block = start + block - min, block = divmod(block, 75*60) - sec, frame = divmod(block, 75) - return min, sec, frame - - def reset(self): - self.list = [] - - def appendtrack(self, track): - self.appendstretch(track, track) - - def appendstretch(self, start, end): - if not self.status: - self.cachestatus() - if not start: - start = 1 - if not end: - end = self.status[6] - if type(end) == type(0): - if end < self.status[5] or end > self.status[6]: - raise Error, 'range error' - else: - l = len(end) - if l == 4: - prog, min, sec, frame = end - if prog < self.status[5] or prog > self.status[6]: - raise Error, 'range error' - end = self.pmsf2msf(prog, min, sec, frame) - elif l <> 3: - raise Error, 'syntax error' - if type(start) == type(0): - if start < self.status[5] or start > self.status[6]: - raise Error, 'range error' - if len(self.list) > 0: - s, e = self.list[-1] - if type(e) == type(0): - if start == e+1: - start = s - del self.list[-1] - else: - l = len(start) - if l == 4: - prog, min, sec, frame = start - if prog < self.status[5] or prog > self.status[6]: - raise Error, 'range error' - start = self.pmsf2msf(prog, min, sec, frame) - elif l <> 3: - raise Error, 'syntax error' - self.list.append((start, end)) - - def settracks(self, list): - self.list = [] - for track in list: - self.appendtrack(track) - - def setcallback(self, cb_type, func, arg): - if cb_type < 0 or cb_type >= 8: - raise Error, 'type out of range' - self.callbacks[cb_type] = (func, arg) - if self.playing: - start, end = self.list[self.listindex] - if type(end) == type(0): - if cb_type <> CD.PNUM: - self.parser.setcallback(cb_type, func, arg) - else: - if cb_type <> CD.ATIME: - self.parser.setcallback(cb_type, func, arg) - - def removecallback(self, cb_type): - if cb_type < 0 or cb_type >= 8: - raise Error, 'type out of range' - self.callbacks[cb_type] = (None, None) - if self.playing: - start, end = self.list[self.listindex] - if type(end) == type(0): - if cb_type <> CD.PNUM: - self.parser.removecallback(cb_type) - else: - if cb_type <> CD.ATIME: - self.parser.removecallback(cb_type) - - def gettrackinfo(self, *arg): - if not self.status: - self.cachestatus() - if not self.trackinfo: - self.cacheinfo() - if len(arg) == 0: - return self.trackinfo[self.status[5]:self.status[6]+1] - result = [] - for i in arg: - if i < self.status[5] or i > self.status[6]: - raise Error, 'range error' - result.append(self.trackinfo[i]) - return result - - def cacheinfo(self): - if not self.status: - self.cachestatus() - self.trackinfo = [] - for i in range(self.status[5]): - self.trackinfo.append(None) - for i in range(self.status[5], self.status[6]+1): - self.trackinfo.append(self.player.gettrackinfo(i)) - - def cachestatus(self): - self.status = self.player.getstatus() - if self.status[0] == CD.NODISC: - self.status = None - raise Error, 'no disc in player' - - def getstatus(self): - return self.player.getstatus() - - def play(self): - if not self.status: - self.cachestatus() - size = self.player.bestreadsize() - self.listindex = 0 - self.playing = 0 - for i in range(8): - func, arg = self.callbacks[i] - if func: - self.parser.setcallback(i, func, arg) - else: - self.parser.removecallback(i) - if len(self.list) == 0: - for i in range(self.status[5], self.status[6]+1): - self.appendtrack(i) - while 1: - if not self.playing: - if self.listindex >= len(self.list): - return - start, end = self.list[self.listindex] -## print 'starting with',`(start, end)` - if type(start) == type(0): - dummy = self.player.seektrack(start) - else: - min, sec, frame = start - dummy = self.player.seek(min, sec, frame) - if type(end) == type(0): - self.parser.setcallback(CD.PNUM, _dopnum, self) - self.end = end - func, arg = self.callbacks[CD.ATIME] - if func: - self.parser.setcallback(CD.ATIME, func, arg) - else: - self.parser.removecallback(CD.ATIME) - else: - min, sec, frame = end - self.parser.setcallback(CD.ATIME, _doatime, self) - self.end = (min * 60 + sec) * 75 + frame - func, arg = self.callbacks[CD.PNUM] - if func: - self.parser.setcallback(CD.PNUM, func, arg) - else: - self.parser.removecallback(CD.PNUM) - self.playing = 1 - data = self.player.readda(size) - if data == '': - self.playing = 0 - self.listindex = self.listindex + 1 - continue - try: - self.parser.parseframe(data) - except _Stop: - self.playing = 0 - self.listindex = self.listindex + 1 diff --git a/Lib/irix5/torgb.py b/Lib/irix5/torgb.py deleted file mode 100755 index f283063c00..0000000000 --- a/Lib/irix5/torgb.py +++ /dev/null @@ -1,97 +0,0 @@ -# Convert "arbitrary" image files to rgb files (SGI's image format). -# Input may be compressed. -# The uncompressed file type may be PBM, PGM, PPM, GIF, TIFF, or Sun raster. -# An exception is raised if the file is not of a recognized type. -# Returned filename is either the input filename or a temporary filename; -# in the latter case the caller must ensure that it is removed. -# Other temporary files used are removed by the function. - -import os -import tempfile -import pipes -import imghdr - -table = {} - -t = pipes.Template() -t.append('fromppm $IN $OUT', 'ff') -table['ppm'] = t - -t = pipes.Template() -t.append('(PATH=$PATH:/ufs/guido/bin/sgi; exec pnmtoppm)', '--') -t.append('fromppm $IN $OUT', 'ff') -table['pnm'] = t -table['pgm'] = t -table['pbm'] = t - -t = pipes.Template() -t.append('fromgif $IN $OUT', 'ff') -table['gif'] = t - -t = pipes.Template() -t.append('tifftopnm', '--') -t.append('(PATH=$PATH:/ufs/guido/bin/sgi; exec pnmtoppm)', '--') -t.append('fromppm $IN $OUT', 'ff') -table['tiff'] = t - -t = pipes.Template() -t.append('rasttopnm', '--') -t.append('(PATH=$PATH:/ufs/guido/bin/sgi; exec pnmtoppm)', '--') -t.append('fromppm $IN $OUT', 'ff') -table['rast'] = t - -t = pipes.Template() -t.append('djpeg', '--') -t.append('(PATH=$PATH:/ufs/guido/bin/sgi; exec pnmtoppm)', '--') -t.append('fromppm $IN $OUT', 'ff') -table['jpeg'] = t - -uncompress = pipes.Template() -uncompress.append('uncompress', '--') - - -error = 'torgb.error' # Exception - -def torgb(filename): - temps = [] - ret = None - try: - ret = _torgb(filename, temps) - finally: - for temp in temps[:]: - if temp <> ret: - try: - os.unlink(temp) - except os.error: - pass - temps.remove(temp) - return ret - -def _torgb(filename, temps): - if filename[-2:] == '.Z': - fname = tempfile.mktemp() - temps.append(fname) - sts = uncompress.copy(filename, fname) - if sts: - raise error, filename + ': uncompress failed' - else: - fname = filename - try: - ftype = imghdr.what(fname) - except IOError, msg: - if type(msg) == type(()) and len(msg) == 2 and \ - type(msg[0]) == type(0) and type(msg[1]) == type(''): - msg = msg[1] - if type(msg) <> type(''): - msg = `msg` - raise error, filename + ': ' + msg - if ftype == 'rgb': - return fname - if ftype == None or not table.has_key(ftype): - raise error, \ - filename + ': unsupported image file type ' + `ftype` - temp = tempfile.mktemp() - sts = table[ftype].copy(fname, temp) - if sts: - raise error, filename + ': conversion to rgb failed' - return temp diff --git a/Lib/lib-old/codehack.py b/Lib/lib-old/codehack.py deleted file mode 100644 index d00d2bfec9..0000000000 --- a/Lib/lib-old/codehack.py +++ /dev/null @@ -1,63 +0,0 @@ -# A subroutine for extracting a function name from a code object -# (with cache) - -import sys -from stat import * -import string -import os -import linecache - -# Extract the function or class name from a code object. -# This is a bit of a hack, since a code object doesn't contain -# the name directly. So what do we do: -# - get the filename (which *is* in the code object) -# - look in the code string to find the first SET_LINENO instruction -# (this must be the first instruction) -# - get the line from the file -# - if the line starts with 'class' or 'def' (after possible whitespace), -# extract the following identifier -# -# This breaks apart when the function was read from -# or constructed by exec(), when the file is not accessible, -# and also when the file has been modified or when a line is -# continued with a backslash before the function or class name. -# -# Because this is a pretty expensive hack, a cache is kept. - -SET_LINENO = 127 # The opcode (see "opcode.h" in the Python source) -identchars = string.letters + string.digits + '_' # Identifier characters - -_namecache = {} # The cache - -def getcodename(co): - key = `co` # arbitrary but uniquely identifying string - if _namecache.has_key(key): return _namecache[key] - filename = co.co_filename - code = co.co_code - name = '' - if ord(code[0]) == SET_LINENO: - lineno = ord(code[1]) | ord(code[2]) << 8 - line = linecache.getline(filename, lineno) - words = string.split(line) - if len(words) >= 2 and words[0] in ('def', 'class'): - name = words[1] - for i in range(len(name)): - if name[i] not in identchars: - name = name[:i] - break - _namecache[key] = name - return name - -# Use the above routine to find a function's name. - -def getfuncname(func): - return getcodename(func.func_code) - -# A part of the above code to extract just the line number from a code object. - -def getlineno(co): - code = co.co_code - if ord(code[0]) == SET_LINENO: - return ord(code[1]) | ord(code[2]) << 8 - else: - return -1 diff --git a/Lib/lib-old/dump.py b/Lib/lib-old/dump.py deleted file mode 100644 index ec895b7e07..0000000000 --- a/Lib/lib-old/dump.py +++ /dev/null @@ -1,63 +0,0 @@ -# Module 'dump' -# -# Print python code that reconstructs a variable. -# This only works in certain cases. -# -# It works fine for: -# - ints and floats (except NaNs and other weird things) -# - strings -# - compounds and lists, provided it works for all their elements -# - imported modules, provided their name is the module name -# -# It works for top-level dictionaries but not for dictionaries -# contained in other objects (could be made to work with some hassle -# though). -# -# It does not work for functions (all sorts), classes, class objects, -# windows, files etc. -# -# Finally, objects referenced by more than one name or contained in more -# than one other object lose their sharing property (this is bad for -# strings used as exception identifiers, for instance). - -# Dump a whole symbol table -# -def dumpsymtab(dict): - for key in dict.keys(): - dumpvar(key, dict[key]) - -# Dump a single variable -# -def dumpvar(name, x): - import sys - t = type(x) - if t == type({}): - print name, '= {}' - for key in x.keys(): - item = x[key] - if not printable(item): - print '#', - print name, '[', `key`, '] =', `item` - elif t in (type(''), type(0), type(0.0), type([]), type(())): - if not printable(x): - print '#', - print name, '=', `x` - elif t == type(sys): - print 'import', name, '#', x - else: - print '#', name, '=', x - -# check if a value is printable in a way that can be read back with input() -# -def printable(x): - t = type(x) - if t in (type(''), type(0), type(0.0)): - return 1 - if t in (type([]), type(())): - for item in x: - if not printable(item): - return 0 - return 1 - if x == {}: - return 1 - return 0 diff --git a/Lib/lib-old/grep.py b/Lib/lib-old/grep.py deleted file mode 100644 index f4666512b7..0000000000 --- a/Lib/lib-old/grep.py +++ /dev/null @@ -1,62 +0,0 @@ -# 'grep' - -import regex -from regex_syntax import * -import string - -opt_show_where = 0 -opt_show_filename = 0 -opt_show_lineno = 1 - -def grep(pat, *files): - return ggrep(RE_SYNTAX_GREP, pat, files) - -def egrep(pat, *files): - return ggrep(RE_SYNTAX_EGREP, pat, files) - -def emgrep(pat, *files): - return ggrep(RE_SYNTAX_EMACS, pat, files) - -def ggrep(syntax, pat, files): - if len(files) == 1 and type(files[0]) == type([]): - files = files[0] - global opt_show_filename - opt_show_filename = (len(files) != 1) - syntax = regex.set_syntax(syntax) - try: - prog = regex.compile(pat) - finally: - syntax = regex.set_syntax(syntax) - for filename in files: - fp = open(filename, 'r') - lineno = 0 - while 1: - line = fp.readline() - if not line: break - lineno = lineno + 1 - if prog.search(line) >= 0: - showline(filename, lineno, line, prog) - fp.close() - -def showline(filename, lineno, line, prog): - if line[-1:] == '\n': line = line[:-1] - if opt_show_lineno: - prefix = string.rjust(`lineno`, 3) + ': ' - else: - prefix = '' - if opt_show_filename: - prefix = filename + ': ' + prefix - print prefix + line - if opt_show_where: - start, end = prog.regs()[0] - line = line[:start] - if '\t' not in line: - prefix = ' ' * (len(prefix) + start) - else: - prefix = ' ' * len(prefix) - for c in line: - if c <> '\t': c = ' ' - prefix = prefix + c - if start == end: prefix = prefix + '\\' - else: prefix = prefix + '^'*(end-start) - print prefix diff --git a/Lib/lib-old/newdir.py b/Lib/lib-old/newdir.py deleted file mode 100644 index 26a7df0c1b..0000000000 --- a/Lib/lib-old/newdir.py +++ /dev/null @@ -1,75 +0,0 @@ -# New dir() function - - -# This should be the new dir(), except that it should still list -# the current local name space by default - -def listattrs(x): - try: - dictkeys = x.__dict__.keys() - except (AttributeError, TypeError): - dictkeys = [] - # - try: - methods = x.__methods__ - except (AttributeError, TypeError): - methods = [] - # - try: - members = x.__members__ - except (AttributeError, TypeError): - members = [] - # - try: - the_class = x.__class__ - except (AttributeError, TypeError): - the_class = None - # - try: - bases = x.__bases__ - except (AttributeError, TypeError): - bases = () - # - total = dictkeys + methods + members - if the_class: - # It's a class instace; add the class's attributes - # that are functions (methods)... - class_attrs = listattrs(the_class) - class_methods = [] - for name in class_attrs: - if is_function(getattr(the_class, name)): - class_methods.append(name) - total = total + class_methods - elif bases: - # It's a derived class; add the base class attributes - for base in bases: - base_attrs = listattrs(base) - total = total + base_attrs - total.sort() - return total - i = 0 - while i+1 < len(total): - if total[i] == total[i+1]: - del total[i+1] - else: - i = i+1 - return total - - -# Helper to recognize functions - -def is_function(x): - return type(x) == type(is_function) - - -# Approximation of builtin dir(); but note that this lists the user's -# variables by default, not the current local name space. - -def dir(*args): - if len(args) > 0: - if len(args) == 1: - args = args[0] - return listattrs(args) - else: - import __main__ - return listattrs(__main__) diff --git a/Lib/lib-old/packmail.py b/Lib/lib-old/packmail.py deleted file mode 100644 index d612c88a8e..0000000000 --- a/Lib/lib-old/packmail.py +++ /dev/null @@ -1,88 +0,0 @@ -# Module 'packmail' -- create a self-unpacking shell archive. - -# This module works on UNIX and on the Mac; the archives can unpack -# themselves only on UNIX. - -import os -from stat import ST_MTIME -import string - -# Print help -def help(): - print 'All fns have a file open for writing as first parameter' - print 'pack(f, fullname, name): pack fullname as name' - print 'packsome(f, directory, namelist): selected files from directory' - print 'packall(f, directory): pack all files from directory' - print 'packnotolder(f, directory, name): pack all files from directory' - print ' that are not older than a file there' - print 'packtree(f, directory): pack entire directory tree' - -# Pack one file -def pack(outfp, file, name): - fp = open(file, 'r') - outfp.write('echo ' + name + '\n') - outfp.write('sed "s/^X//" >' + name + ' <<"!"\n') - while 1: - line = fp.readline() - if not line: break - if line[-1:] <> '\n': - line = line + '\n' - outfp.write('X' + line) - outfp.write('!\n') - fp.close() - -# Pack some files from a directory -def packsome(outfp, dirname, names): - for name in names: - print name - file = os.path.join(dirname, name) - pack(outfp, file, name) - -# Pack all files from a directory -def packall(outfp, dirname): - names = os.listdir(dirname) - names.sort() - packsome(outfp, dirname, names) - -# Pack all files from a directory that are not older than a give one -def packnotolder(outfp, dirname, oldest): - names = os.listdir(dirname) - oldest = os.path.join(dirname, oldest) - st = os.stat(oldest) - mtime = st[ST_MTIME] - todo = [] - for name in names: - print name, '...', - st = os.stat(os.path.join(dirname, name)) - if st[ST_MTIME] >= mtime: - print 'Yes.' - todo.append(name) - else: - print 'No.' - todo.sort() - packsome(outfp, dirname, todo) - -# Pack a whole tree (no exceptions) -def packtree(outfp, dirname): - print 'packtree', dirname - outfp.write('mkdir ' + unixfix(dirname) + '\n') - names = os.listdir(dirname) - subdirs = [] - for name in names: - fullname = os.path.join(dirname, name) - if os.path.isdir(fullname): - subdirs.append(fullname) - else: - print 'pack', fullname - pack(outfp, fullname, unixfix(fullname)) - for subdirname in subdirs: - packtree(outfp, subdirname) - -def unixfix(name): - comps = string.splitfields(name, os.sep) - res = '' - for comp in comps: - if comp: - if res: res = res + '/' - res = res + comp - return res diff --git a/Lib/lib-old/rand.py b/Lib/lib-old/rand.py deleted file mode 100644 index c299d0a9a9..0000000000 --- a/Lib/lib-old/rand.py +++ /dev/null @@ -1,13 +0,0 @@ -# Module 'rand' -# Don't use unless you want compatibility with C's rand()! - -import whrandom - -def srand(seed): - whrandom.seed(seed%256, seed/256%256, seed/65536%256) - -def rand(): - return int(whrandom.random() * 32768.0) % 32768 - -def choice(seq): - return seq[rand() % len(seq)] diff --git a/Lib/lib-old/tb.py b/Lib/lib-old/tb.py deleted file mode 100644 index 6b9cd9a53f..0000000000 --- a/Lib/lib-old/tb.py +++ /dev/null @@ -1,173 +0,0 @@ -# Print tracebacks, with a dump of local variables. -# Also an interactive stack trace browser. - -import sys -import os -from stat import * -import string -import linecache - -def br(): browser(sys.last_traceback) - -def tb(): printtb(sys.last_traceback) - -def browser(tb): - if not tb: - print 'No traceback.' - return - tblist = [] - while tb: - tblist.append(tb) - tb = tb.tb_next - ptr = len(tblist)-1 - tb = tblist[ptr] - while 1: - if tb <> tblist[ptr]: - tb = tblist[ptr] - print `ptr` + ':', - printtbheader(tb) - try: - line = raw_input('TB: ') - except KeyboardInterrupt: - print '\n[Interrupted]' - break - except EOFError: - print '\n[EOF]' - break - cmd = string.strip(line) - if cmd: - if cmd == 'quit': - break - elif cmd == 'list': - browserlist(tb) - elif cmd == 'up': - if ptr-1 >= 0: ptr = ptr-1 - else: print 'Bottom of stack.' - elif cmd == 'down': - if ptr+1 < len(tblist): ptr = ptr+1 - else: print 'Top of stack.' - elif cmd == 'locals': - printsymbols(tb.tb_frame.f_locals) - elif cmd == 'globals': - printsymbols(tb.tb_frame.f_globals) - elif cmd in ('?', 'help'): - browserhelp() - else: - browserexec(tb, cmd) - -def browserlist(tb): - filename = tb.tb_frame.f_code.co_filename - lineno = tb.tb_lineno - last = lineno - first = max(1, last-10) - for i in range(first, last+1): - if i == lineno: prefix = '***' + string.rjust(`i`, 4) + ':' - else: prefix = string.rjust(`i`, 7) + ':' - line = linecache.getline(filename, i) - if line[-1:] == '\n': line = line[:-1] - print prefix + line - -def browserexec(tb, cmd): - locals = tb.tb_frame.f_locals - globals = tb.tb_frame.f_globals - try: - exec(cmd+'\n', globals, locals) - except: - print '*** Exception:', - print sys.exc_type, - if sys.exc_value <> None: - print ':', sys.exc_value, - print - print 'Type help to get help.' - -def browserhelp(): - print - print ' This is the traceback browser. Commands are:' - print ' up : move one level up in the call stack' - print ' down : move one level down in the call stack' - print ' locals : print all local variables at this level' - print ' globals : print all global variables at this level' - print ' list : list source code around the failure' - print ' help : print help (what you are reading now)' - print ' quit : back to command interpreter' - print ' Typing any other 1-line statement will execute it' - print ' using the current level\'s symbol tables' - print - -def printtb(tb): - while tb: - print1tb(tb) - tb = tb.tb_next - -def print1tb(tb): - printtbheader(tb) - if tb.tb_frame.f_locals is not tb.tb_frame.f_globals: - printsymbols(tb.tb_frame.f_locals) - -def printtbheader(tb): - filename = tb.tb_frame.f_code.co_filename - lineno = tb.tb_lineno - info = '"' + filename + '"(' + `lineno` + ')' - line = linecache.getline(filename, lineno) - if line: - info = info + ': ' + string.strip(line) - print info - -def printsymbols(d): - keys = d.keys() - keys.sort() - for name in keys: - print ' ' + string.ljust(name, 12) + ':', - printobject(d[name], 4) - print - -def printobject(v, maxlevel): - if v == None: - print 'None', - elif type(v) in (type(0), type(0.0)): - print v, - elif type(v) == type(''): - if len(v) > 20: - print `v[:17] + '...'`, - else: - print `v`, - elif type(v) == type(()): - print '(', - printlist(v, maxlevel) - print ')', - elif type(v) == type([]): - print '[', - printlist(v, maxlevel) - print ']', - elif type(v) == type({}): - print '{', - printdict(v, maxlevel) - print '}', - else: - print v, - -def printlist(v, maxlevel): - n = len(v) - if n == 0: return - if maxlevel <= 0: - print '...', - return - for i in range(min(6, n)): - printobject(v[i], maxlevel-1) - if i+1 < n: print ',', - if n > 6: print '...', - -def printdict(v, maxlevel): - keys = v.keys() - n = len(keys) - if n == 0: return - if maxlevel <= 0: - print '...', - return - keys.sort() - for i in range(min(6, n)): - key = keys[i] - print `key` + ':', - printobject(v[key], maxlevel-1) - if i+1 < n: print ',', - if n > 6: print '...', diff --git a/Lib/lib-old/util.py b/Lib/lib-old/util.py deleted file mode 100644 index 6cb1433426..0000000000 --- a/Lib/lib-old/util.py +++ /dev/null @@ -1,25 +0,0 @@ -# Module 'util' -- some useful functions that don't fit elsewhere - -# NB: These are now built-in functions, but this module is provided -# for compatibility. Don't use in new programs unless you need backward -# compatibility (i.e. need to run with old interpreters). - - -# Remove an item from a list. -# No complaints if it isn't in the list at all. -# If it occurs more than once, remove the first occurrence. -# -def remove(item, list): - if item in list: list.remove(item) - - -# Return a string containing a file's contents. -# -def readfile(fn): - return readopenfile(open(fn, 'r')) - - -# Read an open file until EOF. -# -def readopenfile(fp): - return fp.read() diff --git a/Lib/lib-old/whatsound.py b/Lib/lib-old/whatsound.py deleted file mode 100644 index b7b349c5ba..0000000000 --- a/Lib/lib-old/whatsound.py +++ /dev/null @@ -1,270 +0,0 @@ -# This module contains several routines that help recognizing sound -# files. -# -# Function whathdr() recognizes various types of sound file headers. -# It understands almost all headers that SOX can decode. -# -# The return tuple contains the following items, in this order: -# - file type (as SOX understands it) -# - sampling rate (0 if unknown or hard to decode) -# - number of channels (0 if unknown or hard to decode) -# - number of frames in the file (-1 if unknown or hard to decode) -# - number of bits/sample, or 'U' for U-LAW, or 'A' for A-LAW -# -# If the file doesn't have a recognizable type, it returns None. -# If the file can't be opened, IOError is raised. -# -# To compute the total time, divide the number of frames by the -# sampling rate (a frame contains a sample for each channel). -# -# Function whatraw() calls the "whatsound" program and interprets its -# output. You'll have to guess the sampling rate by listening though! -# -# Function what() calls whathdr() and if it doesn't recognize the file -# then calls whatraw(). -# -# Finally, the function test() is a simple main program that calls -# what() for all files mentioned on the argument list. For directory -# arguments it calls what() for all files in that directory. Default -# argument is "." (testing all files in the current directory). The -# option -r tells it to recurse down directories found inside -# explicitly given directories. -# -# The file structure is top-down except that the test program and its -# subroutine come last. - - -#------------------------------------------------------# -# Guess the type of any sound file, raw or with header # -#------------------------------------------------------# - -def what(filename): - res = whathdr(filename) - if not res: - res = whatraw(filename) - return res - - -#-----------------------------# -# Guess the type of raw sound # -#-----------------------------# - -def whatraw(filename): - # Assume it's always 1 channel, byte-sized samples - # Don't assume anything about the rate - import os - from stat import ST_SIZE - # XXX "whatsound" should be part of the distribution somehow... - cmd = 'whatsound ' + filename + ' 2>/dev/null' - cmd = 'PATH=$PATH:/ufs/guido/bin/sgi\n' + cmd - pipe = os.popen(cmd, 'r') - data = pipe.read() - sts = pipe.close() - if sts: - return None - if data[:13] == '-t raw -b -s ': - type = 'sb' - sample_size = 8 - elif data[:13] == '-t raw -b -u ': - type = 'ub' - sample_size = 8 - elif data[:13] == '-t raw -b -U ': - type = 'ul' - sample_size = 'U' - else: - return None - try: - frame_count = os.stat(filename)[ST_SIZE] - except IOError: - frame_count = -1 - return type, 0, 1, frame_count, sample_size - - -#-------------------------# -# Recognize sound headers # -#-------------------------# - -def whathdr(filename): - f = open(filename, 'r') - h = f.read(512) - for tf in tests: - res = tf(h, f) - if res: - return res - return None - - -#-----------------------------------# -# Subroutines per sound header type # -#-----------------------------------# - -tests = [] - -def test_aifc(h, f): - import aifc - if h[:4] <> 'FORM': - return None - if h[8:12] == 'AIFC': - fmt = 'aifc' - elif h[8:12] == 'AIFF': - fmt = 'aiff' - else: - return None - f.seek(0) - try: - a = aifc.openfp(f, 'r') - except (EOFError, aifc.Error): - return None - return (fmt, a.getframerate(), a.getnchannels(), \ - a.getnframes(), 8*a.getsampwidth()) - -tests.append(test_aifc) - - -def test_au(h, f): - if h[:4] == '.snd': - f = get_long_be - elif h[:4] in ('\0ds.', 'dns.'): - f = get_long_le - else: - return None - type = 'au' - hdr_size = f(h[4:8]) - data_size = f(h[8:12]) - encoding = f(h[12:16]) - rate = f(h[16:20]) - nchannels = f(h[20:24]) - sample_size = 1 # default - if encoding == 1: - sample_bits = 'U' - elif encoding == 2: - sample_bits = 8 - elif encoding == 3: - sample_bits = 16 - sample_size = 2 - else: - sample_bits = '?' - frame_size = sample_size * nchannels - return type, rate, nchannels, data_size/frame_size, sample_bits - -tests.append(test_au) - - -def test_hcom(h, f): - if h[65:69] <> 'FSSD' or h[128:132] <> 'HCOM': - return None - divisor = get_long_be(h[128+16:128+20]) - return 'hcom', 22050/divisor, 1, -1, 8 - -tests.append(test_hcom) - - -def test_voc(h, f): - if h[:20] <> 'Creative Voice File\032': - return None - sbseek = get_short_le(h[20:22]) - rate = 0 - if 0 <= sbseek < 500 and h[sbseek] == '\1': - ratecode = ord(h[sbseek+4]) - rate = int(1000000.0 / (256 - ratecode)) - return 'voc', rate, 1, -1, 8 - -tests.append(test_voc) - - -def test_wav(h, f): - # 'RIFF' 'WAVE' 'fmt ' - if h[:4] <> 'RIFF' or h[8:12] <> 'WAVE' or h[12:16] <> 'fmt ': - return None - style = get_short_le(h[20:22]) - nchannels = get_short_le(h[22:24]) - rate = get_long_le(h[24:28]) - sample_bits = get_short_le(h[34:36]) - return 'wav', rate, nchannels, -1, sample_bits - -tests.append(test_wav) - - -def test_8svx(h, f): - if h[:4] <> 'FORM' or h[8:12] <> '8SVX': - return None - # Should decode it to get #channels -- assume always 1 - return '8svx', 0, 1, 0, 8 - -tests.append(test_8svx) - - -def test_sndt(h, f): - if h[:5] == 'SOUND': - nsamples = get_long_le(h[8:12]) - rate = get_short_le(h[20:22]) - return 'sndt', rate, 1, nsamples, 8 - -tests.append(test_sndt) - - -def test_sndr(h, f): - if h[:2] == '\0\0': - rate = get_short_le(h[2:4]) - if 4000 <= rate <= 25000: - return 'sndr', rate, 1, -1, 8 - -tests.append(test_sndr) - - -#---------------------------------------------# -# Subroutines to extract numbers from strings # -#---------------------------------------------# - -def get_long_be(s): - return (ord(s[0])<<24) | (ord(s[1])<<16) | (ord(s[2])<<8) | ord(s[3]) - -def get_long_le(s): - return (ord(s[3])<<24) | (ord(s[2])<<16) | (ord(s[1])<<8) | ord(s[0]) - -def get_short_be(s): - return (ord(s[0])<<8) | ord(s[1]) - -def get_short_le(s): - return (ord(s[1])<<8) | ord(s[0]) - - -#--------------------# -# Small test program # -#--------------------# - -def test(): - import sys - recursive = 0 - if sys.argv[1:] and sys.argv[1] == '-r': - del sys.argv[1:2] - recursive = 1 - try: - if sys.argv[1:]: - testall(sys.argv[1:], recursive, 1) - else: - testall(['.'], recursive, 1) - except KeyboardInterrupt: - sys.stderr.write('\n[Interrupted]\n') - sys.exit(1) - -def testall(list, recursive, toplevel): - import sys - import os - for filename in list: - if os.path.isdir(filename): - print filename + '/:', - if recursive or toplevel: - print 'recursing down:' - import glob - names = glob.glob(os.path.join(filename, '*')) - testall(names, recursive, 0) - else: - print '*** directory (use -r) ***' - else: - print filename + ':', - sys.stdout.flush() - try: - print what(filename) - except IOError: - print '*** not found ***' diff --git a/Lib/lib-stdwin/Abstract.py b/Lib/lib-stdwin/Abstract.py deleted file mode 100644 index 51bd305a86..0000000000 --- a/Lib/lib-stdwin/Abstract.py +++ /dev/null @@ -1,63 +0,0 @@ -# Abstract classes for parents and children. -# -# Do not use as base class -- this is for documentation only. -# -# Note that the tree must be built top down (create the parent, -# then add the children). -# -# Also note that the creation methods are not standardized -- -# these have extra parameters dependent on the widget type. -# For historical reasons, button creation methods are called -# define() while split creation methods are called create(). - -class AbstractParent: - # - # Upcalls from child to parent - # - def addchild(self, child): unimpl() - def delchild(self, child): unimpl() - # - def need_mouse(self, child): unimpl() - def no_mouse(self, child): unimpl() - # - def need_timer(self, child): unimpl() - def no_timer(self, child): unimpl() - # - # XXX need_kbd, no_kbd; focus??? - # - def begindrawing(self): return unimpl() - def beginmeasuring(self): return unimpl() - def getwindow(self): return unimpl() # Only for very special cases - # - def change(self, area): unimpl() - def scroll(self, area, (dh, dv)): unimpl() - def settimer(self, itimer): unimpl() - -class AbstractChild: - # - # Downcalls from parent to child - # - def destroy(self): unimpl() - # - def realize(self): return unimpl() - def getminsize(self, m, (width, height)): return unimpl() - def getbounds(self): return unimpl() - def setbounds(self, bounds): unimpl() - def draw(self, d, area): unimpl() - # - # Downcalls only made after certain upcalls - # - def mouse_down(self, detail): unimpl() - def mouse_move(self, detail): unimpl() - def mouse_up(self, detail): unimpl() - # - def timer(self): unimpl() - -# A "Split" is a child that manages one or more children. -# (This terminology is due to DEC SRC, except for CSplits.) -# A child of a split may be another split, a button, a slider, etc. -# Certain upcalls and downcalls can be handled transparently, but -# for others (e.g., all geometry related calls) this is not possible. - -class AbstractSplit(AbstractChild, AbstractParent): - pass diff --git a/Lib/lib-stdwin/BoxParent.py b/Lib/lib-stdwin/BoxParent.py deleted file mode 100644 index c792731c5b..0000000000 --- a/Lib/lib-stdwin/BoxParent.py +++ /dev/null @@ -1,40 +0,0 @@ -from TransParent import TransParent - -class BoxParent(TransParent): - # - def create(self, parent, (dh, dv)): - self = TransParent.create(self, parent) - self.dh = dh - self.dv = dv - return self - # - def getminsize(self, m, (width, height)): - width = max(0, width - 2*self.dh) - height = max(0, height - 2*self.dv) - width, height = self.child.getminsize(m, (width, height)) - return width + 2*self.dh, height + 2*self.dv - # - def setbounds(self, bounds): - (left, top), (right, bottom) = bounds - self.bounds = bounds - left = min(right, left + self.dh) - top = min(bottom, top + self.dv) - right = max(left, right - self.dh) - bottom = max(top, bottom - self.dv) - self.innerbounds = (left, top), (right, bottom) - self.child.setbounds(self.innerbounds) - # - def getbounds(self): - return self.bounds - # - def draw(self, d, area): - (left, top), (right, bottom) = self.bounds - left = left + 1 - top = top + 1 - right = right - 1 - bottom = bottom - 1 - d.box((left, top), (right, bottom)) - TransParent.draw(self, d, area) # XXX clip to innerbounds? - # - # XXX should scroll clip to innerbounds??? - # XXX currently the only user restricts itself to child's bounds diff --git a/Lib/lib-stdwin/Buttons.py b/Lib/lib-stdwin/Buttons.py deleted file mode 100644 index 9a9970789b..0000000000 --- a/Lib/lib-stdwin/Buttons.py +++ /dev/null @@ -1,411 +0,0 @@ -# Module 'Buttons' - - -# Import module 'rect' renamed as '_rect' to avoid exporting it on -# 'from Buttons import *' -# -import rect -_rect = rect -del rect - - -# Field indices in mouse event detail -# -_HV = 0 -_CLICKS = 1 -_BUTTON = 2 -_MASK = 3 - - -# LabelAppearance provides defaults for all appearance methods. -# selected state not visible -# disabled --> crossed out -# hilited --> inverted -# -class LabelAppearance: - # - # Initialization - # - def init_appearance(self): - self.bounds = _rect.empty - self.enabled = 1 - self.hilited = 0 - self.selected = 0 - self.text = '' - # - # Size enquiry - # - def getminsize(self, m, (width, height)): - width = max(width, m.textwidth(self.text) + 6) - height = max(height, m.lineheight() + 6) - return width, height - # - def getbounds(self): - return self.bounds - # - # Changing the parameters - # - def settext(self, text): - self.text = text - if self.bounds <> _rect.empty: - self.recalctextpos() - self.redraw() - # - def setbounds(self, bounds): - self.bounds = bounds - if self.bounds <> _rect.empty: - self.recalc() - # - def realize(self): - pass - # - # Changing the state bits - # - def enable(self, flag): - if flag <> self.enabled: - self.enabled = flag - if self.bounds <> _rect.empty: - self.flipenable(self.parent.begindrawing()) - # - def hilite(self, flag): - if flag <> self.hilited: - self.hilited = flag - if self.bounds <> _rect.empty: - self.fliphilite(self.parent.begindrawing()) - # - def select(self, flag): - if flag <> self.selected: - self.selected = flag - if self.bounds <> _rect.empty: - self.redraw() - # - # Recalculate the box bounds and text position. - # This can be overridden by buttons that draw different boxes - # or want their text in a different position. - # - def recalc(self): - if self.bounds <> _rect.empty: - self.recalcbounds() - self.recalctextpos() - # - def recalcbounds(self): - self.hilitebounds = _rect.inset(self.bounds, (3, 3)) - self.crossbounds = self.bounds - # - def recalctextpos(self): - (left, top), (right, bottom) = self.bounds - m = self.parent.beginmeasuring() - h = (left + right - m.textwidth(self.text)) / 2 - v = (top + bottom - m.lineheight()) / 2 - self.textpos = h, v - # - # Generic drawing interface. - # Do not override redraw() or draw() methods; override drawit() c.s. - # - def redraw(self): - if self.bounds <> _rect.empty: - d = self.parent.begindrawing() - d.erase(self.bounds) - self.draw(d, self.bounds) - # - def draw(self, d, area): - area = _rect.intersect([area, self.bounds]) - if area == _rect.empty: - return - d.cliprect(area) - self.drawit(d) - d.noclip() - # - # The drawit() method is fairly generic but may be overridden. - # - def drawit(self, d): - self.drawpict(d) - if self.text: - d.text(self.textpos, self.text) - if not self.enabled: - self.flipenable(d) - if self.hilited: - self.fliphilite(d) - # - # Default drawing detail functions. - # Overriding these is normally sufficient to get different - # appearances. - # - def drawpict(self, d): - pass - # - def flipenable(self, d): - _xorcross(d, self.crossbounds) - # - def fliphilite(self, d): - d.invert(self.hilitebounds) - - -# A Strut is a label with no width of its own. - -class StrutAppearance(LabelAppearance): - # - def getminsize(self, m, (width, height)): - height = max(height, m.lineheight() + 6) - return width, height - # - - -# ButtonAppearance displays a centered string in a box. -# selected --> bold border -# disabled --> crossed out -# hilited --> inverted -# -class ButtonAppearance(LabelAppearance): - # - def drawpict(self, d): - d.box(_rect.inset(self.bounds, (1, 1))) - if self.selected: - # Make a thicker box - d.box(self.bounds) - d.box(_rect.inset(self.bounds, (2, 2))) - d.box(_rect.inset(self.bounds, (3, 3))) - # - - -# CheckAppearance displays a small square box and a left-justified string. -# selected --> a cross appears in the box -# disabled --> whole button crossed out -# hilited --> box is inverted -# -class CheckAppearance(LabelAppearance): - # - def getminsize(self, m, (width, height)): - minwidth = m.textwidth(self.text) + 6 - minheight = m.lineheight() + 6 - width = max(width, minwidth + minheight + m.textwidth(' ')) - height = max(height, minheight) - return width, height - # - def drawpict(self, d): - d.box(self.boxbounds) - if self.selected: _xorcross(d, self.boxbounds) - # - def recalcbounds(self): - LabelAppearance.recalcbounds(self) - (left, top), (right, bottom) = self.bounds - self.size = bottom - top - 4 - self.boxbounds = (left+2, top+2), (left+2+self.size, bottom-2) - self.hilitebounds = self.boxbounds - # - def recalctextpos(self): - m = self.parent.beginmeasuring() - (left, top), (right, bottom) = self.boxbounds - h = right + m.textwidth(' ') - v = top + (self.size - m.lineheight()) / 2 - self.textpos = h, v - # - - -# RadioAppearance displays a round indicator and a left-justified string. -# selected --> a dot appears in the indicator -# disabled --> whole button crossed out -# hilited --> indicator is inverted -# -class RadioAppearance(CheckAppearance): - # - def drawpict(self, d): - (left, top), (right, bottom) = self.boxbounds - radius = self.size / 2 - center = left + radius, top + radius - d.circle(center, radius) - if self.selected: - d.fillcircle(center, radius*3/5) - # - - -# NoReactivity ignores mouse events. -# -class NoReactivity: - def init_reactivity(self): pass - - -# BaseReactivity defines hooks and asks for mouse events, -# but provides only dummy mouse event handlers. -# The trigger methods call the corresponding hooks set by the user. -# Hooks (and triggers) mean the following: -# down_hook called on some mouse-down events -# move_hook called on some mouse-move events -# up_hook called on mouse-up events -# on_hook called for buttons with on/off state, when it goes on -# hook called when a button 'fires' or a radiobutton goes on -# There are usually extra conditions, e.g., hooks are only called -# when the button is enabled, or active, or selected (on). -# -class BaseReactivity: - # - def init_reactivity(self): - self.down_hook = self.move_hook = self.up_hook = \ - self.on_hook = self.off_hook = \ - self.hook = self.active = 0 - self.parent.need_mouse(self) - # - def mousetest(self, hv): - return _rect.pointinrect(hv, self.bounds) - # - def mouse_down(self, detail): - pass - # - def mouse_move(self, detail): - pass - # - def mouse_up(self, detail): - pass - # - def down_trigger(self): - if self.down_hook: self.down_hook(self) - # - def move_trigger(self): - if self.move_hook: self.move_hook(self) - # - def up_trigger(self): - if self.up_hook: self.up_hook(self) - # - def on_trigger(self): - if self.on_hook: self.on_hook(self) - # - def off_trigger(self): - if self.off_hook: self.off_hook(self) - # - def trigger(self): - if self.hook: self.hook(self) - - -# ToggleReactivity acts like a simple pushbutton. -# It toggles its hilite state on mouse down events. -# -class ToggleReactivity(BaseReactivity): - # - def mouse_down(self, detail): - if self.enabled and self.mousetest(detail[_HV]): - self.active = 1 - self.hilite(not self.hilited) - self.down_trigger() - # - def mouse_move(self, detail): - if self.active: - self.move_trigger() - # - def mouse_up(self, detail): - if self.active: - self.up_trigger() - self.active = 0 - # - def down_trigger(self): - if self.hilited: - self.on_trigger() - else: - self.off_trigger() - self.trigger() - # - - -# TriggerReactivity acts like a fancy pushbutton. -# It hilites itself while the mouse is down within its bounds. -# -class TriggerReactivity(BaseReactivity): - # - def mouse_down(self, detail): - if self.enabled and self.mousetest(detail[_HV]): - self.active = 1 - self.hilite(1) - self.down_trigger() - # - def mouse_move(self, detail): - if self.active: - self.hilite(self.mousetest(detail[_HV])) - if self.hilited: - self.move_trigger() - # - def mouse_up(self, detail): - if self.active: - self.hilite(self.mousetest(detail[_HV])) - if self.hilited: - self.up_trigger() - self.trigger() - self.active = 0 - self.hilite(0) - # - - -# CheckReactivity handles mouse events like TriggerReactivity, -# It overrides the up_trigger method to flip its selected state. -# -class CheckReactivity(TriggerReactivity): - # - def up_trigger(self): - self.select(not self.selected) - if self.selected: - self.on_trigger() - else: - self.off_trigger() - self.trigger() - - -# RadioReactivity turns itself on and the other buttons in its group -# off when its up_trigger method is called. -# -class RadioReactivity(TriggerReactivity): - # - def init_reactivity(self): - TriggerReactivity.init_reactivity(self) - self.group = [] - # - def up_trigger(self): - for b in self.group: - if b <> self: - if b.selected: - b.select(0) - b.off_trigger() - self.select(1) - self.on_trigger() - self.trigger() - - -# Auxiliary class for 'define' method. -# Call the initializers in the right order. -# -class Define: - # - def define(self, parent): - self.parent = parent - parent.addchild(self) - self.init_appearance() - self.init_reactivity() - return self - # - def destroy(self): - self.parent = 0 - # - def definetext(self, parent, text): - self = self.define(parent) - self.settext(text) - return self - - -# Subroutine to cross out a rectangle. -# -def _xorcross(d, bounds): - ((left, top), (right, bottom)) = bounds - # This is s bit funny to make it look better - left = left + 2 - right = right - 2 - top = top + 2 - bottom = bottom - 3 - d.xorline(((left, top), (right, bottom))) - d.xorline((left, bottom), (right, top)) - - -# Ready-made button classes. -# -class Label(NoReactivity, LabelAppearance, Define): pass -class Strut(NoReactivity, StrutAppearance, Define): pass -class PushButton(TriggerReactivity, ButtonAppearance, Define): pass -class CheckButton(CheckReactivity, CheckAppearance, Define): pass -class RadioButton(RadioReactivity, RadioAppearance, Define): pass -class ToggleButton(ToggleReactivity, ButtonAppearance, Define): pass diff --git a/Lib/lib-stdwin/CSplit.py b/Lib/lib-stdwin/CSplit.py deleted file mode 100644 index 90d51119c3..0000000000 --- a/Lib/lib-stdwin/CSplit.py +++ /dev/null @@ -1,69 +0,0 @@ -# A CSplit is a Clock-shaped split: the children are grouped in a circle. -# The numbering is a little different from a real clock: the 12 o'clock -# position is called 0, not 12. This is a little easier since Python -# usually counts from zero. (BTW, there needn't be exactly 12 children.) - - -from math import pi, sin, cos -from Split import Split - -class CSplit(Split): - # - def getminsize(self, m, (width, height)): - # Since things look best if the children are spaced evenly - # along the circle (and often all children have the same - # size anyway) we compute the max child size and assume - # this is each child's size. - for child in self.children: - wi, he = child.getminsize(m, (0, 0)) - width = max(width, wi) - height = max(height, he) - # In approximation, the diameter of the circle we need is - # (diameter of box) * (#children) / pi. - # We approximate pi by 3 (so we slightly overestimate - # our minimal size requirements -- not so bad). - # Because the boxes stick out of the circle we add the - # box size to each dimension. - # Because we really deal with ellipses, do everything - # separate in each dimension. - n = len(self.children) - return width + (width*n + 2)/3, height + (height*n + 2)/3 - # - def getbounds(self): - return self.bounds - # - def setbounds(self, bounds): - self.bounds = bounds - # Place the children. This involves some math. - # Compute center positions for children as if they were - # ellipses with a diameter about 1/N times the - # circumference of the big ellipse. - # (There is some rounding involved to make it look - # reasonable for small and large N alike.) - # XXX One day Python will have automatic conversions... - n = len(self.children) - fn = float(n) - if n == 0: return - (left, top), (right, bottom) = bounds - width, height = right-left, bottom-top - child_width, child_height = width*3/(n+4), height*3/(n+4) - half_width, half_height = \ - float(width-child_width)/2.0, \ - float(height-child_height)/2.0 - center_h, center_v = center = (left+right)/2, (top+bottom)/2 - fch, fcv = float(center_h), float(center_v) - alpha = 2.0 * pi / fn - for i in range(n): - child = self.children[i] - fi = float(i) - fh, fv = \ - fch + half_width*sin(fi*alpha), \ - fcv - half_height*cos(fi*alpha) - left, top = \ - int(fh) - child_width/2, \ - int(fv) - child_height/2 - right, bottom = \ - left + child_width, \ - top + child_height - child.setbounds(((left, top), (right, bottom))) - # diff --git a/Lib/lib-stdwin/DirList.py b/Lib/lib-stdwin/DirList.py deleted file mode 100644 index 446d33b04c..0000000000 --- a/Lib/lib-stdwin/DirList.py +++ /dev/null @@ -1,58 +0,0 @@ -# DirList -- Directory Listing widget - -# XXX Displays messy paths when following '..' - -import os -import stdwin, rect -from stdwinevents import * -from Buttons import PushButton -from WindowParent import WindowParent -from HVSplit import HSplit, VSplit - -class DirList(VSplit): - # - def create(self, parent, dirname): - self = VSplit.create(self, parent) - names = os.listdir(dirname) - for name in names: - if os.path.isdir(os.path.join(dirname, name)): - fullname = os.path.join(dirname, name) - btn = SubdirButton().definetext(self, fullname) - elif name[-3:] == '.py': - btn = ModuleButton().definetext(self, name) - else: - btn = FileButton().definetext(self, name) - return self - # - -class DirListWindow(WindowParent): - # - def create(self, dirname): - self = WindowParent.create(self, dirname, (0, 0)) - child = DirList().create(self, dirname) - self.realize() - return self - # - -class SubdirButton(PushButton): - # - def drawpict(self, d): - PushButton.drawpict(self, d) - d.box(rect.inset(self.bounds, (3, 1))) - # - def up_trigger(self): - window = DirListWindow().create(self.text) - # - -class FileButton(PushButton): - # - def up_trigger(self): - stdwin.fleep() - # - -class ModuleButton(FileButton): - # - def drawpict(self, d): - PushButton.drawpict(self, d) - d.box(rect.inset(self.bounds, (1, 3))) - # diff --git a/Lib/lib-stdwin/FormSplit.py b/Lib/lib-stdwin/FormSplit.py deleted file mode 100644 index 271cb23fc1..0000000000 --- a/Lib/lib-stdwin/FormSplit.py +++ /dev/null @@ -1,58 +0,0 @@ -# A FormSplit lets you place its children exactly where you want them -# (including silly places!). -# It does no explicit geometry management except moving its children -# when it is moved. -# The interface to place children is as follows. -# Before you add a child, you may specify its (left, top) position -# relative to the FormSplit. If you don't specify a position for -# a child, it goes right below the previous child; the first child -# goes to (0, 0) by default. -# NB: This places data attributes named form_* on its children. -# XXX Yes, I know, there should be options to do all sorts of relative -# placement, but for now this will do. - -from Split import Split - -class FormSplit(Split): - # - def create(self, parent): - self.next_left = self.next_top = 0 - self.last_child = None - return Split.create(self, parent) - # - def getminsize(self, m, sugg_size): - max_width, max_height = 0, 0 - for c in self.children: - c.form_width, c.form_height = c.getminsize(m, (0, 0)) - max_width = max(max_width, c.form_width + c.form_left) - max_height = max(max_height, \ - c.form_height + c.form_top) - return max_width, max_height - # - def getbounds(self): - return self.bounds - # - def setbounds(self, bounds): - self.bounds = bounds - fleft, ftop = bounds[0] - for c in self.children: - left, top = c.form_left + fleft, c.form_top + ftop - right, bottom = left + c.form_width, top + c.form_height - c.setbounds(((left, top), (right, bottom))) - # - def placenext(self, left, top): - self.next_left = left - self.next_top = top - self.last_child = None - # - def addchild(self, child): - if self.last_child: - width, height = \ - self.last_child.getminsize(self.beginmeasuring(), \ - (0, 0)) - self.next_top = self.next_top + height - child.form_left = self.next_left - child.form_top = self.next_top - Split.addchild(self, child) - self.last_child = child - # diff --git a/Lib/lib-stdwin/HVSplit.py b/Lib/lib-stdwin/HVSplit.py deleted file mode 100644 index 62e0de75f7..0000000000 --- a/Lib/lib-stdwin/HVSplit.py +++ /dev/null @@ -1,62 +0,0 @@ -# HVSplit contains generic code for HSplit and VSplit. -# HSplit and VSplit are specializations to either dimension. - -# XXX This does not yet stretch/shrink children if there is too much -# XXX or too little space in the split dimension. -# XXX (NB There is no interface to ask children for stretch preferences.) - -from Split import Split - -class HVSplit(Split): - # - def create(self, parent, hv): - # hv is 0 for HSplit, 1 for VSplit - self = Split.create(self, parent) - self.hv = hv - return self - # - def getminsize(self, m, sugg_size): - hv, vh = self.hv, 1 - self.hv - size = [0, 0] - sugg_size = [sugg_size[0], sugg_size[1]] - sugg_size[hv] = 0 - sugg_size = sugg_size[0], sugg_size[1] # Make a tuple - for c in self.children: - csize = c.getminsize(m, sugg_size) - if csize[vh] > size[vh]: size[vh] = csize[vh] - size[hv] = size[hv] + csize[hv] - return size[0], size[1] - # - def getbounds(self): - return self.bounds - # - def setbounds(self, bounds): - self.bounds = bounds - hv, vh = self.hv, 1 - self.hv - mf = self.parent.beginmeasuring - begin, end = bounds - sugg_size = end[0] - begin[0], end[1] - begin[1] - size = self.getminsize(mf(), sugg_size) - origin = [begin[0], begin[1]] - sugg_size = [sugg_size[0], sugg_size[1]] # Make a list - sugg_size[hv] = 0 - sugg_size = sugg_size[0], sugg_size[1] # Make a tuple - for c in self.children: - size = c.getminsize(mf(), sugg_size) - corner = [0, 0] - corner[vh] = end[vh] - corner[hv] = origin[hv] + size[hv] - c.setbounds(((origin[0], origin[1]), \ - (corner[0], corner[1]))) - origin[hv] = corner[hv] - # XXX stretch - # XXX too-small - # - -class HSplit(HVSplit): - def create(self, parent): - return HVSplit.create(self, parent, 0) - -class VSplit(HVSplit): - def create(self, parent): - return HVSplit.create(self, parent, 1) diff --git a/Lib/lib-stdwin/Histogram.py b/Lib/lib-stdwin/Histogram.py deleted file mode 100644 index 74a75f374f..0000000000 --- a/Lib/lib-stdwin/Histogram.py +++ /dev/null @@ -1,36 +0,0 @@ -# Module 'Histogram' - -from Buttons import * - -# A Histogram displays a histogram of numeric data. -# -class HistogramAppearance(LabelAppearance, Define): - # - def define(self, parent): - Define.define(self, (parent, '')) - self.ydata = [] - self.scale = (0, 100) - return self - # - def setdata(self, ydata, scale): - self.ydata = ydata - self.scale = scale # (min, max) - self.parent.change(self.bounds) - # - def drawpict(self, d): - (left, top), (right, bottom) = self.bounds - min, max = self.scale - size = max-min - width, height = right-left, bottom-top - ydata = self.ydata - npoints = len(ydata) - v1 = top + height # constant - h1 = left # changed in loop - for i in range(npoints): - h0 = h1 - v0 = top + height - (ydata[i]-min)*height/size - h1 = left + (i+1) * width/npoints - d.paint((h0, v0), (h1, v1)) - # - -class Histogram(NoReactivity, HistogramAppearance): pass diff --git a/Lib/lib-stdwin/Sliders.py b/Lib/lib-stdwin/Sliders.py deleted file mode 100644 index cbf776daee..0000000000 --- a/Lib/lib-stdwin/Sliders.py +++ /dev/null @@ -1,174 +0,0 @@ -# Module 'Sliders' - - -import stdwin -from stdwinevents import * -import rect -from Buttons import * -from HVSplit import HSplit - - -# Field indices in event detail -# -_HV = 0 -_CLICKS = 1 -_BUTTON = 2 -_MASK = 3 - - -# DragSlider is the simplest possible slider. -# It looks like a button but dragging the mouse left or right -# changes the controlled value. -# It does not support any of the triggers or hooks defined by Buttons, -# but defines its own setval_trigger and setval_hook. -# -class DragSliderReactivity(BaseReactivity): - # - def mouse_down(self, detail): - h, v = hv = detail[_HV] - if self.enabled and self.mousetest(hv): - self.anchor = h - self.oldval = self.val - self.active = 1 - # - def mouse_move(self, detail): - if self.active: - h, v = detail[_HV] - self.setval(self.oldval + (h - self.anchor)) - # - def mouse_up(self, detail): - if self.active: - h, v = detail[_HV] - self.setval(self.oldval + (h - self.anchor)) - self.active = 0 - # - -class DragSliderAppearance(ButtonAppearance): - # - # INVARIANTS maintained by the setval method: - # - # self.min <= self.val <= self.max - # self.text = self.pretext + `self.val` + self.postext - # - # (Notice that unlike Python ranges, the end point belongs - # to the range.) - # - def init_appearance(self): - ButtonAppearance.init_appearance(self) - self.min = 0 - self.val = 0 - self.max = 100 - self.hook = 0 - self.pretext = self.postext = '' - self.recalctext() - # - # The 'get*' and 'set*' methods belong to the generic slider interface - # - def getval(self): return self.val - # - def sethook(self, hook): - self.hook = hook - # - def setminvalmax(self, min, val, max): - self.min = min - self.max = max - self.setval(val) - # - def settexts(self, pretext, postext): - self.pretext = pretext - self.postext = postext - self.recalctext() - # - def setval(self, val): - val = min(self.max, max(self.min, val)) - if val <> self.val: - self.val = val - self.recalctext() - self.trigger() - # - def trigger(self): - if self.hook: - self.hook(self) - # - def recalctext(self): - self.settext(self.pretext + `self.val` + self.postext) - # - -class DragSlider(DragSliderReactivity, DragSliderAppearance, Define): - def definetext(self, parent, text): - raise RuntimeError, 'DragSlider.definetext() not supported' - - -# Auxiliary class for PushButton incorporated in ComplexSlider -# -class _StepButton(PushButton): - def define(self, parent): - self = PushButton.define(self, parent) - self.step = 0 - return self - def setstep(self, step): - self.step = step - def definetextstep(self, parent, text, step): - self = self.definetext(parent, text) - self.setstep(step) - return self - def init_reactivity(self): - PushButton.init_reactivity(self) - self.parent.need_timer(self) - def step_trigger(self): - self.parent.setval(self.parent.getval() + self.step) - def down_trigger(self): - self.step_trigger() - self.parent.settimer(5) - def timer(self): - if self.hilited: - self.step_trigger() - if self.active: - self.parent.settimer(1) - - -# A complex slider is an HSplit initialized to three buttons: -# one to step down, a dragslider, and one to step up. -# -class ComplexSlider(HSplit): - # - # Override Slider define() method - # - def define(self, parent): - self = self.create(parent) # HSplit - # - self.downbutton = _StepButton().definetextstep(self, '-', -1) - self.dragbutton = DragSlider().define(self) - self.upbutton = _StepButton().definetextstep(self, '+', 1) - # - return self - # - # Override HSplit methods - # - def getminsize(self, m, (width, height)): - w1, h1 = self.downbutton.getminsize(m, (0, height)) - w3, h3 = self.upbutton.getminsize(m, (0, height)) - w1 = max(w1, h1) - w3 = max(w3, h3) - w2, h2 = self.dragbutton.getminsize(m, (width-w1-w3, height)) - return w1+w2+w3, max(h1, h2, h3) - # - def setbounds(self, bounds): - (left, top), (right, bottom) = self.bounds = bounds - size = bottom - top - self.downbutton.setbounds(((left, top), (left+size, bottom))) - self.dragbutton.setbounds(((left+size, top), \ - (right-size, bottom))) - self.upbutton.setbounds(((right-size, top), (right, bottom))) - # - # Pass other Slider methods on to dragbutton - # - def getval(self): return self.dragbutton.getval() - def sethook(self, hook): self.dragbutton.sethook(hook) - def setminvalmax(self, args): self.dragbutton.setminvalmax(args) - def settexts(self, args): self.dragbutton.settexts(args) - def setval(self, val): self.dragbutton.setval(val) - def enable(self, flag): - self.downbutton.enable(flag) - self.dragbutton.enable(flag) - self.upbutton.enable(flag) diff --git a/Lib/lib-stdwin/Soundogram.py b/Lib/lib-stdwin/Soundogram.py deleted file mode 100644 index e3c797e3dd..0000000000 --- a/Lib/lib-stdwin/Soundogram.py +++ /dev/null @@ -1,36 +0,0 @@ -# Module 'Soundogram' - -import audio -from Histogram import Histogram - -class Soundogram(Histogram): - # - def define(self, win, chunk): - width, height = corner = win.getwinsize() - bounds = (0, 0), corner - self.chunk = chunk - self.step = (len(chunk)-1)/(width/2+1) + 1 - ydata = _make_ydata(chunk, self.step) - return Histogram.define(self, (win, bounds, ydata, (0, 128))) - # - def setchunk(self, chunk): - self.chunk = chunk - self.recompute() - # - def recompute(self): - (left, top), (right, bottom) = self.bounds - width = right - left - self.step = (len(chunk)-1)/width + 1 - ydata = _make_ydata(chunk, self.step) - self.setdata(ydata, (0, 128)) - # - - -def _make_ydata(chunk, step): - ydata = [] - for i in range(0, len(chunk), step): - piece = audio.chr2num(chunk[i:i+step]) - mi, ma = min(piece), max(piece) - y = max(abs(mi), abs(ma)) - ydata.append(y) - return ydata diff --git a/Lib/lib-stdwin/Split.py b/Lib/lib-stdwin/Split.py deleted file mode 100644 index 5ff98088c4..0000000000 --- a/Lib/lib-stdwin/Split.py +++ /dev/null @@ -1,211 +0,0 @@ -# Generic Split implementation. -# Use as a base class for other splits. -# Derived classes should at least implement the methods that call -# unimpl() below: getminsize(), getbounds() and setbounds(). - -Error = 'Split.Error' # Exception - -import rect -from stdwinevents import * - -class Split: - # - # Calls from creator - # NB derived classes may add parameters to create() - # - def create(self, parent): - parent.addchild(self) - self.parent = parent - self.children = [] - self.mouse_interest = [] - self.keybd_interest = [] - self.timer_interest = [] - self.altdraw_interest = [] - self.mouse_focus = None - self.keybd_focus = None - return self - # - # Downcalls from parent to child - # - def destroy(self): - self.parent = None - for child in self.children: - child.destroy() - del self.children[:] - del self.mouse_interest[:] - del self.keybd_interest[:] - del self.timer_interest[:] - del self.altdraw_interest[:] - self.mouse_focus = None - self.keybd_focus = None - # - def getminsize(self, m, (width, height)): - return unimpl() # Should ask children - def getbounds(self): - return unimpl() - def setbounds(self, bounds): - unimpl() # Should tell children - # - def realize(self): - for child in self.children: - child.realize() - # - def draw(self, d, detail): - # (Could avoid calls to children outside the area) - for child in self.children: - child.draw(d, detail) - # - def altdraw(self, detail): - for child in self.altdraw_interest: - child.altdraw(detail) - # - # Keyboard focus handling (used internally) - # XXX This is not enough if two levels of splits - # XXX surround text fields! - # - def set_keybd_focus(self, child): - if self.keybd_focus <> child: - if self.keybd_focus: - self.keybd_focus.deactivate() - self.keybd_focus = None - if child: - child.activate() - self.keybd_focus = child - def next_keybd_focus(self): - if not self.keybd_interest: - self.set_keybd_focus(None) - return - if self.keybd_focus in self.keybd_interest: - i = self.keybd_interest.index(self.keybd_focus) - i = (i+1) % len(self.keybd_interest) - else: - i = 0 - self.set_keybd_focus(self.keybd_interest[i]) - # - # Downcalls only made after certain upcalls - # - def mouse_down(self, detail): - if self.mouse_focus: - self.mouse_focus.mouse_down(detail) - return - p = detail[0] - for child in self.mouse_interest: - if rect.pointinrect(p, child.getbounds()): - self.mouse_focus = child - if child in self.keybd_interest: - self.set_keybd_focus(child) - child.mouse_down(detail) - def mouse_move(self, detail): - if self.mouse_focus: - self.mouse_focus.mouse_move(detail) - def mouse_up(self, detail): - if self.mouse_focus: - self.mouse_focus.mouse_up(detail) - self.mouse_focus = None - # - def activate(self): - if self.keybd_focus: - self.keybd_focus.activate() - else: - self.next_keybd_focus() - def deactivate(self): - if self.keybd_focus: - self.keybd_focus.deactivate() - # - def keybd(self, type, detail): - if not self.keybd_focus: - self.set_keybd_focus(self.keybd_interest[0]) - if type == WE_COMMAND and detail == WC_TAB and \ - len(self.keybd_interest) > 1: - self.next_keybd_focus() - return - self.keybd_focus.keybd(type, detail) - # - def timer(self): - for child in self.timer_interest: - child.timer() - # - # Upcalls from child to parent - # - def addchild(self, child): - if child in self.children: - raise Error, 'addchild: child already inlist' - self.children.append(child) - def delchild(self, child): - if child not in self.children: - raise Error, 'delchild: child not in list' - self.children.remove(child) - if child in self.mouse_interest: - self.mouse_interest.remove(child) - if child in self.keybd_interest: - self.keybd_interest.remove(child) - if child in self.timer_interest: - self.timer_interest.remove(child) - if child in self.altdraw_interest: - self.altdraw_interest.remove(child) - if child == self.mouse_focus: - self.mouse_focus = None - if child == self.keybd_focus: - self.keybd_focus = None - # - def need_mouse(self, child): - if child not in self.mouse_interest: - self.mouse_interest.append(child) - self.parent.need_mouse(self) - def no_mouse(self, child): - if child == self.mouse_focus: - self.mouse_focus = None - if child in self.mouse_interest: - self.mouse_interest.remove(child) - if not self.mouse_interest: - self.parent.no_mouse(self) - # - def need_keybd(self, child): - if child not in self.keybd_interest: - self.keybd_interest.append(child) - self.parent.need_keybd(self) - if not self.keybd_focus: - self.set_keybd_focus(child) - def no_keybd(self, child): - if child == self.keybd_focus: - self.keybd_focus = None # Don't call child.deactivate() - if child in self.keybd_interest: - self.keybd_interest.remove(child) - if not self.keybd_interest: - self.parent.no_keybd(self) - # - def need_timer(self, child): - if child not in self.timer_interest: - self.timer_interest.append(child) - self.parent.need_timer(self) - def no_timer(self, child): - if child in self.timer_interest: - self.timer_interest.remove(child) - if not self.timer_interest: - self.parent.no_timer(self) - # - def need_altdraw(self, child): - if child not in self.altdraw_interest: - self.altdraw_interest.append(child) - self.parent.need_altdraw(self) - def no_altdraw(self, child): - if child in self.altdraw_interest: - self.altdraw_interest.remove(child) - if not self.altdraw_interest: - self.parent.no_altdraw(self) - # - # The rest are transparent: - # - def begindrawing(self): - return self.parent.begindrawing() - def beginmeasuring(self): - return self.parent.beginmeasuring() - def getwindow(self): - return self.parent.getwindow() - # - def change(self, area): - self.parent.change(area) - def scroll(self, area, vector): - self.parent.scroll(area, vector) - def settimer(self, itimer): - self.parent.settimer(itimer) diff --git a/Lib/lib-stdwin/StripChart.py b/Lib/lib-stdwin/StripChart.py deleted file mode 100644 index afec007ae4..0000000000 --- a/Lib/lib-stdwin/StripChart.py +++ /dev/null @@ -1,70 +0,0 @@ -# Module 'StripChart' - -import rect -from Buttons import LabelAppearance, NoReactivity - -# A StripChart doesn't really look like a label but it needs a base class. -# LabelAppearance allows it to be disabled and hilited. - -class StripChart(LabelAppearance, NoReactivity): - # - def define(self, parent, scale): - self.parent = parent - parent.addchild(self) - self.init_appearance() - self.init_reactivity() - self.ydata = [] - self.scale = scale - self.resetbounds() - return self - # - def destroy(self): - self.parent = 0 - # - def setbounds(self, bounds): - LabelAppearance.setbounds(self, bounds) - self.resetbounds() - # - def resetbounds(self): - (left, top), (right, bottom) = self.bounds - self.width = right-left - self.height = bottom-top - excess = len(self.ydata) - self.width - if excess > 0: - del self.ydata[:excess] - elif excess < 0: - while len(self.ydata) < self.width: - self.ydata.insert(0, 0) - # - def append(self, y): - self.ydata.append(y) - excess = len(self.ydata) - self.width - if excess > 0: - del self.ydata[:excess] - if self.bounds <> rect.empty: - self.parent.scroll(self.bounds, (-excess, 0)) - if self.bounds <> rect.empty: - (left, top), (right, bottom) = self.bounds - i = len(self.ydata) - area = (left+i-1, top), (left+i, bottom) - self.draw(self.parent.begindrawing(), area) - # - def draw(self, d, area): - area = rect.intersect([area, self.bounds]) - if area == rect.empty: - return - d.cliprect(area) - d.erase(self.bounds) - (a_left, a_top), (a_right, a_bottom) = area - (left, top), (right, bottom) = self.bounds - height = bottom - top - i1 = a_left - left - i2 = a_right - left - for i in range(max(0, i1), min(len(self.ydata), i2)): - split = bottom-self.ydata[i]*height/self.scale - d.paint((left+i, split), (left+i+1, bottom)) - if not self.enabled: - self.flipenable(d) - if self.hilited: - self.fliphilite(d) - d.noclip() diff --git a/Lib/lib-stdwin/TextEdit.py b/Lib/lib-stdwin/TextEdit.py deleted file mode 100644 index e08e496811..0000000000 --- a/Lib/lib-stdwin/TextEdit.py +++ /dev/null @@ -1,126 +0,0 @@ -# Text editing widget - -# NB: this always assumes fixed bounds. -# For auto-growing TextEdit windows, different code would be needed. - -from stdwinevents import * - -class TextEdit: - # - def create(self, parent, (cols, rows)): - parent.addchild(self) - self.parent = parent - self.cols = cols - self.rows = rows - self.text = '' - # Creation of the editor is done in realize() - self.editor = None - self.dh = self.dv = 0 - return self - # - def createboxed(self, parent, (cols, rows), (dh, dv)): - self = self.create(parent, (cols, rows)) - self.dh = max(0, dh) - self.dv = max(0, dv) - return self - # - def settext(self, text): - self.editor.settext(text) - # - def gettext(self): - return self.editor.gettext(text) - # - # Downcalls from parent to child - # - def destroy(self): - del self.parent - del self.editor - del self.window - # - def getminsize(self, m, (width, height)): - width = max(0, width - 2*self.dh) - height = max(0, height - 2*self.dv) - if width > 0 and self.editor: - (left, top), (right, bottom) = self.editor.getrect() - act_width, act_height = right - left, bottom - top - if width >= act_width: - width = width + 2*self.dh - height = max(height, act_height) + 2*self.dv - return width, height - width = max(width, self.cols*m.textwidth('in')/2) + 2*self.dh - height = max(height, self.rows*m.lineheight()) + 2*self.dv - return width, height - # - def setbounds(self, bounds): - self.bounds = bounds - if self.editor: - (left, top), (right, bottom) = bounds - left = left + self.dh - top = top + self.dv - right = right - self.dh - bottom = bottom - self.dv - self.editor.move((left, top), (right, bottom)) - if self.dh and self.dv: - (left, top), (right, bottom) = bounds - left = left + 1 - top = top + 1 - right = right - 1 - bottom = bottom - 1 - bounds = (left, top), (right, bottom) - self.editor.setview(bounds) - # - def getbounds(self): - return self.bounds - # - def realize(self): - self.window = self.parent.getwindow() - (left, top), (right, bottom) = self.bounds - left = left + self.dh - top = top + self.dv - right = right - self.dh - bottom = bottom - self.dv - self.editor = \ - self.window.textcreate((left, top), (right, bottom)) - self.editor.setactive(0) - bounds = self.bounds - if self.dh and self.dv: - (left, top), (right, bottom) = bounds - left = left + 1 - top = top + 1 - right = right - 1 - bottom = bottom - 1 - bounds = (left, top), (right, bottom) - self.editor.setview(bounds) - self.editor.settext(self.text) - self.parent.need_mouse(self) - self.parent.need_keybd(self) - self.parent.need_altdraw(self) - # - def draw(self, d, area): - if self.dh and self.dv: - d.box(self.bounds) - # - def altdraw(self, area): - self.editor.draw(area) - # - # Event downcalls - # - def mouse_down(self, detail): - x = self.editor.event(WE_MOUSE_DOWN, self.window, detail) - # - def mouse_move(self, detail): - x = self.editor.event(WE_MOUSE_MOVE, self.window, detail) - # - def mouse_up(self, detail): - x = self.editor.event(WE_MOUSE_UP, self.window, detail) - # - def keybd(self, type, detail): - x = self.editor.event(type, self.window, detail) - # - def activate(self): - self.editor.setfocus(0, 30000) - self.editor.setactive(1) - # - def deactivate(self): - self.editor.setactive(0) - # diff --git a/Lib/lib-stdwin/TransParent.py b/Lib/lib-stdwin/TransParent.py deleted file mode 100644 index 49dcd3d071..0000000000 --- a/Lib/lib-stdwin/TransParent.py +++ /dev/null @@ -1,123 +0,0 @@ -# A class that sits transparently between a parent and one child. -# First create the parent, then this thing, then the child. -# Use this as a base class for objects that are almost transparent. -# Don't use as a base class for parents with multiple children. - -Error = 'TransParent.Error' # Exception - -class ManageOneChild: - # - # Upcalls shared with other single-child parents - # - def addchild(self, child): - if self.child: - raise Error, 'addchild: one child only' - if not child: - raise Error, 'addchild: bad child' - self.child = child - # - def delchild(self, child): - if not self.child: - raise Error, 'delchild: no child' - if child <> self.child: - raise Error, 'delchild: not my child' - self.child = 0 - -class TransParent(ManageOneChild): - # - # Calls from creator - # NB derived classes may add parameters to create() - # - def create(self, parent): - parent.addchild(self) - self.parent = parent - self.child = None # No child yet - return self - # - # Downcalls from parent to child - # - def destroy(self): - del self.parent - if self.child: self.child.destroy() - del self.child - # - def getminsize(self, args): - if not self.child: - m, size = args - return size - else: - return self.child.getminsize(args) - def getbounds(self, bounds): - if not self.child: - raise Error, 'getbounds w/o child' - else: - return self.child.getbounds() - def setbounds(self, bounds): - if not self.child: - raise Error, 'setbounds w/o child' - else: - self.child.setbounds(bounds) - def realize(self): - if self.child: - self.child.realize() - def draw(self, d, area): - if self.child: - self.child.draw(d, area) - def altdraw(self, area): - if self.child: - self.child.altdraw(area) - # - # Downcalls only made after certain upcalls - # - def mouse_down(self, detail): - if self.child: self.child.mouse_down(detail) - def mouse_move(self, detail): - if self.child: self.child.mouse_move(detail) - def mouse_up(self, detail): - if self.child: self.child.mouse_up(detail) - # - def keybd(self, type_detail): - self.child.keybd(type_detail) - def activate(self): - self.child.activate() - def deactivate(self): - self.child.deactivate() - # - def timer(self): - if self.child: self.child.timer() - # - # Upcalls from child to parent - # - def need_mouse(self, child): - self.parent.need_mouse(self) - def no_mouse(self, child): - self.parent.no_mouse(self) - # - def need_timer(self, child): - self.parent.need_timer(self) - def no_timer(self, child): - self.parent.no_timer(self) - # - def need_altdraw(self, child): - self.parent.need_altdraw(self) - def no_altdraw(self, child): - self.parent.no_altdraw(self) - # - def need_keybd(self, child): - self.parent.need_keybd(self) - def no_keybd(self, child): - self.parent.no_keybd(self) - # - def begindrawing(self): - return self.parent.begindrawing() - def beginmeasuring(self): - return self.parent.beginmeasuring() - def getwindow(self): - return self.parent.getwindow() - # - def change(self, area): - self.parent.change(area) - def scroll(self, area, vector): - self.parent.scroll(area, vector) - def settimer(self, itimer): - self.parent.settimer(itimer) diff --git a/Lib/lib-stdwin/VUMeter.py b/Lib/lib-stdwin/VUMeter.py deleted file mode 100644 index ed9a4738c1..0000000000 --- a/Lib/lib-stdwin/VUMeter.py +++ /dev/null @@ -1,47 +0,0 @@ -# Module 'VUMeter' - -import audio -from StripChart import StripChart - -K = 1024 -Rates = [0, 32*K, 16*K, 8*K] - -class VUMeter(StripChart): - # - # Override define() and timer() methods - # - def define(self, parent): - self = StripChart.define(self, (parent, 128)) - self.parent.need_timer(self) - self.sampling = 0 - self.rate = 3 - self.enable(0) - return self - # - def timer(self): - if self.sampling: - chunk = audio.wait_recording() - self.sampling = 0 - nums = audio.chr2num(chunk) - ampl = max(abs(min(nums)), abs(max(nums))) - self.append(ampl) - if self.enabled and not self.sampling: - audio.setrate(self.rate) - size = Rates[self.rate]/10 - size = size/48*48 - audio.start_recording(size) - self.sampling = 1 - if self.sampling: - self.parent.settimer(1) - # - # New methods: start() and stop() - # - def stop(self): - if self.sampling: - chunk = audio.stop_recording() - self.sampling = 0 - self.enable(0) - # - def start(self): - self.enable(1) - self.timer() diff --git a/Lib/lib-stdwin/WindowParent.py b/Lib/lib-stdwin/WindowParent.py deleted file mode 100644 index cdec10b283..0000000000 --- a/Lib/lib-stdwin/WindowParent.py +++ /dev/null @@ -1,189 +0,0 @@ -# A 'WindowParent' is the only module that uses real stdwin functionality. -# It is the root of the tree. -# It should have exactly one child when realized. -# -# There is also an alternative interface to "mainloop" here. - -import stdwin -from stdwinevents import * -import mainloop - -from TransParent import ManageOneChild - -Error = 'WindowParent.Error' # Exception - -class WindowParent(ManageOneChild): - # - def create(self, title, size): - self.title = title - self.size = size # (width, height) - self._reset() - self.close_hook = WindowParent.delayed_destroy - return self - # - def _reset(self): - self.child = None - self.win = None - self.itimer = 0 - self.do_mouse = 0 - self.do_keybd = 0 - self.do_timer = 0 - self.do_altdraw = 0 - self.pending_destroy = 0 - self.close_hook = None - self.menu_hook = None - # - def destroy(self): - mainloop.unregister(self.win) - if self.child: self.child.destroy() - self._reset() - # - def delayed_destroy(self): - # This interface to be used by 'Close' buttons etc.; - # destroying a window from within a button hook - # is not a good idea... - self.pending_destroy = 1 - # - def close_trigger(self): - if self.close_hook: self.close_hook(self) - # - def menu_trigger(self, menu, item): - if self.menu_hook: - self.menu_hook(self, menu, item) - # - def need_mouse(self, child): self.do_mouse = 1 - def no_mouse(self, child): self.do_mouse = 0 - # - def need_keybd(self, child): - self.do_keybd = 1 - self.child.activate() - def no_keybd(self, child): - self.do_keybd = 0 - self.child.deactivate() - # - def need_timer(self, child): self.do_timer = 1 - def no_timer(self, child): self.do_timer = 0 - # - def need_altdraw(self, child): self.do_altdraw = 1 - def no_altdraw(self, child): self.do_altdraw = 0 - # - def realize(self): - if self.win: - raise Error, 'realize(): called twice' - if not self.child: - raise Error, 'realize(): no child' - # Compute suggested size - self.size = self.child.getminsize(self.beginmeasuring(), \ - self.size) - save_defsize = stdwin.getdefwinsize() - scrwidth, scrheight = stdwin.getscrsize() - width, height = self.size - if width > scrwidth: - width = scrwidth * 2/3 - if height > scrheight: - height = scrheight * 2/3 - stdwin.setdefwinsize(width, height) - self.hbar, self.vbar = stdwin.getdefscrollbars() - self.win = stdwin.open(self.title) - stdwin.setdefwinsize(save_defsize) - self.win.setdocsize(self.size) - if self.itimer: - self.win.settimer(self.itimer) - width, height = self.win.getwinsize() - if self.hbar: - width = self.size[0] - if self.vbar: - height = self.size[1] - self.child.setbounds(((0, 0), (width, height))) - self.child.realize() - self.win.dispatch = self.dispatch - mainloop.register(self.win) - # - def fixup(self): - # XXX This could share code with realize() above - self.size = self.child.getminsize(self.beginmeasuring(), \ - self.win.getwinsize()) - self.win.setdocsize(self.size) - width, height = self.win.getwinsize() - if self.hbar: - width = self.size[0] - if self.vbar: - height = self.size[1] - self.child.setbounds(((0, 0), (width, height))) - # Force a redraw of the entire window: - self.win.change((0, 0), self.size) - # - def beginmeasuring(self): - # Return something with which a child can measure text - if self.win: - return self.win.begindrawing() - else: - return stdwin - # - def begindrawing(self): - if self.win: - return self.win.begindrawing() - else: - raise Error, 'begindrawing(): not realized yet' - # - def getwindow(self): - if self.win: - return self.win - else: - raise Error, 'getwindow(): not realized yet' - # - def change(self, area): - if self.win: - self.win.change(area) - # - def scroll(self, area, vector): - if self.win: - self.win.scroll(area, vector) - # - def settimer(self, itimer): - if self.win: - self.win.settimer(itimer) - else: - self.itimer = itimer - # - # Only call dispatch once we are realized - # - def dispatch(self, (type, win, detail)): - if type == WE_DRAW: - d = self.win.begindrawing() - self.child.draw(d, detail) - del d - if self.do_altdraw: self.child.altdraw(detail) - elif type == WE_MOUSE_DOWN: - if self.do_mouse: self.child.mouse_down(detail) - elif type == WE_MOUSE_MOVE: - if self.do_mouse: self.child.mouse_move(detail) - elif type == WE_MOUSE_UP: - if self.do_mouse: self.child.mouse_up(detail) - elif type in (WE_CHAR, WE_COMMAND): - if self.do_keybd: self.child.keybd(type, detail) - elif type == WE_TIMER: - if self.do_timer: self.child.timer() - elif type == WE_SIZE: - self.fixup() - elif type == WE_CLOSE: - self.close_trigger() - elif type == WE_MENU: - self.menu_trigger(detail) - if self.pending_destroy: - self.destroy() - # - -def MainLoop(): - mainloop.mainloop() - -def Dispatch(event): - mainloop.dispatch(event) - -# Interface used by WindowSched: - -def CountWindows(): - return mainloop.countwindows() - -def AnyWindow(): - return mainloop.anywindow() diff --git a/Lib/lib-stdwin/WindowSched.py b/Lib/lib-stdwin/WindowSched.py deleted file mode 100644 index 56ca6f853b..0000000000 --- a/Lib/lib-stdwin/WindowSched.py +++ /dev/null @@ -1,58 +0,0 @@ -# Combine a real-time scheduling queue and stdwin event handling. -# Uses the millisecond timer. - -import stdwin, stdwinq -from stdwinevents import WE_TIMER -import mainloop -import sched -import time - -# Delay function called by the scheduler when it has nothing to do. -# Return immediately when something is done, or when the delay is up. -# -def delayfunc(msecs): - # - # Check for immediate stdwin event - # - event = stdwinq.pollevent() - if event: - mainloop.dispatch(event) - return - # - # Use millisleep for very short delays or if there are no windows - # - if msecs < 100 or mainloop.countwindows() == 0: - if msecs > 0: - time.millisleep(msecs) - return - # - # Post a timer event on an arbitrary window and wait for it - # - window = mainloop.anywindow() - window.settimer(msecs/100) - event = stdwinq.getevent() - window.settimer(0) - if event[0] <> WE_TIMER: - mainloop.dispatch(event) - -q = sched.scheduler(time.millitimer, delayfunc) - -# Export functions enter, enterabs and cancel just like a scheduler -# -enter = q.enter -enterabs = q.enterabs -cancel = q.cancel - -# Emptiness check must check both queues -# -def empty(): - return q.empty() and mainloop.countwindows() == 0 - -# Run until there is nothing left to do -# -def run(): - while not empty(): - if q.empty(): - mainloop.dispatch(stdwinq.getevent()) - else: - q.run() diff --git a/Lib/lib-stdwin/anywin.py b/Lib/lib-stdwin/anywin.py deleted file mode 100644 index 38ee8690a6..0000000000 --- a/Lib/lib-stdwin/anywin.py +++ /dev/null @@ -1,14 +0,0 @@ -# Module 'anywin' -# Open a file or directory in a window - -import dirwin -import filewin -import os - -def open(name): - print 'opening', name, '...' - if os.path.isdir(name): - w = dirwin.open(name) - else: - w = filewin.open(name) - return w diff --git a/Lib/lib-stdwin/basewin.py b/Lib/lib-stdwin/basewin.py deleted file mode 100644 index 7a43536967..0000000000 --- a/Lib/lib-stdwin/basewin.py +++ /dev/null @@ -1,64 +0,0 @@ -# basewin.py - -import stdwin -import mainloop -from stdwinevents import * - -class BaseWindow: - - def __init__(self, title): - self.win = stdwin.open(title) - self.win.dispatch = self.dispatch - mainloop.register(self.win) - -# def reopen(self): -# title = self.win.gettitle() -# winpos = self.win.getwinpos() -# winsize = self.win.getwinsize() -# origin = self.win.getorigin() -# docsize = self.win.getdocsize() -# mainloop.unregister(self.win) -# del self.win.dispatch -# self.win.close() -# stdwin.setdefwinpos(winpos) -# stdwin.setdefwinsize(winsize) -# self.win = stdwin.open(title) -# stdwin.setdefwinpos(0, 0) -# stdwin.setdefwinsize(0, 0) -# self.win.setdocsize(docsize) -# self.win.setorigin(origin) -# self.win.dispatch = self.dispatch -# mainloop.register(self.win) - - def popup(self): - if self.win is not stdwin.getactive(): - self.win.setactive() - - def close(self): - mainloop.unregister(self.win) - del self.win.dispatch - self.win.close() - - def dispatch(self, event): - type, win, detail = event - if type == WE_CHAR: - self.char(detail) - elif type == WE_COMMAND: - self.command(detail) - elif type == WE_MOUSE_DOWN: - self.mouse_down(detail) - elif type == WE_MOUSE_MOVE: - self.mouse_move(detail) - elif type == WE_MOUSE_UP: - self.mouse_up(detail) - elif type == WE_DRAW: - self.draw(detail) - elif type == WE_CLOSE: - self.close() - - def no_op(self, detail): - pass - char = command = mouse_down = mouse_move = mouse_up = draw = no_op - - def refreshall(self): - self.win.change((-10, 0), (10000, 30000)) diff --git a/Lib/lib-stdwin/dirwin.py b/Lib/lib-stdwin/dirwin.py deleted file mode 100644 index e8b0170207..0000000000 --- a/Lib/lib-stdwin/dirwin.py +++ /dev/null @@ -1,29 +0,0 @@ -# Module 'dirwin' - -# Directory windows, a subclass of listwin - -import os -import gwin -import listwin -import anywin -import dircache - -def action(w, string, i, detail): - (h, v), clicks, button, mask = detail - if clicks == 2: - name = os.path.join(w.name, string) - try: - w2 = anywin.open(name) - w2.parent = w - except os.error, why: - stdwin.message('Can\'t open ' + name + ': ' + why[1]) - -def open(name): - name = os.path.join(name, '') - list = dircache.opendir(name)[:] - list.sort() - dircache.annotate(name, list) - w = listwin.open(name, list) - w.name = name - w.action = action - return w diff --git a/Lib/lib-stdwin/filewin.py b/Lib/lib-stdwin/filewin.py deleted file mode 100644 index a03c3f70a6..0000000000 --- a/Lib/lib-stdwin/filewin.py +++ /dev/null @@ -1,20 +0,0 @@ -# Module 'filewin' -# File windows, a subclass of textwin (which is a subclass of gwin) - -import textwin -import builtin - - -# FILE WINDOW - -def open_readonly(fn): # Open a file window - fp = builtin.open(fn, 'r') - w = textwin.open_readonly(fn, fp.read()) - w.fn = fn - return w - -def open(fn): # Open a file window - fp = builtin.open(fn, 'r') - w = textwin.open(fn, fp.read()) - w.fn = fn - return w diff --git a/Lib/lib-stdwin/formatter.py b/Lib/lib-stdwin/formatter.py deleted file mode 100644 index 7ddfc1d680..0000000000 --- a/Lib/lib-stdwin/formatter.py +++ /dev/null @@ -1,207 +0,0 @@ -# A class to help applications that do fancy text formatting. -# You create an instance each time you must redraw the window. -# Set the initial left, top and right coordinates; -# then feed it words, font changes and vertical movements. -# -# This class should eventually be extended to support much fancier -# formatting, along the lines of TeX; for now, a very simple model -# is sufficient. -# -class formatter: - # - # Initialize a formatter instance. - # Pass the window's drawing object, and left, top, right - # coordinates of the drawing space as arguments. - # - def __init__(self, d, left, top, right): - self.d = d # Drawing object - self.left = left # Left margin - self.right = right # Right margin - self.v = top # Top of current line - self.center = 0 - self.justify = 1 - self.setfont('') # Default font - self._reset() # Prepare for new line - # - # Reset for start of fresh line. - # - def _reset(self): - self.boxes = [] # Boxes and glue still to be output - self.sum_width = 0 # Total width of boxes - self.sum_space = 0 # Total space between boxes - self.sum_stretch = 0 # Total stretch for space between boxes - self.max_ascent = 0 # Max ascent of current line - self.max_descent = 0 # Max descent of current line - self.avail_width = self.right - self.left - self.hang_indent = 0 - # - # Set the current font, and compute some values from it. - # - def setfont(self, font): - self.font = font - self.d.setfont(font) - self.font_space = self.d.textwidth(' ') - self.font_ascent = self.d.baseline() - self.font_descent = self.d.lineheight() - self.font_ascent - # - # Add a word to the list of boxes; first flush if line is full. - # Space and stretch factors are expressed in fractions - # of the current font's space width. - # (Two variations: one without, one with explicit stretch factor.) - # - def addword(self, word, spacefactor): - self.addwordstretch(word, spacefactor, spacefactor) - # - def addwordstretch(self, word, spacefactor, stretchfactor): - width = self.d.textwidth(word) - if width > self.avail_width: - self._flush(1) - space = int(float(self.font_space) * float(spacefactor)) - stretch = int(float(self.font_space) * float(stretchfactor)) - box = (self.font, word, width, space, stretch) - self.boxes.append(box) - self.sum_width = self.sum_width + width - self.sum_space = self.sum_space + space - self.sum_stretch = self.sum_stretch + stretch - self.max_ascent = max(self.font_ascent, self.max_ascent) - self.max_descent = max(self.font_descent, self.max_descent) - self.avail_width = self.avail_width - width - space - # - # Flush current line and start a new one. - # Flushing twice is harmless (i.e. does not introduce a blank line). - # (Two versions: the internal one has a parameter for justification.) - # - def flush(self): - self._flush(0) - # - def _flush(self, justify): - if not self.boxes: - return - # - # Compute amount of stretch needed. - # - if justify and self.justify or self.center: - # - # Compute extra space to fill; - # this is avail_width plus glue from last box. - # Also compute available stretch. - # - last_box = self.boxes[len(self.boxes)-1] - font, word, width, space, stretch = last_box - tot_extra = self.avail_width + space - tot_stretch = self.sum_stretch - stretch - else: - tot_extra = tot_stretch = 0 - # - # Output the boxes. - # - baseline = self.v + self.max_ascent - h = self.left + self.hang_indent - if self.center: - h = h + tot_extra / 2 - tot_extra = tot_stretch = 0 - for font, word, width, space, stretch in self.boxes: - self.d.setfont(font) - v = baseline - self.d.baseline() - self.d.text((h, v), word) - h = h + width + space - if tot_extra > 0 and tot_stretch > 0: - extra = stretch * tot_extra / tot_stretch - h = h + extra - tot_extra = tot_extra - extra - tot_stretch = tot_stretch - stretch - # - # Prepare for next line. - # - self.v = baseline + self.max_descent - self.d.setfont(self.font) - self._reset() - # - # Add vertical space; first flush. - # Vertical space is expressed in fractions of the current - # font's line height. - # - def vspace(self, lines): - self.vspacepixels(int(lines * self.d.lineheight())) - # - # Add vertical space given in pixels. - # - def vspacepixels(self, dv): - self.flush() - self.v = self.v + dv - # - # Set temporary (hanging) indent, for paragraph start. - # First flush. - # - def tempindent(self, space): - self.flush() - hang = int(float(self.font_space) * float(space)) - self.hang_indent = hang - self.avail_width = self.avail_width - hang - # - # Add (permanent) left indentation. First flush. - # - def addleftindent(self, space): - self.flush() - self.left = self.left \ - + int(float(self.font_space) * float(space)) - self._reset() - # - - -# Test procedure -# -def test(): - import stdwin, stdwinq - from stdwinevents import * - try: - import mac - # Mac font assignments: - font1 = 'times', '', 12 - font2 = 'times', 'b', 14 - except ImportError: - # X11R4 font assignments - font1 = '*times-medium-r-*-120-*' - font2 = '*times-bold-r-*-140-*' - words = \ - ['The','quick','brown','fox','jumps','over','the','lazy','dog.'] - words = words * 2 - stage = 0 - stages = [(0,0,'ragged'), (1,0,'justified'), (0,1,'centered')] - justify, center, title = stages[stage] - stdwin.setdefwinsize(300,200) - w = stdwin.open(title) - winsize = w.getwinsize() - while 1: - type, window, detail = stdwinq.getevent() - if type == WE_CLOSE: - break - elif type == WE_SIZE: - newsize = w.getwinsize() - if newsize <> winsize: - w.change((0,0), winsize) - winsize = newsize - w.change((0,0), winsize) - elif type == WE_MOUSE_DOWN: - stage = (stage + 1) % len(stages) - justify, center, title = stages[stage] - w.settitle(title) - w.change((0, 0), (1000, 1000)) - elif type == WE_DRAW: - width, height = winsize - f = formatter(w.begindrawing(), 0, 0, width) - f.center = center - f.justify = justify - if not center: - f.tempindent(5) - for font in font1, font2, font1: - f.setfont(font) - for word in words: - space = 1 + (word[-1:] == '.') - f.addword(word, space) - if center and space > 1: - f.flush() - f.flush() - height = f.v - del f - w.setdocsize(0, height) diff --git a/Lib/lib-stdwin/gwin.py b/Lib/lib-stdwin/gwin.py deleted file mode 100644 index 626c8fa2fb..0000000000 --- a/Lib/lib-stdwin/gwin.py +++ /dev/null @@ -1,110 +0,0 @@ -# Module 'gwin' -# Generic stdwin windows - -# This is used as a base class from which to derive other window types. -# XXX DON'T USE THIS CODE ANY MORE! It is ages old! - -import stdwin, stdwinq -from stdwinevents import * -from mainloop import mainloop, register, unregister, windows - -# Open a window - -def open(title): # Open a generic window - w = stdwin.open(title) - stdwin.setdefwinsize(0, 0) - # Set default event handlers - w.draw = nop - w.char = nop - w.mdown = nop - w.mmove = nop - w.mup = nop - w.m2down = m2down - w.m2up = m2up - w.size = nop - w.move = nop - w.activate = w.deactivate = nop - w.timer = nop - # default command handlers - w.close = close - w.tab = tab - w.enter = enter - w.backspace = backspace - w.arrow = arrow - w.kleft = w.kup = w.kright = w.kdown = nop - w.dispatch = treatevent - register(w) - return w - - -def treatevent(e): # Handle a stdwin event - type, w, detail = e - if type == WE_DRAW: - w.draw(w, detail) - elif type == WE_MENU: - m, item = detail - m.action[item](w, m, item) - elif type == WE_COMMAND: - treatcommand(w, detail) - elif type == WE_CHAR: - w.char(w, detail) - elif type == WE_MOUSE_DOWN: - if detail[1] > 1: w.m2down(w, detail) - else: w.mdown(w, detail) - elif type == WE_MOUSE_MOVE: - w.mmove(w, detail) - elif type == WE_MOUSE_UP: - if detail[1] > 1: w.m2up(w, detail) - else: w.mup(w, detail) - elif type == WE_SIZE: - w.size(w, w.getwinsize()) - elif type == WE_ACTIVATE: - w.activate(w) - elif type == WE_DEACTIVATE: - w.deactivate(w) - elif type == WE_MOVE: - w.move(w) - elif type == WE_TIMER: - w.timer(w) - elif type == WE_CLOSE: - w.close(w) - -def treatcommand(w, type): # Handle a we_command event - if type == WC_CLOSE: - w.close(w) - elif type == WC_RETURN: - w.enter(w) - elif type == WC_TAB: - w.tab(w) - elif type == WC_BACKSPACE: - w.backspace(w) - elif type in (WC_LEFT, WC_UP, WC_RIGHT, WC_DOWN): - w.arrow(w, type) - - -# Methods - -def close(w): # Close method - unregister(w) - del w.close # Delete our close function - w.close() # Call the close method - -def arrow(w, detail): # Arrow key method - if detail == WC_LEFT: - w.kleft(w) - elif detail == WC_UP: - w.kup(w) - elif detail == WC_RIGHT: - w.kright(w) - elif detail == WC_DOWN: - w.kdown(w) - - -# Trivial methods - -def tab(w): w.char(w, '\t') -def enter(w): w.char(w, '\n') # 'return' is a Python reserved word -def backspace(w): w.char(w, '\b') -def m2down(w, detail): w.mdown(w, detail) -def m2up(w, detail): w.mup(w, detail) -def nop(*args): pass diff --git a/Lib/lib-stdwin/listwin.py b/Lib/lib-stdwin/listwin.py deleted file mode 100644 index 9480a81fc9..0000000000 --- a/Lib/lib-stdwin/listwin.py +++ /dev/null @@ -1,47 +0,0 @@ -# Module 'listwin' -# List windows, a subclass of gwin - -import gwin -import stdwin - -def maxlinewidth(a): # Compute maximum textwidth of lines in a sequence - max = 0 - for line in a: - width = stdwin.textwidth(line) - if width > max: max = width - return max - -def action(w, string, i, detail): # Default item selection method - pass - -def mup(w, detail): # Mouse up method - (h, v), clicks, button, mask = detail - i = divmod(v, w.lineheight)[0] - if 0 <= i < len(w.data): - w.action(w, w.data[i], i, detail) - -def draw(w, ((left, top), (right, bottom))): # Text window draw method - data = w.data - d = w.begindrawing() - lh = w.lineheight - itop = top/lh - ibot = (bottom-1)/lh + 1 - if itop < 0: itop = 0 - if ibot > len(data): ibot = len(data) - for i in range(itop, ibot): d.text((0, i*lh), data[i]) - -def open(title, data): # Display a list of texts in a window - lineheight = stdwin.lineheight() - h, v = maxlinewidth(data), len(data)*lineheight - h0, v0 = h + stdwin.textwidth(' '), v + lineheight - if h0 > stdwin.textwidth(' ')*80: h0 = 0 - if v0 > stdwin.lineheight()*24: v0 = 0 - stdwin.setdefwinsize(h0, v0) - w = gwin.open(title) - w.setdocsize(h, v) - w.lineheight = lineheight - w.data = data - w.draw = draw - w.action = action - w.mup = mup - return w diff --git a/Lib/lib-stdwin/mainloop.py b/Lib/lib-stdwin/mainloop.py deleted file mode 100644 index aa40c34b4e..0000000000 --- a/Lib/lib-stdwin/mainloop.py +++ /dev/null @@ -1,256 +0,0 @@ -# Standard main loop for *all* STDWIN applications. -# This requires that applications: -# - register their windows on creation and unregister them when closed -# - have a 'dispatch' function as a window member - - -import stdwin, stdwinq -from stdwinevents import * - - -# List of windows known to the main loop. -# -windows = [] - - -# Last window that ever received an event -# -last_window = None - - -# Function to register a window. -# -def register(win): - # First test the dispatch function by passing it a null event -- - # this catches registration of unconforming windows. - win.dispatch((WE_NULL, win, None)) - if win not in windows: - windows.append(win) - - -# Function to unregister a window. -# It is not an error to unregister an already unregistered window -# (this is useful for cleanup actions). -# -def unregister(win): - global last_window - if win == last_window: - last_window = None - if win in windows: - windows.remove(win) # Not in 0.9.1 - # 0.9.1 solution: - #for i in range(len(windows)): - # if windows[i] = win: - # del windows[i] - # break - - -# Interfaces used by WindowSched. -# -def countwindows(): - return len(windows) -# -def anywindow(): - if windows: - return windows[0] - else: - return None - - -# NEW: register any number of file descriptors -# -fdlist = [] -select_args = None -select_handlers = None -# -def registerfd(fd, mode, handler): - if mode not in ('r', 'w', 'x'): - raise ValueError, 'mode must be r, w or x' - if type(fd) <> type(0): - fd = fd.fileno() # If this fails it's not a proper select arg - for i in range(len(fdlist)): - if fdlist[i][:2] == (fd, mode): - raise ValueError, \ - '(fd, mode) combination already registered' - fdlist.append((fd, mode, handler)) - make_select_args() -# -def unregisterfd(fd, *args): - if type(fd) <> type(0): - fd = fd.fileno() # If this fails it's not a proper select arg - args = (fd,) + args - n = len(args) - for i in range(len(fdlist)): - if fdlist[i][:n] == args: - del fdlist[i] - make_select_args() -# -def make_select_args(): - global select_args, select_handlers - rlist, wlist, xlist = [], [], [] - rhandlers, whandlers, xhandlers = {}, {}, {} - for fd, mode, handler in fdlist: - if mode == 'r': - rlist.append(fd) - rhandlers[`fd`] = handler - if mode == 'w': - wlist.append(fd) - whandlers[`fd`] = handler - if mode == 'x': - xlist.append(fd) - xhandlers[`fd`] = handler - if rlist or wlist or xlist: - select_args = rlist, wlist, xlist - select_handlers = rhandlers, whandlers, xhandlers - else: - select_args = None - select_handlers = None -# -def do_select(): - import select - reply = apply(select.select, select_args) - for mode in 0, 1, 2: - list = reply[mode] - for fd in list: - handler = select_handlers[mode][`fd`] - handler(fd, 'rwx'[mode]) - - -# Event processing main loop. -# Return when there are no windows left, or when an unhandled -# exception occurs. (It is safe to restart the main loop after -# an unsuccessful exit.) -# Python's stdwin.getevent() turns WE_COMMAND/WC_CANCEL events -# into KeyboardInterrupt exceptions; these are turned back in events. -# -recursion_level = 0 # Hack to make it reentrant -def mainloop(): - global recursion_level - recursion_level = recursion_level + 1 - try: - stdwin_select_handler() # Process events already in queue - while 1: - if windows and not fdlist: - while windows and not fdlist: - try: - event = stdwinq.getevent() - except KeyboardInterrupt: - event = (WE_COMMAND, \ - None, WC_CANCEL) - dispatch(event) - elif windows and fdlist: - fd = stdwin.fileno() - if recursion_level == 1: - registerfd(fd, 'r', stdwin_select_handler) - try: - while windows: - do_select() - stdwin_select_handler() - finally: - if recursion_level == 1: - unregisterfd(fd) - elif fdlist: - while fdlist and not windows: - do_select() - else: - break - finally: - recursion_level = recursion_level - 1 - - -# Check for events without ever blocking -# -def check(): - stdwin_select_handler() - # XXX Should check for socket stuff as well - - -# Handle stdwin events until none are left -# -def stdwin_select_handler(*args): - while 1: - try: - event = stdwinq.pollevent() - except KeyboardInterrupt: - event = (WE_COMMAND, None, WC_CANCEL) - if event is None: - break - dispatch(event) - - -# Run a modal dialog loop for a window. The dialog window must have -# been registered first. This prohibits most events (except size/draw -# events) to other windows. The modal dialog loop ends when the -# dialog window unregisters itself. -# -passthrough = WE_SIZE, WE_DRAW -beeping = WE_MOUSE_DOWN, WE_COMMAND, WE_CHAR, WE_KEY, WE_CLOSE, WE_MENU -# -def modaldialog(window): - if window not in windows: - raise ValueError, 'modaldialog window not registered' - while window in windows: - try: - event = stdwinq.getevent() - except KeyboardInterrupt: - event = WE_COMMAND, None, WC_CANCEL - etype, ewindow, edetail = event - if etype not in passthrough and ewindow <> window: - if etype in beeping: - stdwin.fleep() - continue - dispatch(event) - - -# Dispatch a single event. -# Events for the no window in particular are sent to the active window -# or to the last window that received an event (these hacks are for the -# WE_LOST_SEL event, which is directed to no particular window). -# Windows not in the windows list don't get their events: -# events for such windows are silently ignored. -# -def dispatch(event): - global last_window - if event[1] == None: - active = stdwin.getactive() - if active: last_window = active - else: - last_window = event[1] - if last_window in windows: - last_window.dispatch(event) - - -# Dialog base class -# -class Dialog: - # - def __init__(self, title): - self.window = stdwin.open(title) - self.window.dispatch = self.dispatch - register(self.window) - # - def close(self): - unregister(self.window) - del self.window.dispatch - self.window.close() - # - def dispatch(self, event): - etype, ewindow, edetail = event - if etype == WE_CLOSE: - self.close() - - -# Standard modal dialogs -# XXX implemented using stdwin dialogs for now -# -def askstr(prompt, default): - return stdwin.askstr(prompt, default) -# -def askync(prompt, yesorno): - return stdwin.askync(prompt, yesorno) -# -def askfile(prompt, default, new): - return stdwin.askfile(prompt, default, new) -# -def message(msg): - stdwin.message(msg) diff --git a/Lib/lib-stdwin/rect.py b/Lib/lib-stdwin/rect.py deleted file mode 100644 index 393eafd769..0000000000 --- a/Lib/lib-stdwin/rect.py +++ /dev/null @@ -1,89 +0,0 @@ -# Module 'rect'. -# -# Operations on rectangles. -# There is some normalization: all results return the object 'empty' -# if their result would contain no points. - - -# Exception. -# -error = 'rect.error' - - -# The empty rectangle. -# -empty = (0, 0), (0, 0) - - -# Check if a rectangle is empty. -# -def is_empty(r): - (left, top), (right, bottom) = r - return left >= right or top >= bottom - - -# Compute the intersection or two or more rectangles. -# This works with a list or tuple argument. -# -def intersect(list): - if not list: raise error, 'intersect called with empty list' - if is_empty(list[0]): return empty - (left, top), (right, bottom) = list[0] - for rect in list[1:]: - if is_empty(rect): - return empty - (l, t), (r, b) = rect - if left < l: left = l - if top < t: top = t - if right > r: right = r - if bottom > b: bottom = b - if is_empty(((left, top), (right, bottom))): - return empty - return (left, top), (right, bottom) - - -# Compute the smallest rectangle containing all given rectangles. -# This works with a list or tuple argument. -# -def union(list): - (left, top), (right, bottom) = list[0] - for (l, t), (r, b) in list[1:]: - if not is_empty(((l, t), (r, b))): - if l < left: left = l - if t < top: top = t - if r > right: right = r - if b > bottom: bottom = b - res = (left, top), (right, bottom) - if is_empty(res): - return empty - return res - - -# Check if a point is in a rectangle. -# -def pointinrect((h, v), ((left, top), (right, bottom))): - return left <= h < right and top <= v < bottom - - -# Return a rectangle that is dh, dv inside another -# -def inset(((left, top), (right, bottom)), (dh, dv)): - left = left + dh - top = top + dv - right = right - dh - bottom = bottom - dv - r = (left, top), (right, bottom) - if is_empty(r): - return empty - else: - return r - - -# Conversions between rectangles and 'geometry tuples', -# given as origin (h, v) and dimensions (width, height). -# -def rect2geom((left, top), (right, bottom)): - return (left, top), (right-left, bottom-top) - -def geom2rect((h, v), (width, height)): - return (h, v), (h+width, v+height) diff --git a/Lib/lib-stdwin/srcwin.py b/Lib/lib-stdwin/srcwin.py deleted file mode 100644 index 29b78010a6..0000000000 --- a/Lib/lib-stdwin/srcwin.py +++ /dev/null @@ -1,129 +0,0 @@ -# srcwin.py -- a source listing window - -import stdwin -from stdwinevents import * -import basewin - -WIDTH = 40 -MAXHEIGHT = 24 - - -class TextWindow(basewin.BaseWindow): - - def __init__(self, title, contents): - self.contents = contents - self.linecount = countlines(self.contents) - # - self.lineheight = lh = stdwin.lineheight() - self.leftmargin = self.getmargin() - self.top = 0 - self.rightmargin = 30000 # Infinity - self.bottom = lh * self.linecount - # - width = WIDTH*stdwin.textwidth('0') - height = lh*min(MAXHEIGHT, self.linecount) - stdwin.setdefwinsize(width, height) - basewin.BaseWindow.__init__(self, title) - # - self.win.setdocsize(0, self.bottom) - self.initeditor() - - def initeditor(self): - r = (self.leftmargin, self.top), (self.rightmargin, self.bottom) - self.editor = self.win.textcreate(r) - self.editor.settext(self.contents) - - def closeeditor(self): - self.editor.close() - -# def reopen(self): -# self.closeeditor() -# basewin.BaseWindow.reopen(self) -# self.initeditor() - - # Override the following two methods to format line numbers differently - - def getmark(self, lineno): - return `lineno` - - def getmargin(self): - return stdwin.textwidth(`self.linecount + 1` + ' ') - - # Event dispatcher, called from mainloop.mainloop() - - def dispatch(self, event): - if event[0] == WE_NULL: return # Dummy tested by mainloop - if event[0] == WE_DRAW or not self.editor.event(event): - basewin.BaseWindow.dispatch(self, event) - - # Event handlers - - def close(self): - self.closeeditor() - basewin.BaseWindow.close(self) - - def draw(self, detail): - dummy = self.editor.draw(detail) - # Draw line numbers - (left, top), (right, bottom) = detail - topline = top/self.lineheight - botline = bottom/self.lineheight + 1 - botline = min(self.linecount, botline) - d = self.win.begindrawing() - try: - h, v = 0, self.lineheight * topline - for lineno in range(topline+1, botline+1): - d.text((h, v), self.getmark(lineno)) - v = v + self.lineheight - finally: - d.close() - - # Calls from outside - - def changemark(self, lineno): # redraw the mark for a line - left = 0 - top = (lineno-1) * self.lineheight - right = self.leftmargin - bottom = lineno * self.lineheight - d = self.win.begindrawing() - try: - d.erase((left, top), (right, bottom)) - d.text((left, top), self.getmark(lineno)) - finally: - d.close() - - def showline(self, lineno): # scroll to make a line visible - left = 0 - top = (lineno-1) * self.lineheight - right = self.leftmargin - bottom = lineno * self.lineheight - self.win.show((left, top), (right, bottom)) - - -# Subroutine to count the number of lines in a string - -def countlines(text): - n = 0 - for c in text: - if c == '\n': n = n+1 - if text and text[-1] != '\n': n = n+1 # Partial last line - return n - - -class SourceWindow(TextWindow): - - def __init__(self, filename): - self.filename = filename - f = open(self.filename, 'r') - contents = f.read() - f.close() - TextWindow.__init__(self, self.filename, contents) - -# ------------------------------ testing ------------------------------ - -TESTFILE = 'srcwin.py' - -def test(): - import mainloop - sw = SourceWindow(TESTFILE) - mainloop.mainloop() diff --git a/Lib/lib-stdwin/stdwinevents.py b/Lib/lib-stdwin/stdwinevents.py deleted file mode 100644 index 62cf8d2931..0000000000 --- a/Lib/lib-stdwin/stdwinevents.py +++ /dev/null @@ -1,61 +0,0 @@ -# Module 'stdwinevents' -- Constants for stdwin event types -# -# Suggested usage: -# from stdwinevents import * - -# The function stdwin.getevent() returns a tuple containing: -# (type, window, detail) -# where detail may be or a value depending on type, see below: - -# Values for type: - -WE_NULL = 0 # not reported -- means 'no event' internally -WE_ACTIVATE = 1 # detail is None -WE_CHAR = 2 # detail is the character -WE_COMMAND = 3 # detail is one of the WC_* constants below -WE_MOUSE_DOWN = 4 # detail is ((h, v), clicks, button, mask) -WE_MOUSE_MOVE = 5 # ditto -WE_MOUSE_UP = 6 # ditto -WE_MENU = 7 # detail is (menu, item) -WE_SIZE = 8 # detail is (width, height) -WE_MOVE = 9 # not reported -- reserved for future use -WE_DRAW = 10 # detail is ((left, top), (right, bottom)) -WE_TIMER = 11 # detail is None -WE_DEACTIVATE = 12 # detail is None -WE_EXTERN = 13 # detail is None -WE_KEY = 14 # detail is ??? -WE_LOST_SEL = 15 # detail is selection number -WE_CLOSE = 16 # detail is None - -# Values for detail when type is WE_COMMAND: - -WC_CLOSE = 1 # obsolete; now reported as WE_CLOSE -WC_LEFT = 2 # left arrow key -WC_RIGHT = 3 # right arrow key -WC_UP = 4 # up arrow key -WC_DOWN = 5 # down arrow key -WC_CANCEL = 6 # not reported -- turned into KeyboardInterrupt -WC_BACKSPACE = 7 # backspace key -WC_TAB = 8 # tab key -WC_RETURN = 9 # return or enter key - -# Selection numbers - -WS_CLIPBOARD = 0 -WS_PRIMARY = 1 -WS_SECONDARY = 2 - -# Modifier masks in key and mouse events - -WM_SHIFT = (1 << 0) -WM_LOCK = (1 << 1) -WM_CONTROL = (1 << 2) -WM_META = (1 << 3) -WM_OPTION = (1 << 4) -WM_NUM = (1 << 5) - -WM_BUTTON1 = (1 << 8) -WM_BUTTON2 = (1 << 9) -WM_BUTTON3 = (1 << 10) -WM_BUTTON4 = (1 << 11) -WM_BUTTON5 = (1 << 12) diff --git a/Lib/lib-stdwin/stdwinq.py b/Lib/lib-stdwin/stdwinq.py deleted file mode 100644 index af72986d68..0000000000 --- a/Lib/lib-stdwin/stdwinq.py +++ /dev/null @@ -1,53 +0,0 @@ -# Replacements for getevent() and pollevent(), -# and new functions ungetevent() and sync(). - - -# Every library module should ideally use this instead of -# stdwin.{get,poll}event(), so applications can use the services -# of ungetevent() and sync(). - - -import stdwin - - -# Events read ahead are stored in this queue. -# -queue = [] - - -# Replacement for getevent(). -# -def getevent(): - if queue: - event = queue[0] - del queue[0] - return event - else: - return stdwin.getevent() - - -# Replacement for pollevent(). -# -def pollevent(): - if queue: - return getevent() - else: - return stdwin.pollevent() - - -# Push an event back in the queue. -# -def ungetevent(event): - queue.insert(0, event) - - -# Synchronize the display. It turns out that this is the way to -# force STDWIN to call XSync(), which some (esoteric) applications need. -# (This is stronger than just flushing -- it actually waits for a -# positive response from the X server on the last command issued.) -# -def sync(): - while 1: - event = stdwin.pollevent() - if not event: break - queue.append(event) diff --git a/Lib/lib-stdwin/tablewin.py b/Lib/lib-stdwin/tablewin.py deleted file mode 100644 index eba161d6f3..0000000000 --- a/Lib/lib-stdwin/tablewin.py +++ /dev/null @@ -1,236 +0,0 @@ -# Module 'tablewin' - -# Display a table, with per-item actions: - -# A1 | A2 | A3 | .... | AN -# B1 | B2 | B3 | .... | BN -# C1 | C2 | C3 | .... | CN -# .. | .. | .. | .... | .. -# Z1 | Z2 | Z3 | .... | ZN - -# Not all columns need to have the same length. -# The data structure is a list of columns; -# each column is a list of items. -# Each item is a pair of a string and an action procedure. -# The first item may be a column title. - -import stdwin -import gwin -from stdwinevents import * - -def open(title, data): # Public function to open a table window - # - # Set geometry parameters (one day, these may be changeable) - # - margin = stdwin.textwidth(' ') - lineheight = stdwin.lineheight() - # - # Geometry calculations - # - colstarts = [0] - totwidth = 0 - maxrows = 0 - for coldata in data: - # Height calculations - rows = len(coldata) - if rows > maxrows: maxrows = rows - # Width calculations - width = colwidth(coldata) + margin - totwidth = totwidth + width - colstarts.append(totwidth) - # - # Calculate document and window height - # - docwidth, docheight = totwidth, maxrows*lineheight - winwidth, winheight = docwidth, docheight - if winwidth > stdwin.textwidth('n')*100: winwidth = 0 - if winheight > stdwin.lineheight()*30: winheight = 0 - # - # Create the window - # - stdwin.setdefwinsize(winwidth, winheight) - w = gwin.open(title) - # - # Set properties and override methods - # - w.data = data - w.margin = margin - w.lineheight = lineheight - w.colstarts = colstarts - w.totwidth = totwidth - w.maxrows = maxrows - w.selection = (-1, -1) - w.lastselection = (-1, -1) - w.selshown = 0 - w.setdocsize(docwidth, docheight) - w.draw = draw - w.mup = mup - w.arrow = arrow - # - # Return - # - return w - -def update(w, data): # Change the data - # - # Hide selection - # - hidesel(w, w.begindrawing()) - # - # Get old geometry parameters - # - margin = w.margin - lineheight = w.lineheight - # - # Geometry calculations - # - colstarts = [0] - totwidth = 0 - maxrows = 0 - for coldata in data: - # Height calculations - rows = len(coldata) - if rows > maxrows: maxrows = rows - # Width calculations - width = colwidth(coldata) + margin - totwidth = totwidth + width - colstarts.append(totwidth) - # - # Calculate document and window height - # - docwidth, docheight = totwidth, maxrows*lineheight - # - # Set changed properties and change window size - # - w.data = data - w.colstarts = colstarts - w.totwidth = totwidth - w.maxrows = maxrows - w.change((0, 0), (10000, 10000)) - w.setdocsize(docwidth, docheight) - w.change((0, 0), (docwidth, docheight)) - # - # Show selection, or forget it if out of range - # - showsel(w, w.begindrawing()) - if not w.selshown: w.selection = (-1, -1) - -def colwidth(coldata): # Subroutine to calculate column width - maxwidth = 0 - for string, action in coldata: - width = stdwin.textwidth(string) - if width > maxwidth: maxwidth = width - return maxwidth - -def draw(w, ((left, top), (right, bottom))): # Draw method - ileft = whichcol(w, left) - iright = whichcol(w, right-1) + 1 - if iright > len(w.data): iright = len(w.data) - itop = divmod(top, w.lineheight)[0] - if itop < 0: itop = 0 - ibottom, remainder = divmod(bottom, w.lineheight) - if remainder: ibottom = ibottom + 1 - d = w.begindrawing() - if ileft <= w.selection[0] < iright: - if itop <= w.selection[1] < ibottom: - hidesel(w, d) - d.erase((left, top), (right, bottom)) - for i in range(ileft, iright): - col = w.data[i] - jbottom = len(col) - if ibottom < jbottom: jbottom = ibottom - h = w.colstarts[i] - v = itop * w.lineheight - for j in range(itop, jbottom): - string, action = col[j] - d.text((h, v), string) - v = v + w.lineheight - showsel(w, d) - -def mup(w, detail): # Mouse up method - (h, v), nclicks, button, mask = detail - icol = whichcol(w, h) - if 0 <= icol < len(w.data): - irow = divmod(v, w.lineheight)[0] - col = w.data[icol] - if 0 <= irow < len(col): - string, action = col[irow] - action(w, string, (icol, irow), detail) - -def whichcol(w, h): # Return column number (may be >= len(w.data)) - for icol in range(0, len(w.data)): - if h < w.colstarts[icol+1]: - return icol - return len(w.data) - -def arrow(w, type): - if type == WC_LEFT: - incr = -1, 0 - elif type == WC_UP: - incr = 0, -1 - elif type == WC_RIGHT: - incr = 1, 0 - elif type == WC_DOWN: - incr = 0, 1 - else: - return - icol, irow = w.lastselection - icol = icol + incr[0] - if icol < 0: icol = len(w.data)-1 - if icol >= len(w.data): icol = 0 - if 0 <= icol < len(w.data): - irow = irow + incr[1] - if irow < 0: irow = len(w.data[icol]) - 1 - if irow >= len(w.data[icol]): irow = 0 - else: - irow = 0 - if 0 <= icol < len(w.data) and 0 <= irow < len(w.data[icol]): - w.lastselection = icol, irow - string, action = w.data[icol][irow] - detail = (0, 0), 1, 1, 1 - action(w, string, (icol, irow), detail) - - -# Selection management -# TO DO: allow multiple selected entries - -def select(w, selection): # Public function to set the item selection - d = w.begindrawing() - hidesel(w, d) - w.selection = selection - showsel(w, d) - if w.selshown: lastselection = selection - -def hidesel(w, d): # Hide the selection, if shown - if w.selshown: invertsel(w, d) - -def showsel(w, d): # Show the selection, if hidden - if not w.selshown: invertsel(w, d) - -def invertsel(w, d): # Invert the selection, if valid - icol, irow = w.selection - if 0 <= icol < len(w.data) and 0 <= irow < len(w.data[icol]): - left = w.colstarts[icol] - right = w.colstarts[icol+1] - top = irow * w.lineheight - bottom = (irow+1) * w.lineheight - d.invert((left, top), (right, bottom)) - w.selshown = (not w.selshown) - - -# Demonstration - -def demo_action(w, string, (icol, irow), detail): # Action function for demo - select(w, (irow, icol)) - -def demo(): # Demonstration - da = demo_action # shorthand - col0 = [('a1', da), ('bbb1', da), ('c1', da)] - col1 = [('a2', da), ('bbb2', da)] - col2 = [('a3', da), ('b3', da), ('c3', da), ('d4', da), ('d5', da)] - col3 = [] - for i in range(1, 31): col3.append('xxx' + `i`, da) - data = [col0, col1, col2, col3] - w = open('tablewin.demo', data) - gwin.mainloop() - return w diff --git a/Lib/lib-stdwin/textwin.py b/Lib/lib-stdwin/textwin.py deleted file mode 100644 index 778717fe14..0000000000 --- a/Lib/lib-stdwin/textwin.py +++ /dev/null @@ -1,117 +0,0 @@ -# Module 'textwin' - -# Text windows, a subclass of gwin - -import stdwin -import gwin -from stdwinevents import * - - -def fixsize(w): - docwidth, docheight = w.text.getrect()[1] - winheight = w.getwinsize()[1] - if winheight > docheight: docheight = winheight - w.setdocsize(0, docheight) - fixeditmenu(w) - -def cut(w, m, id): - s = w.text.getfocustext() - if s: - stdwin.setcutbuffer(0, s) - w.text.replace('') - fixsize(w) - -def copy(w, m, id): - s = w.text.getfocustext() - if s: - stdwin.setcutbuffer(0, s) - fixeditmenu(w) - -def paste(w, m, id): - w.text.replace(stdwin.getcutbuffer(0)) - fixsize(w) - -def addeditmenu(w): - m = w.editmenu = w.menucreate('Edit') - m.action = [] - m.additem('Cut', 'X') - m.action.append(cut) - m.additem('Copy', 'C') - m.action.append(copy) - m.additem('Paste', 'V') - m.action.append(paste) - -def fixeditmenu(w): - m = w.editmenu - f = w.text.getfocus() - can_copy = (f[0] < f[1]) - m.enable(1, can_copy) - if not w.readonly: - m.enable(0, can_copy) - m.enable(2, (stdwin.getcutbuffer(0) <> '')) - -def draw(w, area): # Draw method - w.text.draw(area) - -def size(w, newsize): # Size method - w.text.move((0, 0), newsize) - fixsize(w) - -def close(w): # Close method - del w.text # Break circular ref - gwin.close(w) - -def char(w, c): # Char method - w.text.replace(c) - fixsize(w) - -def backspace(w): # Backspace method - void = w.text.event(WE_COMMAND, w, WC_BACKSPACE) - fixsize(w) - -def arrow(w, detail): # Arrow method - w.text.arrow(detail) - fixeditmenu(w) - -def mdown(w, detail): # Mouse down method - void = w.text.event(WE_MOUSE_DOWN, w, detail) - fixeditmenu(w) - -def mmove(w, detail): # Mouse move method - void = w.text.event(WE_MOUSE_MOVE, w, detail) - -def mup(w, detail): # Mouse up method - void = w.text.event(WE_MOUSE_UP, w, detail) - fixeditmenu(w) - -def activate(w): # Activate method - fixeditmenu(w) - -def open(title, str): # Display a string in a window - w = gwin.open(title) - w.readonly = 0 - w.text = w.textcreate((0, 0), w.getwinsize()) - w.text.replace(str) - w.text.setfocus(0, 0) - addeditmenu(w) - fixsize(w) - w.draw = draw - w.size = size - w.close = close - w.mdown = mdown - w.mmove = mmove - w.mup = mup - w.char = char - w.backspace = backspace - w.arrow = arrow - w.activate = activate - return w - -def open_readonly(title, str): # Same with char input disabled - w = open(title, str) - w.readonly = 1 - w.char = w.backspace = gwin.nop - # Disable Cut and Paste menu item; leave Copy alone - w.editmenu.enable(0, 0) - w.editmenu.enable(2, 0) - return w diff --git a/Lib/lib-stdwin/wdb.py b/Lib/lib-stdwin/wdb.py deleted file mode 100644 index d5c28bb9f1..0000000000 --- a/Lib/lib-stdwin/wdb.py +++ /dev/null @@ -1,309 +0,0 @@ -# wdb.py -- a window-based Python debugger - -# XXX To do: -# - don't fall out of bottom frame - - -import stdwin -from stdwinevents import * -import sys -import basewin -import bdb -import repr - -WIDTH = 40 -HEIGHT = 8 - -WdbDone = 'wdb.WdbDone' # Exception to continue execution - - -class Wdb(bdb.Bdb, basewin.BaseWindow): # Window debugger - - def __init__(self): - self.sourcewindows = {} - self.framewindows = {} - bdb.Bdb.__init__(self) - width = WIDTH*stdwin.textwidth('0') - height = HEIGHT*stdwin.lineheight() - stdwin.setdefwinsize(width, height) - basewin.BaseWindow.__init__(self, '--Stack--') - self.closed = 0 - - def reset(self): - if self.closed: raise RuntimeError, 'already closed' - bdb.Bdb.reset(self) - self.forget() - - def forget(self): - self.lineno = None - self.stack = [] - self.curindex = 0 - self.curframe = None - for fn in self.sourcewindows.keys(): - self.sourcewindows[fn].resetlineno() - - def setup(self, f, t): - self.forget() - self.stack, self.curindex = self.get_stack(f, t) - self.curframe = self.stack[self.curindex][0] - # Build a list of current frames - cfl = [] - for f, i in self.stack: cfl.append(f) - # Remove deactivated frame windows - for name in self.framewindows.keys(): - fw = self.framewindows[name] - if fw.frame not in cfl: fw.close() - else: fw.refreshframe() - # Refresh the stack window - self.refreshstack() - - # Override Bdb methods (except user_call, for now) - - def user_line(self, frame): - # This function is called when we stop or break at this line - self.interaction(frame, None) - - def user_return(self, frame, return_value): - # This function is called when a return trap is set here - frame.f_locals['__return__'] = return_value - self.settitle('--Return--') - self.interaction(frame, None) - if not self.closed: - self.settitle('--Stack--') - - def user_exception(self, frame, (exc_type, exc_value, exc_traceback)): - # This function is called if an exception occurs, - # but only if we are to stop at or just below this level - frame.f_locals['__exception__'] = exc_type, exc_value - self.settitle(exc_type + ': ' + repr.repr(exc_value)) - stdwin.fleep() - self.interaction(frame, exc_traceback) - if not self.closed: - self.settitle('--Stack--') - - # Change the title - - def settitle(self, title): - self.savetitle = self.win.gettitle() - self.win.settitle(title) - - # General interaction function - - def interaction(self, frame, traceback): - import mainloop - self.popup() - self.setup(frame, traceback) - try: - mainloop.mainloop() - except WdbDone: - pass - self.forget() - - # Functions whose name is do_X for some character X - # are callable directly from the keyboard. - - def do_up(self): - if self.curindex == 0: - stdwin.fleep() - else: - self.curindex = self.curindex - 1 - self.curframe = self.stack[self.curindex][0] - self.refreshstack() - do_u = do_up - - def do_down(self): - if self.curindex + 1 == len(self.stack): - stdwin.fleep() - else: - self.curindex = self.curindex + 1 - self.curframe = self.stack[self.curindex][0] - self.refreshstack() - do_d = do_down - - def do_step(self): - self.set_step() - raise WdbDone - do_s = do_step - - def do_next(self): - self.set_next(self.curframe) - raise WdbDone - do_n = do_next - - def do_return(self): - self.set_return(self.curframe) - raise WdbDone - do_r = do_return - - def do_continue(self): - self.set_continue() - raise WdbDone - do_c = do_cont = do_continue - - def do_quit(self): - self.close() - raise WdbDone - do_q = do_quit - - def do_list(self): - fn = self.curframe.f_code.co_filename - if not self.sourcewindows.has_key(fn): - import wdbsrcwin - try: - self.sourcewindows[fn] = wdbsrcwin. \ - DebuggerSourceWindow(self, fn) - except IOError: - stdwin.fleep() - return - w = self.sourcewindows[fn] - lineno = self.stack[self.curindex][1] - w.setlineno(lineno) - w.popup() - do_l = do_list - - def do_frame(self): - name = 'locals' + `self.curframe`[16:-1] - if self.framewindows.has_key(name): - self.framewindows[name].popup() - else: - import wdbframewin - self.framewindows[name] = \ - wdbframewin.FrameWindow(self, \ - self.curframe, \ - self.curframe.f_locals, name) - do_f = do_frame - - def do_globalframe(self): - name = 'globals' + `self.curframe`[16:-1] - if self.framewindows.has_key(name): - self.framewindows[name].popup() - else: - import wdbframewin - self.framewindows[name] = \ - wdbframewin.FrameWindow(self, \ - self.curframe, \ - self.curframe.f_globals, name) - do_g = do_globalframe - - # Link between the debugger and the window - - def refreshstack(self): - height = stdwin.lineheight() * (1 + len(self.stack)) - self.win.setdocsize((0, height)) - self.refreshall() # XXX be more subtle later - # Also pass the information on to the source windows - filename = self.curframe.f_code.co_filename - lineno = self.curframe.f_lineno - for fn in self.sourcewindows.keys(): - w = self.sourcewindows[fn] - if fn == filename: - w.setlineno(lineno) - else: - w.resetlineno() - - # The remaining methods override BaseWindow methods - - def close(self): - if not self.closed: - basewin.BaseWindow.close(self) - self.closed = 1 - for key in self.sourcewindows.keys(): - self.sourcewindows[key].close() - for key in self.framewindows.keys(): - self.framewindows[key].close() - self.set_quit() - - def char(self, detail): - try: - func = eval('self.do_' + detail) - except (AttributeError, SyntaxError): - stdwin.fleep() - return - func() - - def command(self, detail): - if detail == WC_UP: - self.do_up() - elif detail == WC_DOWN: - self.do_down() - - def mouse_down(self, detail): - (h, v), clicks, button, mask = detail - i = v / stdwin.lineheight() - if 0 <= i < len(self.stack): - if i != self.curindex: - self.curindex = i - self.curframe = self.stack[self.curindex][0] - self.refreshstack() - elif clicks == 2: - self.do_frame() - else: - stdwin.fleep() - - def draw(self, detail): - import linecache, codehack, string - d = self.win.begindrawing() - try: - h, v = 0, 0 - for f, lineno in self.stack: - fn = f.f_code.co_filename - if f is self.curframe: - s = '> ' - else: - s = ' ' - s = s + fn + '(' + `lineno` + ')' - s = s + codehack.getcodename(f.f_code) - if f.f_locals.has_key('__args__'): - args = f.f_locals['__args__'] - if args is not None: - s = s + repr.repr(args) - if f.f_locals.has_key('__return__'): - rv = f.f_locals['__return__'] - s = s + '->' - s = s + repr.repr(rv) - line = linecache.getline(fn, lineno) - if line: s = s + ': ' + string.strip(line) - d.text((h, v), s) - v = v + d.lineheight() - finally: - d.close() - - -# Simplified interface - -def run(statement): - x = Wdb() - try: x.run(statement) - finally: x.close() - -def runctx(statement, globals, locals): - x = Wdb() - try: x.runctx(statement, globals, locals) - finally: x.close() - -def runcall(*args): - x = Wdb() - try: apply(x.runcall, args) - finally: x.close() - - -# Post-Mortem interface - -def post_mortem(traceback): - x = Wdb() - x.reset() - x.interaction(None, traceback) - -def pm(): - import sys - post_mortem(sys.last_traceback) - - -# Main program for testing - -TESTCMD = 'import x; x.main()' - -def test(): - import linecache - linecache.checkcache() - run(TESTCMD) diff --git a/Lib/lib-stdwin/wdbframewin.py b/Lib/lib-stdwin/wdbframewin.py deleted file mode 100644 index 13bd1731a9..0000000000 --- a/Lib/lib-stdwin/wdbframewin.py +++ /dev/null @@ -1,143 +0,0 @@ -# wdbframewin.py -- frame window for wdb.py - -# XXX To do: -# - display function name in window title -# - execute arbitrary statements instead of just evaluating expressions -# - allow setting variables by editing their values - - -import stdwin -from stdwinevents import * -import basewin -import sys - -WIDTH = 40 -MINHEIGHT = 8 -MAXHEIGHT = 16 - -class FrameWindow(basewin.BaseWindow): - - def __init__(self, debugger, frame, dict, name): - self.debugger = debugger - self.frame = frame # Not used except for identity tests - self.dict = dict - self.name = name - nl = max(MINHEIGHT, len(self.dict) + 5) - nl = min(nl, MAXHEIGHT) - width = WIDTH*stdwin.textwidth('0') - height = nl*stdwin.lineheight() - stdwin.setdefwinsize(width, height) - basewin.BaseWindow.__init__( - self, '--Frame ' + name + '--') - # XXX Should use current function name - self.initeditor() - self.displaylist = ['>>>', '', '-'*WIDTH] - self.refreshframe() - - def initeditor(self): - r = (stdwin.textwidth('>>> '), 0), (30000, stdwin.lineheight()) - self.editor = self.win.textcreate(r) - - def closeeditor(self): - self.editor.close() - - def dispatch(self, event): - type, win, detail = event - if type == WE_NULL: return # Dummy tested by mainloop - if type in (WE_DRAW, WE_COMMAND) \ - or not self.editor.event(event): - basewin.BaseWindow.dispatch(self, event) - - def close(self): - del self.debugger.framewindows[self.name] - del self.debugger, self.dict - self.closeeditor() - basewin.BaseWindow.close(self) - - def command(self, detail): - if detail == WC_RETURN: - self.re_eval() - else: - dummy = self.editor.event(WE_COMMAND, \ - self.win, detail) - - def mouse_down(self, detail): - (h, v), clicks, button, mask = detail - if clicks != 2: - return - i = v / stdwin.lineheight() - if 5 <= i < len(self.displaylist): - import string - name = string.splitfields(self.displaylist[i],' = ')[0] - if not self.dict.has_key(name): - stdwin.fleep() - return - value = self.dict[name] - if not hasattr(value, '__dict__'): - stdwin.fleep() - return - name = 'instance ' + `value` - if self.debugger.framewindows.has_key(name): - self.debugger.framewindows[name].popup() - else: - self.debugger.framewindows[name] = \ - FrameWindow(self.debugger, - self.frame, value.__dict__, - name) - return - stdwin.fleep() - - def re_eval(self): - import string, repr - expr = string.strip(self.editor.gettext()) - if expr == '': - output = '' - else: - globals = self.frame.f_globals - globals['__privileged__'] = 1 - locals = self.dict - try: - value = eval(expr, globals, locals) - output = repr.repr(value) - except: - output = sys.exc_type + ': ' + `sys.exc_value` - self.displaylist[1] = output - lh = stdwin.lineheight() - r = (-10, 0), (30000, 2*lh) - self.win.change(r) - self.editor.setfocus(0, len(expr)) - - def draw(self, detail): - (left, top), (right, bottom) = detail - dummy = self.editor.draw(detail) - d = self.win.begindrawing() - try: - lh = d.lineheight() - h, v = 0, 0 - for line in self.displaylist: - if v+lh > top and v < bottom: - d.text((h, v), line) - v = v + lh - finally: - d.close() - - def refreshframe(self): - import repr - del self.displaylist[3:] - self.re_eval() - names = self.dict.keys() - for key, label in ('__args__', 'Args: '), \ - ('__return__', 'Return: '): - if self.dict.has_key(key): - names.remove(key) - value = self.dict[key] - label = label + repr.repr(value) - self.displaylist.append(label) - names.sort() - for name in names: - value = self.dict[name] - line = name + ' = ' + repr.repr(value) - self.displaylist.append(line) - self.win.setdocsize(0, \ - stdwin.lineheight() * len(self.displaylist)) - self.refreshall() # XXX Be more subtle later diff --git a/Lib/lib-stdwin/wdbsrcwin.py b/Lib/lib-stdwin/wdbsrcwin.py deleted file mode 100644 index f79fab94be..0000000000 --- a/Lib/lib-stdwin/wdbsrcwin.py +++ /dev/null @@ -1,100 +0,0 @@ -# wdbsrcwin.py -- source window for wdb - -import stdwin -from stdwinevents import * -import srcwin - - -class DebuggerSourceWindow(srcwin.SourceWindow): - - def __init__(self, debugger, filename): - self.debugger = debugger - self.curlineno = 0 - self.focus = 0 - srcwin.SourceWindow.__init__(self, filename) - - def close(self): - del self.debugger.sourcewindows[self.filename] - del self.debugger - srcwin.SourceWindow.close(self) - - def dispatch(self, event): - type, win, detail = event - if type == WE_CHAR: - self.char(detail) - elif type == WE_COMMAND: - self.command(detail) - elif type == WE_MOUSE_DOWN: - self.mouse_down(detail) - else: - srcwin.SourceWindow.dispatch(self, event) - - def char(self, detail): - self.debugger.char(detail) - - def command(self, detail): - self.debugger.command(detail) - - def mouse_down(self, detail): - (h, v), clicks, button, mask = detail - if h >= self.leftmargin: - srcwin.SourceWindow.dispatch(self, \ - (WE_MOUSE_DOWN, self.win, detail)) - return - lineno = v/self.lineheight + 1 - if 1 <= lineno <= self.linecount: - if self.debugger.get_break(self.filename, lineno): - f = self.debugger.clear_break - else: - f = self.debugger.set_break - err = f(self.filename, lineno) - if err: stdwin.message(err) - else: self.changemark(lineno) - else: - stdwin.fleep() - - def getmark(self, lineno): - s = `lineno` - if lineno == self.focus: - s = '[' + s + ']' - else: - s = ' ' + s + ' ' - if lineno == self.curlineno: - s = s + '->' - else: - s = s + ' ' - br = self.debugger.breaks - if br.has_key(self.filename) and lineno in br[self.filename]: - s = s + 'B' - else: - s = s + ' ' - return s - - def getmargin(self): - return stdwin.textwidth('[' + `self.linecount+1` + ']->B ') - - def setlineno(self, newlineno): - if newlineno != self.curlineno: - oldlineno = self.curlineno - self.curlineno = newlineno - self.changemark(oldlineno) - self.changemark(newlineno) - if newlineno != 0: - self.showline(newlineno) - - def resetlineno(self): - self.setlineno(0) - - def setfocus(self, newfocus): - if newfocus != self.focus: - oldfocus = self.focus - self.focus = newfocus - self.changemark(oldfocus) - self.changemark(newfocus) - if newfocus != 0: - self.showline(newfocus) - - def resetfocus(self): - self.setfocus(0) - -# XXX Should get rid of focus stuff again diff --git a/Lib/linecache.py b/Lib/linecache.py deleted file mode 100644 index b981869859..0000000000 --- a/Lib/linecache.py +++ /dev/null @@ -1,90 +0,0 @@ -# Cache lines from files. -# This is intended to read lines from modules imported -- hence if a filename -# is not found, it will look down the module search path for a file by -# that name. - -import sys -import os -from stat import * - -def getline(filename, lineno): - lines = getlines(filename) - if 1 <= lineno <= len(lines): - return lines[lineno-1] - else: - return '' - - -# The cache - -cache = {} # The cache - - -# Clear the cache entirely - -def clearcache(): - global cache - cache = {} - - -# Get the lines for a file from the cache. -# Update the cache if it doesn't contain an entry for this file already. - -def getlines(filename): - if cache.has_key(filename): - return cache[filename][2] - else: - return updatecache(filename) - - -# Discard cache entries that are out of date. -# (This is not checked upon each call!) - -def checkcache(): - for filename in cache.keys(): - size, mtime, lines, fullname = cache[filename] - try: - stat = os.stat(fullname) - except os.error: - del cache[filename] - continue - if size <> stat[ST_SIZE] or mtime <> stat[ST_MTIME]: - del cache[filename] - - -# Update a cache entry and return its list of lines. -# If something's wrong, print a message, discard the cache entry, -# and return an empty list. - -def updatecache(filename): - if cache.has_key(filename): - del cache[filename] - if filename[0] + filename[-1] == '<>': - return [] - fullname = filename - try: - stat = os.stat(fullname) - except os.error, msg: - # Try looking through the module search path - basename = os.path.split(filename)[1] - for dirname in sys.path: - fullname = os.path.join(dirname, basename) - try: - stat = os.stat(fullname) - break - except os.error: - pass - else: - # No luck - print '*** Cannot stat', filename, ':', msg - return [] - try: - fp = open(fullname, 'r') - lines = fp.readlines() - fp.close() - except IOError, msg: - print '*** Cannot open', fullname, ':', msg - return [] - size, mtime = stat[ST_SIZE], stat[ST_MTIME] - cache[filename] = size, mtime, lines, fullname - return lines diff --git a/Lib/macpath.py b/Lib/macpath.py deleted file mode 100644 index b5c17f0be7..0000000000 --- a/Lib/macpath.py +++ /dev/null @@ -1,126 +0,0 @@ -# module 'macpath' -- pathname (or -related) operations for the Macintosh - -import string -import mac -from stat import * - - -# Normalize the case of a pathname. Dummy in Posix, but string.lower here. - -normcase = string.lower - - -# Return true if a path is absolute. -# On the Mac, relative paths begin with a colon, -# but as a special case, paths with no colons at all are also relative. -# Anything else is absolute (the string up to the first colon is the -# volume name). - -def isabs(s): - return ':' in s and s[0] <> ':' - - -# Join two pathnames. -# The result is equivalent to what the second pathname would refer to -# if the first pathname were the current directory. - -def join(s, t): - if (not s) or isabs(t): return t - if t[:1] == ':': t = t[1:] - if ':' not in s: - s = ':' + s - if s[-1:] <> ':': - s = s + ':' - return s + t - - -# Split a pathname in two parts: the directory leading up to the final bit, -# and the basename (the filename, without colons, in that directory). -# The result (s, t) is such that join(s, t) yields the original argument. - -def split(s): - if ':' not in s: return '', s - colon = 0 - for i in range(len(s)): - if s[i] == ':': colon = i+1 - return s[:colon], s[colon:] - - -# Short interfaces to split() - -def dirname(s): return split(s)[0] -def basename(s): return split(s)[1] - - -# XXX This is undocumented and may go away! -# Normalize a pathname: get rid of '::' sequences by backing up, -# e.g., 'foo:bar::bletch' becomes 'foo:bletch'. -# Raise the exception norm_error below if backing up is impossible, -# e.g., for '::foo'. - -norm_error = 'macpath.norm_error: path cannot be normalized' - -def norm(s): - import string - if ':' not in s: - return ':' + s - f = string.splitfields(s, ':') - pre = [] - post = [] - if not f[0]: - pre = f[:1] - f = f[1:] - if not f[len(f)-1]: - post = f[-1:] - f = f[:-1] - res = [] - for seg in f: - if seg: - res.append(seg) - else: - if not res: raise norm_error, 'path starts with ::' - del res[len(res)-1] - if not (pre or res): - raise norm_error, 'path starts with volume::' - if pre: res = pre + res - if post: res = res + post - s = res[0] - for seg in res[1:]: - s = s + ':' + seg - return s - - -# Return true if the pathname refers to an existing directory. - -def isdir(s): - try: - st = mac.stat(s) - except mac.error: - return 0 - return S_ISDIR(st[ST_MODE]) - - -# Return true if the pathname refers to an existing regular file. - -def isfile(s): - try: - st = mac.stat(s) - except mac.error: - return 0 - return S_ISREG(st[ST_MODE]) - - -# Return true if the pathname refers to an existing file or directory. - -def exists(s): - try: - st = mac.stat(s) - except mac.error: - return 0 - return 1 - - -# Normalize path, removing things like ...:A:..:... (yet to be written) - -def normpath(s): - return s diff --git a/Lib/mimetools.py b/Lib/mimetools.py deleted file mode 100644 index 2a076f0345..0000000000 --- a/Lib/mimetools.py +++ /dev/null @@ -1,112 +0,0 @@ -# Various tools used by MIME-reading or MIME-writing programs. - - -import string -import rfc822 - - -# A derived class of rfc822.Message that knows about MIME headers and -# contains some hooks for decoding encoded and multipart messages. - -class Message(rfc822.Message): - - def __init__(self, fp): - rfc822.Message.__init__(self, fp) - self.encodingheader = \ - self.getheader('content-transfer-encoding') - self.typeheader = \ - self.getheader('content-type') - self.parsetype() - self.parseplist() - - def parsetype(self): - str = self.typeheader - if str == None: - str = 'text/plain' - if ';' in str: - i = string.index(str, ';') - self.plisttext = str[i:] - str = str[:i] - else: - self.plisttext = '' - fields = string.splitfields(str, '/') - for i in range(len(fields)): - fields[i] = string.lower(string.strip(fields[i])) - self.type = string.joinfields(fields, '/') - self.maintype = fields[0] - self.subtype = string.joinfields(fields[1:], '/') - - def parseplist(self): - str = self.plisttext - self.plist = [] - while str[:1] == ';': - str = str[1:] - if ';' in str: - # XXX Should parse quotes! - end = string.index(str, ';') - else: - end = len(str) - f = str[:end] - if '=' in f: - i = string.index(f, '=') - f = string.lower(string.strip(f[:i])) + \ - '=' + string.strip(f[i+1:]) - self.plist.append(string.strip(f)) - - def getplist(self): - return self.plist - - def getparam(self, name): - name = string.lower(name) + '=' - n = len(name) - for p in self.plist: - if p[:n] == name: - return rfc822.unquote(p[n:]) - return None - - def getencoding(self): - if self.encodingheader == None: - return '7bit' - return self.encodingheader - - def gettype(self): - return self.type - - def getmaintype(self): - return self.maintype - - def getsubtype(self): - return self.subtype - - - - -# Utility functions -# ----------------- - - -# Return a random string usable as a multipart boundary. -# The method used is so that it is *very* unlikely that the same -# string of characters will every occur again in the Universe, -# so the caller needn't check the data it is packing for the -# occurrence of the boundary. -# -# The boundary contains dots so you have to quote it in the header. - -_prefix = None - -def choose_boundary(): - global _generation, _prefix, _timestamp - import time - import rand - if _prefix == None: - import socket - import os - hostid = socket.gethostbyname(socket.gethostname()) - uid = `os.getuid()` - pid = `os.getpid()` - seed = `rand.rand()` - _prefix = hostid + '.' + uid + '.' + pid - timestamp = `int(time.time())` - seed = `rand.rand()` - return _prefix + '.' + timestamp + '.' + seed diff --git a/Lib/multifile.py b/Lib/multifile.py deleted file mode 100644 index 7a52ab6133..0000000000 --- a/Lib/multifile.py +++ /dev/null @@ -1,117 +0,0 @@ -# A class that makes each part of a multipart message "feel" like an -# ordinary file, as long as you use fp.readline(). Allows recursive -# use, for nested multipart messages. Probably best used together -# with module mimetools. -# -# Suggested use: -# -# real_fp = open(...) -# fp = MultiFile(real_fp) -# -# "read some lines from fp" -# fp.push(separator) -# while 1: -# "read lines from fp until it returns an empty string" (A) -# if not fp.next(): break -# fp.pop() -# "read remaining lines from fp until it returns an empty string" -# -# The latter sequence may be used recursively at (A). -# It is also allowed to use multiple push()...pop() sequences. -# Note that if a nested multipart message is terminated by a separator -# for an outer message, this is not reported, even though it is really -# illegal input. - -import sys -import string - -err = sys.stderr.write - -Error = 'multifile.Error' - -class MultiFile: - # - def __init__(self, fp): - self.fp = fp - self.stack = [] # Grows down - self.level = 0 - self.last = 0 - self.start = self.fp.tell() - self.posstack = [] # Grows down - # - def tell(self): - if self.level > 0: - return self.lastpos - return self.fp.tell() - self.start - # - def seek(self, pos): - if not 0 <= pos <= self.tell() or \ - self.level > 0 and pos > self.lastpos: - raise Error, 'bad MultiFile.seek() call' - self.fp.seek(pos + self.start) - self.level = 0 - self.last = 0 - # - def readline(self): - if self.level > 0: return '' - line = self.fp.readline() - if not line: - self.level = len(self.stack) - self.last = (self.level > 0) - if self.last: - err('*** Sudden EOF in MultiFile.readline()\n') - return '' - if line[:2] <> '--': return line - n = len(line) - k = n - while k > 0 and line[k-1] in string.whitespace: k = k-1 - mark = line[2:k] - if mark[-2:] == '--': mark1 = mark[:-2] - else: mark1 = None - for i in range(len(self.stack)): - sep = self.stack[i] - if sep == mark: - self.last = 0 - break - elif mark1 <> None and sep == mark1: - self.last = 1 - break - else: - return line - # Get here after break out of loop - self.lastpos = self.tell() - len(line) - self.level = i+1 - if self.level > 1: - err('*** Missing endmarker in MultiFile.readline()\n') - return '' - # - def next(self): - while self.readline(): pass - if self.level > 1 or self.last: - return 0 - self.level = 0 - self.last = 0 - self.start = self.fp.tell() - return 1 - # - def push(self, sep): - if self.level > 0: - raise Error, 'bad MultiFile.push() call' - self.stack.insert(0, sep) - self.posstack.insert(0, self.start) - self.start = self.fp.tell() - # - def pop(self): - if self.stack == []: - raise Error, 'bad MultiFile.pop() call' - if self.level <= 1: - self.last = 0 - else: - abslastpos = self.lastpos + self.start - self.level = max(0, self.level - 1) - del self.stack[0] - self.start = self.posstack[0] - del self.posstack[0] - if self.level > 0: - self.lastpos = abslastpos - self.start - # diff --git a/Lib/mutex.py b/Lib/mutex.py deleted file mode 100644 index b897863574..0000000000 --- a/Lib/mutex.py +++ /dev/null @@ -1,58 +0,0 @@ -# Mutual exclusion -- for use with module sched - -# A mutex has two pieces of state -- a 'locked' bit and a queue. -# When the mutex is not locked, the queue is empty. -# Otherwise, the queue contains 0 or more (function, argument) pairs -# representing functions (or methods) waiting to acquire the lock. -# When the mutex is unlocked while the queue is not empty, -# the first queue entry is removed and its function(argument) pair called, -# implying it now has the lock. -# -# Of course, no multi-threading is implied -- hence the funny interface -# for lock, where a function is called once the lock is aquired. -# -class mutex: - # - # Create a new mutex -- initially unlocked - # - def __init__(self): - self.locked = 0 - self.queue = [] - # - # Test the locked bit of the mutex - # - def test(self): - return self.locked - # - # Atomic test-and-set -- grab the lock if it is not set, - # return true if it succeeded - # - def testandset(self): - if not self.locked: - self.locked = 1 - return 1 - else: - return 0 - # - # Lock a mutex, call the function with supplied argument - # when it is acquired. - # If the mutex is already locked, place function and argument - # in the queue. - # - def lock(self, function, argument): - if self.testandset(): - function(argument) - else: - self.queue.append(function, argument) - # - # Unlock a mutex. If the queue is not empty, call the next - # function with its argument. - # - def unlock(self): - if self.queue: - function, argument = self.queue[0] - del self.queue[0] - function(argument) - else: - self.locked = 0 - # diff --git a/Lib/newdir.py b/Lib/newdir.py deleted file mode 100644 index 26a7df0c1b..0000000000 --- a/Lib/newdir.py +++ /dev/null @@ -1,75 +0,0 @@ -# New dir() function - - -# This should be the new dir(), except that it should still list -# the current local name space by default - -def listattrs(x): - try: - dictkeys = x.__dict__.keys() - except (AttributeError, TypeError): - dictkeys = [] - # - try: - methods = x.__methods__ - except (AttributeError, TypeError): - methods = [] - # - try: - members = x.__members__ - except (AttributeError, TypeError): - members = [] - # - try: - the_class = x.__class__ - except (AttributeError, TypeError): - the_class = None - # - try: - bases = x.__bases__ - except (AttributeError, TypeError): - bases = () - # - total = dictkeys + methods + members - if the_class: - # It's a class instace; add the class's attributes - # that are functions (methods)... - class_attrs = listattrs(the_class) - class_methods = [] - for name in class_attrs: - if is_function(getattr(the_class, name)): - class_methods.append(name) - total = total + class_methods - elif bases: - # It's a derived class; add the base class attributes - for base in bases: - base_attrs = listattrs(base) - total = total + base_attrs - total.sort() - return total - i = 0 - while i+1 < len(total): - if total[i] == total[i+1]: - del total[i+1] - else: - i = i+1 - return total - - -# Helper to recognize functions - -def is_function(x): - return type(x) == type(is_function) - - -# Approximation of builtin dir(); but note that this lists the user's -# variables by default, not the current local name space. - -def dir(*args): - if len(args) > 0: - if len(args) == 1: - args = args[0] - return listattrs(args) - else: - import __main__ - return listattrs(__main__) diff --git a/Lib/nntplib.py b/Lib/nntplib.py deleted file mode 100644 index e7f0627595..0000000000 --- a/Lib/nntplib.py +++ /dev/null @@ -1,367 +0,0 @@ -# An NNTP client class. Based on RFC 977: Network News Transfer -# Protocol, by Brian Kantor and Phil Lapsley. - - -# Example: -# -# >>> from nntplib import NNTP -# >>> s = NNTP('charon') -# >>> resp, count, first, last, name = s.group('nlnet.misc') -# >>> print 'Group', name, 'has', count, 'articles, range', first, 'to', last -# Group nlnet.misc has 525 articles, range 6960 to 7485 -# >>> resp, subs = s.xhdr('subject', first + '-' + last) -# >>> resp = s.quit() -# >>> -# -# Here 'resp' is the server response line. -# Error responses are turned into exceptions. -# -# To post an article from a file: -# >>> f = open(filename, 'r') # file containing article, including header -# >>> resp = s.post(f) -# >>> -# -# For descriptions of all methods, read the comments in the code below. -# Note that all arguments and return values representing article numbers -# are strings, not numbers, since they are rarely used for calculations. - - -# Imports -import regex -import socket -import string - - -# Exception raised when an error or invalid response is received - -error_reply = 'nntplib.error_reply' # unexpected [123]xx reply -error_temp = 'nntplib.error_temp' # 4xx errors -error_perm = 'nntplib.error_perm' # 5xx errors -error_proto = 'nntplib.error_proto' # response does not begin with [1-5] - - -# Standard port used by NNTP servers -NNTP_PORT = 119 - - -# Response numbers that are followed by additional text (e.g. article) -LONGRESP = ['100', '215', '220', '221', '222', '230', '231'] - - -# Line terminators (we always output CRLF, but accept any of CRLF, CR, LF) -CRLF = '\r\n' - - -# The class itself - -class NNTP: - - # Initialize an instance. Arguments: - # - host: hostname to connect to - # - port: port to connect to (default the standard NNTP port) - - def __init__(self, host, *args): - if len(args) > 1: raise TypeError, 'too many args' - if args: port = args[0] - else: port = NNTP_PORT - self.host = host - self.port = port - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.sock.connect(self.host, self.port) - self.file = self.sock.makefile('r') - self.debugging = 0 - self.welcome = self.getresp() - - # Get the welcome message from the server - # (this is read and squirreled away by __init__()). - # If the response code is 200, posting is allowed; - # if it 201, posting is not allowed - - def getwelcome(self): - if self.debugging: print '*welcome*', `self.welcome` - return self.welcome - - # Set the debugging level. Argument level means: - # 0: no debugging output (default) - # 1: print commands and responses but not body text etc. - # 2: also print raw lines read and sent before stripping CR/LF - - def debug(self, level): - self.debugging = level - - # Internal: send one line to the server, appending CRLF - def putline(self, line): - line = line + CRLF - if self.debugging > 1: print '*put*', `line` - self.sock.send(line) - - # Internal: send one command to the server (through putline()) - def putcmd(self, line): - if self.debugging: print '*cmd*', `line` - self.putline(line) - - # Internal: return one line from the server, stripping CRLF. - # Raise EOFError if the connection is closed - def getline(self): - line = self.file.readline() - if self.debugging > 1: - print '*get*', `line` - if not line: raise EOFError - if line[-2:] == CRLF: line = line[:-2] - elif line[-1:] in CRLF: line = line[:-1] - return line - - # Internal: get a response from the server. - # Raise various errors if the response indicates an error - def getresp(self): - resp = self.getline() - if self.debugging: print '*resp*', `resp` - c = resp[:1] - if c == '4': - raise error_temp, resp - if c == '5': - raise error_perm, resp - if c not in '123': - raise error_proto, resp - return resp - - # Internal: get a response plus following text from the server. - # Raise various errors if the response indicates an error - def getlongresp(self): - resp = self.getresp() - if resp[:3] not in LONGRESP: - raise error_reply, resp - list = [] - while 1: - line = self.getline() - if line == '.': - break - list.append(line) - return resp, list - - # Internal: send a command and get the response - def shortcmd(self, line): - self.putcmd(line) - return self.getresp() - - # Internal: send a command and get the response plus following text - def longcmd(self, line): - self.putcmd(line) - return self.getlongresp() - - # Process a NEWGROUPS command. Arguments: - # - date: string 'yymmdd' indicating the date - # - time: string 'hhmmss' indicating the time - # Return: - # - resp: server response if succesful - # - list: list of newsgroup names - - def newgroups(self, date, time): - return self.longcmd('NEWGROUPS ' + date + ' ' + time) - - # Process a NEWNEWS command. Arguments: - # - group: group name or '*' - # - date: string 'yymmdd' indicating the date - # - time: string 'hhmmss' indicating the time - # Return: - # - resp: server response if succesful - # - list: list of article ids - - def newnews(self, group, date, time): - cmd = 'NEWNEWS ' + group + ' ' + date + ' ' + time - return self.longcmd(cmd) - - # Process a LIST command. Return: - # - resp: server response if succesful - # - list: list of (group, first, last, flag) (strings) - - def list(self): - resp, list = self.longcmd('LIST') - for i in range(len(list)): - # Parse lines into "group first last flag" - list[i] = string.split(list[i]) - return resp, list - - # Process a GROUP command. Argument: - # - group: the group name - # Returns: - # - resp: server response if succesful - # - count: number of articles (string) - # - first: first article number (string) - # - last: last article number (string) - # - name: the group name - - def group(self, name): - resp = self.shortcmd('GROUP ' + name) - if resp[:3] <> '211': - raise error_reply, resp - words = string.split(resp) - count = first = last = 0 - n = len(words) - if n > 1: - count = words[1] - if n > 2: - first = words[2] - if n > 3: - last = words[3] - if n > 4: - name = string.lower(words[4]) - return resp, count, first, last, name - - # Process a HELP command. Returns: - # - resp: server response if succesful - # - list: list of strings - - def help(self): - return self.longcmd('HELP') - - # Internal: parse the response of a STAT, NEXT or LAST command - def statparse(self, resp): - if resp[:2] <> '22': - raise error_reply, resp - words = string.split(resp) - nr = 0 - id = '' - n = len(words) - if n > 1: - nr = words[1] - if n > 2: - id = string.lower(words[2]) - return resp, nr, id - - # Internal: process a STAT, NEXT or LAST command - def statcmd(self, line): - resp = self.shortcmd(line) - return self.statparse(resp) - - # Process a STAT command. Argument: - # - id: article number or message id - # Returns: - # - resp: server response if succesful - # - nr: the article number - # - id: the article id - - def stat(self, id): - return self.statcmd('STAT ' + id) - - # Process a NEXT command. No arguments. Return as for STAT - - def next(self): - return self.statcmd('NEXT') - - # Process a LAST command. No arguments. Return as for STAT - - def last(self): - return self.statcmd('LAST') - - # Internal: process a HEAD, BODY or ARTICLE command - def artcmd(self, line): - resp, list = self.longcmd(line) - resp, nr, id = self.statparse(resp) - return resp, nr, id, list - - # Process a HEAD command. Argument: - # - id: article number or message id - # Returns: - # - resp: server response if succesful - # - list: the lines of the article's header - - def head(self, id): - return self.artcmd('HEAD ' + id) - - # Process a BODY command. Argument: - # - id: article number or message id - # Returns: - # - resp: server response if succesful - # - list: the lines of the article's body - - def body(self, id): - return self.artcmd('BODY ' + id) - - # Process an ARTICLE command. Argument: - # - id: article number or message id - # Returns: - # - resp: server response if succesful - # - list: the lines of the article - - def article(self, id): - return self.artcmd('ARTICLE ' + id) - - # Process a SLAVE command. Returns: - # - resp: server response if succesful - - def slave(self): - return self.shortcmd('SLAVE') - - # Process an XHDR command (optional server extension). Arguments: - # - hdr: the header type (e.g. 'subject') - # - str: an article nr, a message id, or a range nr1-nr2 - # Returns: - # - resp: server response if succesful - # - list: list of (nr, value) strings - - def xhdr(self, hdr, str): - resp, lines = self.longcmd('XHDR ' + hdr + ' ' + str) - for i in range(len(lines)): - line = lines[i] - n = regex.match('^[0-9]+', line) - nr = line[:n] - if n < len(line) and line[n] == ' ': n = n+1 - lines[i] = (nr, line[n:]) - return resp, lines - - # Process a POST command. Arguments: - # - f: file containing the article - # Returns: - # - resp: server response if succesful - - def post(self, f): - resp = self.shortcmd('POST') - # Raises error_??? if posting is not allowed - if resp[0] <> '3': - raise error_reply, resp - while 1: - line = f.readline() - if not line: - break - if line[-1] == '\n': - line = line[:-1] - if line == '.': - line = '..' - self.putline(line) - self.putline('.') - return self.getresp() - - # Process an IHAVE command. Arguments: - # - id: message-id of the article - # - f: file containing the article - # Returns: - # - resp: server response if succesful - # Note that if the server refuses the article an exception is raised - - def ihave(self, id, f): - resp = self.shortcmd('IHAVE ' + id) - # Raises error_??? if the server already has it - if resp[0] <> '3': - raise error_reply, resp - while 1: - line = f.readline() - if not line: - break - if line[-1] == '\n': - line = line[:-1] - if line == '.': - line = '..' - self.putline(line) - self.putline('.') - return self.getresp() - - # Process a QUIT command and close the socket. Returns: - # - resp: server response if succesful - - def quit(self): - resp = self.shortcmd('QUIT') - self.file.close() - self.sock.close() - del self.file, self.sock - return resp diff --git a/Lib/os.py b/Lib/os.py deleted file mode 100644 index 7322fa56f9..0000000000 --- a/Lib/os.py +++ /dev/null @@ -1,70 +0,0 @@ -# os.py -- either mac or posix depending on what system we're on. - -# This exports: -# - all functions from either posix or mac, e.g., os.unlink, os.stat, etc. -# - os.path is either module posixpath or macpath -# - os.name is either 'posix' or 'mac' -# - os.curdir is a string representing the current directory ('.' or ':') -# - os.pardir is a string representing the parent directory ('..' or '::') -# - os.sep is the (or a most common) pathname separator ('/' or ':') - -# Programs that import and use 'os' stand a better chance of being -# portable between different platforms. Of course, they must then -# only use functions that are defined by all platforms (e.g., unlink -# and opendir), and leave all pathname manipulation to os.path -# (e.g., split and join). - -# XXX This will need to distinguish between real posix and MS-DOS emulation - -try: - from posix import * - try: - from posix import _exit - except ImportError: - pass - name = 'posix' - curdir = '.' - pardir = '..' - sep = '/' - import posixpath - path = posixpath - del posixpath -except ImportError: - from mac import * - name = 'mac' - curdir = ':' - pardir = '::' - sep = ':' - import macpath - path = macpath - del macpath - -def execl(file, *args): - execv(file, args) - -def execle(file, *args): - env = args[-1] - execve(file, args[:-1], env) - -def execlp(file, *args): - execvp(file, args) - -def execvp(file, args): - if '/' in file: - execv(file, args) - return - ENOENT = 2 - if environ.has_key('PATH'): - import string - PATH = string.splitfields(environ['PATH'], ':') - else: - PATH = ['', '/bin', '/usr/bin'] - exc, arg = (ENOENT, 'No such file or directory') - for dir in PATH: - fullname = path.join(dir, file) - try: - execv(fullname, args) - except error, (errno, msg): - if errno != ENOENT: - exc, arg = error, (errno, msg) - raise exc, arg diff --git a/Lib/ospath.py b/Lib/ospath.py deleted file mode 100644 index 866d02e77a..0000000000 --- a/Lib/ospath.py +++ /dev/null @@ -1,15 +0,0 @@ -# ospath.py is to {posix,mac}path.py what os.py is to modules {posix,mac} - -try: - import posix - name = 'posix' - del posix -except ImportError: - import mac - name = 'mac' - del mac - -if name == 'posix': - from posixpath import * -elif name == 'mac': - from macpath import * diff --git a/Lib/packmail.py b/Lib/packmail.py deleted file mode 100644 index d612c88a8e..0000000000 --- a/Lib/packmail.py +++ /dev/null @@ -1,88 +0,0 @@ -# Module 'packmail' -- create a self-unpacking shell archive. - -# This module works on UNIX and on the Mac; the archives can unpack -# themselves only on UNIX. - -import os -from stat import ST_MTIME -import string - -# Print help -def help(): - print 'All fns have a file open for writing as first parameter' - print 'pack(f, fullname, name): pack fullname as name' - print 'packsome(f, directory, namelist): selected files from directory' - print 'packall(f, directory): pack all files from directory' - print 'packnotolder(f, directory, name): pack all files from directory' - print ' that are not older than a file there' - print 'packtree(f, directory): pack entire directory tree' - -# Pack one file -def pack(outfp, file, name): - fp = open(file, 'r') - outfp.write('echo ' + name + '\n') - outfp.write('sed "s/^X//" >' + name + ' <<"!"\n') - while 1: - line = fp.readline() - if not line: break - if line[-1:] <> '\n': - line = line + '\n' - outfp.write('X' + line) - outfp.write('!\n') - fp.close() - -# Pack some files from a directory -def packsome(outfp, dirname, names): - for name in names: - print name - file = os.path.join(dirname, name) - pack(outfp, file, name) - -# Pack all files from a directory -def packall(outfp, dirname): - names = os.listdir(dirname) - names.sort() - packsome(outfp, dirname, names) - -# Pack all files from a directory that are not older than a give one -def packnotolder(outfp, dirname, oldest): - names = os.listdir(dirname) - oldest = os.path.join(dirname, oldest) - st = os.stat(oldest) - mtime = st[ST_MTIME] - todo = [] - for name in names: - print name, '...', - st = os.stat(os.path.join(dirname, name)) - if st[ST_MTIME] >= mtime: - print 'Yes.' - todo.append(name) - else: - print 'No.' - todo.sort() - packsome(outfp, dirname, todo) - -# Pack a whole tree (no exceptions) -def packtree(outfp, dirname): - print 'packtree', dirname - outfp.write('mkdir ' + unixfix(dirname) + '\n') - names = os.listdir(dirname) - subdirs = [] - for name in names: - fullname = os.path.join(dirname, name) - if os.path.isdir(fullname): - subdirs.append(fullname) - else: - print 'pack', fullname - pack(outfp, fullname, unixfix(fullname)) - for subdirname in subdirs: - packtree(outfp, subdirname) - -def unixfix(name): - comps = string.splitfields(name, os.sep) - res = '' - for comp in comps: - if comp: - if res: res = res + '/' - res = res + comp - return res diff --git a/Lib/pdb.doc b/Lib/pdb.doc deleted file mode 100644 index c92b57229d..0000000000 --- a/Lib/pdb.doc +++ /dev/null @@ -1,165 +0,0 @@ -The Python Debugger -=================== - -To use the debugger in its simplest form: - - >>> import pdb - >>> pdb.run('') - -The debugger's prompt is '(Pdb) '. This will stop in the first -function call in . - -Alternatively, if a statement terminated with an unhandled exception, -you can use pdb's post-mortem facility to inspect the contents of the -traceback: - - >>> - - >>> import pdb - >>> pdb.pm() - -The commands recognized by the debugger are listed in the next -section. Most can be abbreviated as indicated; e.g., h(elp) means -that 'help' can be typed as 'h' or 'help' (but not as 'he' or 'hel', -nor as 'H' or 'Help' or 'HELP'). Optional arguments are enclosed in -square brackets. - -A blank line repeats the previous command literally. (Except for -'list', where it lists the next 11 lines.) - -Commands that the debugger doesn't recognize are assumed to be Python -statements and are executed in the context of the program being -debugged. Python statements can also be prefixed with an exclamation -point ('!'). This is a powerful way to inspect the program being -debugged; it is even possible to change variables. When an exception -occurs in such a statement, the exception name is printed but the -debugger's state is not changed. - -The debugger is not directly programmable; but it is implemented as a -class from which you can derive your own debugger class, so you can -make as fancy as you like. - - -Debugger commands -================= - -h(elp) - Without argument, print the list of available commands. - With a command name as argument, print help about that command - (this is currently not implemented). - -w(here) - Print a stack trace, with the most recent frame at the bottom. - An arrow indicates the "current frame", which determines the - context of most commands. - -d(own) - Move the current frame one level down in the stack trace - (to an older frame). - -u(p) - Move the current frame one level up in the stack trace - (to a newer frame). - -b(reak) [lineno] - With a line number argument, set a break there in the current file. - Without argument, list all breaks. - -cl(ear) [lineno] - With a line number argument, clear that break in the current file. - Without argument, clear all breaks (but first ask confirmation). - -s(tep) - Execute the current line, stop at the first possible occasion - (either in a function that is called or in the current function). - -n(ext) - Continue execution until the next line in the current function - is reached or it returns. - -r(eturn) - Continue execution until the current function returns. - -c(ont(inue)) - Continue execution, only stop when a breakpoint is encountered. - -l(ist) [first [,last]] - List source code for the current file. - Without arguments, list 11 lines around the current line - or continue the previous listing. - With one argument, list 11 lines starting at that line. - With two arguments, list the given range; - if the second argument is less than the first, it is a count. - -a(rgs) - Print the argument list of the current function. - -p expression - Print the value of the expression. - -(!) statement - Execute the (one-line) statement in the context of - the current stack frame. - The exclamation point can be omitted unless the first word - of the statement resembles a debugger command. - To assign to a global variable you must always prefix the - command with a 'global' command, e.g.: - (Pdb) global list_options; list_options = ['-l'] - (Pdb) - -q(uit) - Quit from the debugger. - The program being executed is aborted. - - -How it works -============ - -Some changes were made to the interpreter: -- sys.settrace(func) sets the global trace function -- there can also a local trace function (see later) - -Trace functions have three arguments: (frame, event, arg) - - frame is the current stack frame - - event is a string: 'call', 'line', 'return' or 'exception' - - arg is dependent on the event type -A trace function should return a new trace function or None. -Class methods are accepted (and most useful!) as trace methods. - -The events have the following meaning: - - 'call': A function is called (or some other code block entered). - The global trace function is called; - arg is the argument list to the function; - the return value specifies the local trace function. - - 'line': The interpreter is about to execute a new line of code - (sometimes multiple line events on one line exist). - The local trace function is called; arg in None; - the return value specifies the new local trace function. - - 'return': A function (or other code block) is about to return. - The local trace function is called; - arg is the value that will be returned. - The trace function's return value is ignored. - - 'exception': An exception has occurred. - The local trace function is called; - arg is a triple (exception, value, traceback); - the return value specifies the new local trace function - -Note that as an exception is propagated down the chain of callers, an -'exception' event is generated at each level. - -Stack frame objects have the following read-only attributes: - f_code: the code object being executed - f_lineno: the current line number (-1 for 'call' events) - f_back: the stack frame of the caller, or None - f_locals: dictionary containing local name bindings - f_globals: dictionary containing global name bindings - -Code objects have the following read-only attributes: - co_code: the code string - co_names: the list of names used by the code - co_consts: the list of (literal) constants used by the code - co_filename: the filename from which the code was compiled diff --git a/Lib/pdb.py b/Lib/pdb.py deleted file mode 100755 index 64451d5f4e..0000000000 --- a/Lib/pdb.py +++ /dev/null @@ -1,324 +0,0 @@ -# pdb.py -- finally, a Python debugger! - -# (See pdb.doc for documentation.) - -import string -import sys -import linecache -import cmd -import bdb -import repr - - -class Pdb(bdb.Bdb, cmd.Cmd): - - def __init__(self): - bdb.Bdb.__init__(self) - cmd.Cmd.__init__(self) - self.prompt = '(Pdb) ' - - def reset(self): - bdb.Bdb.reset(self) - self.forget() - - def forget(self): - self.lineno = None - self.stack = [] - self.curindex = 0 - self.curframe = None - - def setup(self, f, t): - self.forget() - self.stack, self.curindex = self.get_stack(f, t) - self.curframe = self.stack[self.curindex][0] - - # Override Bdb methods (except user_call, for now) - - def user_line(self, frame): - # This function is called when we stop or break at this line - self.interaction(frame, None) - - def user_return(self, frame, return_value): - # This function is called when a return trap is set here - frame.f_locals['__return__'] = return_value - print '--Return--' - self.interaction(frame, None) - - def user_exception(self, frame, (exc_type, exc_value, exc_traceback)): - # This function is called if an exception occurs, - # but only if we are to stop at or just below this level - frame.f_locals['__exception__'] = exc_type, exc_value - print exc_type + ':', repr.repr(exc_value) - self.interaction(frame, exc_traceback) - - # General interaction function - - def interaction(self, frame, traceback): - self.setup(frame, traceback) - self.print_stack_entry(self.stack[self.curindex]) - self.cmdloop() - self.forget() - - def default(self, line): - if line[:1] == '!': line = line[1:] - locals = self.curframe.f_locals - globals = self.curframe.f_globals - globals['__privileged__'] = 1 - try: - exec(line + '\n', globals, locals) - except: - print '***', sys.exc_type + ':', sys.exc_value - - # Command definitions, called by cmdloop() - # The argument is the remaining string on the command line - # Return true to exit from the command loop - - do_h = cmd.Cmd.do_help - - def do_break(self, arg): - if not arg: - print self.get_all_breaks() # XXX - return - try: - lineno = int(eval(arg)) - except: - print '*** Error in argument:', `arg` - return - filename = self.curframe.f_code.co_filename - err = self.set_break(filename, lineno) - if err: print '***', err - do_b = do_break - - def do_clear(self, arg): - if not arg: - try: - reply = raw_input('Clear all breaks? ') - except EOFError: - reply = 'no' - reply = string.lower(string.strip(reply)) - if reply in ('y', 'yes'): - self.clear_all_breaks() - return - try: - lineno = int(eval(arg)) - except: - print '*** Error in argument:', `arg` - return - filename = self.curframe.f_code.co_filename - err = self.clear_break(filename, lineno) - if err: print '***', err - do_cl = do_clear # 'c' is already an abbreviation for 'continue' - - def do_where(self, arg): - self.print_stack_trace() - do_w = do_where - - def do_up(self, arg): - if self.curindex == 0: - print '*** Oldest frame' - else: - self.curindex = self.curindex - 1 - self.curframe = self.stack[self.curindex][0] - self.print_stack_entry(self.stack[self.curindex]) - self.lineno = None - do_u = do_up - - def do_down(self, arg): - if self.curindex + 1 == len(self.stack): - print '*** Newest frame' - else: - self.curindex = self.curindex + 1 - self.curframe = self.stack[self.curindex][0] - self.print_stack_entry(self.stack[self.curindex]) - self.lineno = None - do_d = do_down - - def do_step(self, arg): - self.set_step() - return 1 - do_s = do_step - - def do_next(self, arg): - self.set_next(self.curframe) - return 1 - do_n = do_next - - def do_return(self, arg): - self.set_return(self.curframe) - return 1 - do_r = do_return - - def do_continue(self, arg): - self.set_continue() - return 1 - do_c = do_cont = do_continue - - def do_quit(self, arg): - self.set_quit() - return 1 - do_q = do_quit - - def do_args(self, arg): - if self.curframe.f_locals.has_key('__return__'): - print `self.curframe.f_locals['__return__']` - else: - print '*** Not arguments?!' - do_a = do_args - - def do_retval(self, arg): - if self.curframe.f_locals.has_key('__return__'): - print self.curframe.f_locals['__return__'] - else: - print '*** Not yet returned!' - do_rv = do_retval - - def do_p(self, arg): - self.curframe.f_globals['__privileged__'] = 1 - try: - value = eval(arg, self.curframe.f_globals, \ - self.curframe.f_locals) - except: - print '***', sys.exc_type + ':', `sys.exc_value` - return - - print `value` - - def do_list(self, arg): - self.lastcmd = 'list' - last = None - if arg: - try: - x = eval(arg, {}, {}) - if type(x) == type(()): - first, last = x - first = int(first) - last = int(last) - if last < first: - # Assume it's a count - last = first + last - else: - first = max(1, int(x) - 5) - except: - print '*** Error in argument:', `arg` - return - elif self.lineno is None: - first = max(1, self.curframe.f_lineno - 5) - else: - first = self.lineno + 1 - if last == None: - last = first + 10 - filename = self.curframe.f_code.co_filename - breaklist = self.get_file_breaks(filename) - try: - for lineno in range(first, last+1): - line = linecache.getline(filename, lineno) - if not line: - print '[EOF]' - break - else: - s = string.rjust(`lineno`, 3) - if len(s) < 4: s = s + ' ' - if lineno in breaklist: s = s + 'B' - else: s = s + ' ' - if lineno == self.curframe.f_lineno: - s = s + '->' - print s + '\t' + line, - self.lineno = lineno - except KeyboardInterrupt: - pass - do_l = do_list - - def do_whatis(self, arg): - import codehack - try: - value = eval(arg, self.curframe.f_globals, \ - self.curframe.f_locals) - except: - print '***', sys.exc_type + ':', `sys.exc_value` - return - code = None - # Is it a function? - try: code = value.func_code - except: pass - if code: - print 'Function', codehack.getcodename(code) - return - # Is it an instance method? - try: code = value.im_func.func_code - except: pass - if code: - print 'Method', codehack.getcodename(code) - return - # None of the above... - print type(value) - - # Print a traceback starting at the top stack frame. - # The most recently entered frame is printed last; - # this is different from dbx and gdb, but consistent with - # the Python interpreter's stack trace. - # It is also consistent with the up/down commands (which are - # compatible with dbx and gdb: up moves towards 'main()' - # and down moves towards the most recent stack frame). - - def print_stack_trace(self): - try: - for frame_lineno in self.stack: - self.print_stack_entry(frame_lineno) - except KeyboardInterrupt: - pass - - def print_stack_entry(self, frame_lineno): - frame, lineno = frame_lineno - if frame is self.curframe: - print '>', - else: - print ' ', - print self.format_stack_entry(frame_lineno) - - -# Simplified interface - -def run(statement): - Pdb().run(statement) - -def runctx(statement, globals, locals): - Pdb().runctx(statement, globals, locals) - -def runcall(*args): - apply(Pdb().runcall, args) - - -# Post-Mortem interface - -def post_mortem(t): - p = Pdb() - p.reset() - while t.tb_next <> None: t = t.tb_next - p.interaction(t.tb_frame, t) - -def pm(): - import sys - post_mortem(sys.last_traceback) - - -# Main program for testing - -TESTCMD = 'import x; x.main()' - -def test(): - import linecache - linecache.checkcache() - run(TESTCMD) - -# print help -def help(): - import os - for dirname in sys.path: - fullname = os.path.join(dirname, 'pdb.doc') - if os.path.exists(fullname): - sts = os.system('${PAGER-more} '+fullname) - if sts: print '*** Pager exit status:', sts - break - else: - print 'Sorry, can\'t find the help file "pdb.doc"', - print 'along the Python search path' diff --git a/Lib/persist.py b/Lib/persist.py deleted file mode 100755 index 8f0f164bc6..0000000000 --- a/Lib/persist.py +++ /dev/null @@ -1,297 +0,0 @@ -# persist.py -# -# Implement limited persistence. -# -# Simple interface: -# persist.save() save __main__ module on file (overwrite) -# persist.load() load __main__ module from file (merge) -# -# These use the filename persist.defaultfile, initialized to 'wsrestore.py'. -# -# A raw interface also exists: -# persist.writedict(dict, fp) save dictionary to open file -# persist.readdict(dict, fp) read (merge) dictionary from open file -# -# Internally, the function dump() and a whole bunch of support of functions -# traverse a graph of objects and print them in a restorable form -# (which happens to be a Python module). -# -# XXX Limitations: -# - Volatile objects are dumped as strings: -# - open files, windows etc. -# - Other 'obscure' objects are dumped as strings: -# - classes, instances and methods -# - compiled regular expressions -# - anything else reasonably obscure (e.g., capabilities) -# - type objects for obscure objects -# - It's slow when there are many of lists or dictionaries -# (This could be fixed if there were a quick way to compute a hash -# function of any object, even if recursive) - -defaultfile = 'wsrestore.py' - -def save(): - import __main__ - import os - # XXX On SYSV, if len(defaultfile) >= 14, this is wrong! - backup = defaultfile + '~' - try: - os.unlink(backup) - except os.error: - pass - try: - os.rename(defaultfile, backup) - except os.error: - pass - fp = open(defaultfile, 'w') - writedict(__main__.__dict__, fp) - fp.close() - -def load(): - import __main__ - fp = open(defaultfile, 'r') - readdict(__main__.__dict__, fp) - -def writedict(dict, fp): - import sys - savestdout = sys.stdout - try: - sys.stdout = fp - dump(dict) # Writes to sys.stdout - finally: - sys.stdout = savestdout - -def readdict(dict, fp): - contents = fp.read() - globals = {} - exec(contents, globals) - top = globals['top'] - for key in top.keys(): - if dict.has_key(key): - print 'warning:', key, 'not overwritten' - else: - dict[key] = top[key] - - -# Function dump(x) prints (on sys.stdout!) a sequence of Python statements -# that, when executed in an empty environment, will reconstruct the -# contents of an arbitrary dictionary. - -import sys - -# Name used for objects dict on output. -# -FUNNYNAME = FN = 'A' - -# Top-level function. Call with the object you want to dump. -# -def dump(x): - types = {} - stack = [] # Used by test for recursive objects - print FN, '= {}' - topuid = dumpobject(x, types, stack) - print 'top =', FN, '[', `topuid`, ']' - -# Generic function to dump any object. -# -dumpswitch = {} -# -def dumpobject(x, types, stack): - typerepr = `type(x)` - if not types.has_key(typerepr): - types[typerepr] = {} - typedict = types[typerepr] - if dumpswitch.has_key(typerepr): - return dumpswitch[typerepr](x, typedict, types, stack) - else: - return dumpbadvalue(x, typedict, types, stack) - -# Generic function to dump unknown values. -# This assumes that the Python interpreter prints such values as -# . -# The object will be read back as a string: ''. -# In some cases it may be possible to fix the dump manually; -# to ease the editing, these cases are labeled with an XXX comment. -# -def dumpbadvalue(x, typedict, types, stack): - xrepr = `x` - if typedict.has_key(xrepr): - return typedict[xrepr] - uid = genuid() - typedict[xrepr] = uid - print FN, '[', `uid`, '] =', `xrepr`, '# XXX' - return uid - -# Generic function to dump pure, simple values, except strings -# -def dumpvalue(x, typedict, types, stack): - xrepr = `x` - if typedict.has_key(xrepr): - return typedict[xrepr] - uid = genuid() - typedict[xrepr] = uid - print FN, '[', `uid`, '] =', `x` - return uid - -# Functions to dump string objects -# -def dumpstring(x, typedict, types, stack): - # XXX This can break if strings have embedded '\0' bytes - # XXX because of a bug in the dictionary module - if typedict.has_key(x): - return typedict[x] - uid = genuid() - typedict[x] = uid - print FN, '[', `uid`, '] =', `x` - return uid - -# Function to dump type objects -# -typeswitch = {} -class some_class: - def method(self): pass -some_instance = some_class() -# -def dumptype(x, typedict, types, stack): - xrepr = `x` - if typedict.has_key(xrepr): - return typedict[xrepr] - uid = genuid() - typedict[xrepr] = uid - if typeswitch.has_key(xrepr): - print FN, '[', `uid`, '] =', typeswitch[xrepr] - elif x == type(sys): - print 'import sys' - print FN, '[', `uid`, '] = type(sys)' - elif x == type(sys.stderr): - print 'import sys' - print FN, '[', `uid`, '] = type(sys.stderr)' - elif x == type(dumptype): - print 'def some_function(): pass' - print FN, '[', `uid`, '] = type(some_function)' - elif x == type(some_class): - print 'class some_class: pass' - print FN, '[', `uid`, '] = type(some_class)' - elif x == type(some_instance): - print 'class another_class: pass' - print 'some_instance = another_class()' - print FN, '[', `uid`, '] = type(some_instance)' - elif x == type(some_instance.method): - print 'class yet_another_class:' - print ' def method(): pass' - print 'another_instance = yet_another_class()' - print FN, '[', `uid`, '] = type(another_instance.method)' - else: - # Unknown type - print FN, '[', `uid`, '] =', `xrepr`, '# XXX' - return uid - -# Initialize the typeswitch -# -for x in None, 0, 0.0, '', (), [], {}: - typeswitch[`type(x)`] = 'type(' + `x` + ')' -for s in 'type(0)', 'abs', '[].append': - typeswitch[`type(eval(s))`] = 'type(' + s + ')' - -# Dump a tuple object -# -def dumptuple(x, typedict, types, stack): - item_uids = [] - xrepr = '' - for item in x: - item_uid = dumpobject(item, types, stack) - item_uids.append(item_uid) - xrepr = xrepr + ' ' + item_uid - del stack[-1:] - if typedict.has_key(xrepr): - return typedict[xrepr] - uid = genuid() - typedict[xrepr] = uid - print FN, '[', `uid`, '] = (', - for item_uid in item_uids: - print FN, '[', `item_uid`, '],', - print ')' - return uid - -# Dump a list object -# -def dumplist(x, typedict, types, stack): - # Check for recursion - for x1, uid1 in stack: - if x is x1: return uid1 - # Check for occurrence elsewhere in the typedict - for uid1 in typedict.keys(): - if x is typedict[uid1]: return uid1 - # This uses typedict differently! - uid = genuid() - typedict[uid] = x - print FN, '[', `uid`, '] = []' - stack.append(x, uid) - item_uids = [] - for item in x: - item_uid = dumpobject(item, types, stack) - item_uids.append(item_uid) - del stack[-1:] - for item_uid in item_uids: - print FN, '[', `uid`, '].append(', FN, '[', `item_uid`, '])' - return uid - -# Dump a dictionary object -# -def dumpdict(x, typedict, types, stack): - # Check for recursion - for x1, uid1 in stack: - if x is x1: return uid1 - # Check for occurrence elsewhere in the typedict - for uid1 in typedict.keys(): - if x is typedict[uid1]: return uid1 - # This uses typedict differently! - uid = genuid() - typedict[uid] = x - print FN, '[', `uid`, '] = {}' - stack.append(x, uid) - item_uids = [] - for key in x.keys(): - val_uid = dumpobject(x[key], types, stack) - item_uids.append(key, val_uid) - del stack[-1:] - for key, val_uid in item_uids: - print FN, '[', `uid`, '][', `key`, '] =', - print FN, '[', `val_uid`, ']' - return uid - -# Dump a module object -# -def dumpmodule(x, typedict, types, stack): - xrepr = `x` - if typedict.has_key(xrepr): - return typedict[xrepr] - from string import split - # `x` has the form - name = xrepr[9:-2] - uid = genuid() - typedict[xrepr] = uid - print 'import', name - print FN, '[', `uid`, '] =', name - return uid - - -# Initialize dumpswitch, a table of functions to dump various objects, -# indexed by `type(x)`. -# -for x in None, 0, 0.0: - dumpswitch[`type(x)`] = dumpvalue -for x, f in ('', dumpstring), (type(0), dumptype), ((), dumptuple), \ - ([], dumplist), ({}, dumpdict), (sys, dumpmodule): - dumpswitch[`type(x)`] = f - - -# Generate the next unique id; a string consisting of digits. -# The seed is stored as seed[0]. -# -seed = [0] -# -def genuid(): - x = seed[0] - seed[0] = seed[0] + 1 - return `x` diff --git a/Lib/pipes.py b/Lib/pipes.py deleted file mode 100644 index 0ae0b8c9ed..0000000000 --- a/Lib/pipes.py +++ /dev/null @@ -1,301 +0,0 @@ -# Conversion pipeline templates -# ============================= - - -# The problem: -# ------------ -# -# Suppose you have some data that you want to convert to another format -# (e.g. from GIF image format to PPM image format). Maybe the -# conversion involves several steps (e.g. piping it through compress or -# uuencode). Some of the conversion steps may require that their input -# is a disk file, others may be able to read standard input; similar for -# their output. The input to the entire conversion may also be read -# from a disk file or from an open file, and similar for its output. -# -# The module lets you construct a pipeline template by sticking one or -# more conversion steps together. It will take care of creating and -# removing temporary files if they are necessary to hold intermediate -# data. You can then use the template to do conversions from many -# different sources to many different destinations. The temporary -# file names used are different each time the template is used. -# -# The templates are objects so you can create templates for many -# different conversion steps and store them in a dictionary, for -# instance. - - -# Directions: -# ----------- -# -# To create a template: -# t = Template() -# -# To add a conversion step to a template: -# t.append(command, kind) -# where kind is a string of two characters: the first is '-' if the -# command reads its standard input or 'f' if it requires a file; the -# second likewise for the output. The command must be valid /bin/sh -# syntax. If input or output files are required, they are passed as -# $IN and $OUT; otherwise, it must be possible to use the command in -# a pipeline. -# -# To add a conversion step at the beginning: -# t.prepend(command, kind) -# -# To convert a file to another file using a template: -# sts = t.copy(infile, outfile) -# If infile or outfile are the empty string, standard input is read or -# standard output is written, respectively. The return value is the -# exit status of the conversion pipeline. -# -# To open a file for reading or writing through a conversion pipeline: -# fp = t.open(file, mode) -# where mode is 'r' to read the file, or 'w' to write it -- just like -# for the built-in function open() or for os.popen(). -# -# To create a new template object initialized to a given one: -# t2 = t.clone() -# -# For an example, see the function test() at the end of the file. - - -import sys -import regex - -import os -import tempfile -import string - - -# Conversion step kinds - -FILEIN_FILEOUT = 'ff' # Must read & write real files -STDIN_FILEOUT = '-f' # Must write a real file -FILEIN_STDOUT = 'f-' # Must read a real file -STDIN_STDOUT = '--' # Normal pipeline element -SOURCE = '.-' # Must be first, writes stdout -SINK = '-.' # Must be last, reads stdin - -stepkinds = [FILEIN_FILEOUT, STDIN_FILEOUT, FILEIN_STDOUT, STDIN_STDOUT, \ - SOURCE, SINK] - - -# A pipeline template is a Template object: - -class Template: - - # Template() returns a fresh pipeline template - def __init__(self): - self.debugging = 0 - self.reset() - - # t.__repr__() implements `t` - def __repr__(self): - return '