From f55aa80b372268902d27ad8ae3a45e465c6b9b19 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Fri, 26 Nov 2010 08:59:40 +0000 Subject: Merged revisions 85820,85823,85825,85840,85843-85845,85849-85851,85855,85867,85875,85907-85908,85911,85914 via svnmerge from svn+ssh://svn.python.org/python/branches/py3k ........ r85820 | georg.brandl | 2010-10-24 16:20:22 +0200 (So, 24 Okt 2010) | 1 line Remove usage of exception indexing. ........ r85823 | georg.brandl | 2010-10-24 16:32:45 +0200 (So, 24 Okt 2010) | 1 line Fix style. ........ r85825 | georg.brandl | 2010-10-24 17:16:02 +0200 (So, 24 Okt 2010) | 1 line Add documentation about the default warnings filters. ........ r85840 | georg.brandl | 2010-10-25 19:50:20 +0200 (Mo, 25 Okt 2010) | 1 line #3018: tkinter demo fixes for py3k. ........ r85843 | georg.brandl | 2010-10-26 08:59:23 +0200 (Di, 26 Okt 2010) | 1 line Markup fix. ........ r85844 | georg.brandl | 2010-10-26 12:39:14 +0200 (Di, 26 Okt 2010) | 1 line Work a bit more on tkinter demos. ........ r85845 | georg.brandl | 2010-10-26 12:42:16 +0200 (Di, 26 Okt 2010) | 1 line faqwiz is removed. ........ r85849 | georg.brandl | 2010-10-26 21:31:06 +0200 (Di, 26 Okt 2010) | 1 line #10200: typo. ........ r85850 | georg.brandl | 2010-10-26 21:58:11 +0200 (Di, 26 Okt 2010) | 1 line #10200: typo. ........ r85851 | georg.brandl | 2010-10-26 22:12:37 +0200 (Di, 26 Okt 2010) | 1 line Fix import. ........ r85855 | georg.brandl | 2010-10-27 09:21:54 +0200 (Mi, 27 Okt 2010) | 1 line Encoding fix. ........ r85867 | georg.brandl | 2010-10-27 22:01:51 +0200 (Mi, 27 Okt 2010) | 1 line Add David. ........ r85875 | georg.brandl | 2010-10-28 10:38:30 +0200 (Do, 28 Okt 2010) | 1 line Fix bytes/str issues in get-remote-certificate.py. ........ r85907 | georg.brandl | 2010-10-29 06:54:13 +0200 (Fr, 29 Okt 2010) | 1 line #10222: fix for overzealous AIX compiler. ........ r85908 | georg.brandl | 2010-10-29 07:22:17 +0200 (Fr, 29 Okt 2010) | 1 line send_bytes obviously needs bytes... ........ r85911 | georg.brandl | 2010-10-29 07:36:28 +0200 (Fr, 29 Okt 2010) | 1 line Fix markup error and update false positive entries from "make suspicious". ........ r85914 | georg.brandl | 2010-10-29 08:17:38 +0200 (Fr, 29 Okt 2010) | 1 line (?:...) is a non-capturing, but still grouping construct. ........ --- Demo/cgi/README | 3 +- Demo/md5test/md5driver.py | 2 +- Demo/tkinter/guido/AttrDialog.py | 451 ----------------------- Demo/tkinter/guido/ManPage.py | 220 ------------ Demo/tkinter/guido/MimeViewer.py | 143 -------- Demo/tkinter/guido/ShellWindow.py | 147 -------- Demo/tkinter/guido/attr_dialog.py | 460 ++++++++++++++++++++++++ Demo/tkinter/guido/canvasevents.py | 54 ++- Demo/tkinter/guido/dialog.py | 3 +- Demo/tkinter/guido/electrons.py | 4 +- Demo/tkinter/guido/hanoi.py | 4 +- Demo/tkinter/guido/listtree.py | 3 - Demo/tkinter/guido/manpage.py | 215 +++++++++++ Demo/tkinter/guido/mbox.py | 49 +-- Demo/tkinter/guido/mimeviewer.py | 159 ++++++++ Demo/tkinter/guido/rmt.py | 2 +- Demo/tkinter/guido/shell_window.py | 146 ++++++++ Demo/tkinter/guido/solitaire.py | 55 ++- Demo/tkinter/guido/sortvisu.py | 119 +++--- Demo/tkinter/guido/ss1.py | 8 +- Demo/tkinter/guido/svkill.py | 8 +- Demo/tkinter/guido/tkman.py | 26 +- Demo/tkinter/guido/wish.py | 14 +- Demo/tkinter/matt/bind-w-mult-calls-p-type.py | 1 - Demo/tkinter/matt/entry-with-shared-variable.py | 3 +- Demo/tkinter/matt/pong-demo-1.py | 2 - Demo/tkinter/matt/printing-coords-of-items.py | 2 +- Doc/library/locale.rst | 2 +- Doc/library/multiprocessing.rst | 4 +- Doc/library/re.rst | 2 +- Doc/library/string.rst | 2 +- Doc/library/warnings.rst | 14 + Doc/tools/sphinxext/susp-ignored.csv | 12 +- Lib/test/test_ssl.py | 2 +- Misc/developers.txt | 3 + Parser/tokenizer.h | 2 +- Tools/pynche/pyColorChooser.py | 4 +- Tools/ssl/get-remote-certificate.py | 18 +- 38 files changed, 1207 insertions(+), 1161 deletions(-) delete mode 100755 Demo/tkinter/guido/AttrDialog.py delete mode 100755 Demo/tkinter/guido/ManPage.py delete mode 100755 Demo/tkinter/guido/MimeViewer.py delete mode 100755 Demo/tkinter/guido/ShellWindow.py create mode 100644 Demo/tkinter/guido/attr_dialog.py create mode 100644 Demo/tkinter/guido/manpage.py create mode 100755 Demo/tkinter/guido/mimeviewer.py create mode 100644 Demo/tkinter/guido/shell_window.py diff --git a/Demo/cgi/README b/Demo/cgi/README index e50d2d0..c0631b6 100644 --- a/Demo/cgi/README +++ b/Demo/cgi/README @@ -1,8 +1,7 @@ CGI Examples ------------ -Here are some example CGI programs. For a larger example, see -../../Tools/faqwiz/. +Here are some example CGI programs. cgi0.sh -- A shell script to test your server is configured for CGI cgi1.py -- A Python script to test your server is configured for CGI diff --git a/Demo/md5test/md5driver.py b/Demo/md5test/md5driver.py index 7df3e75..7f561ab 100755 --- a/Demo/md5test/md5driver.py +++ b/Demo/md5test/md5driver.py @@ -80,7 +80,7 @@ def MDFilter(): mdContext = md5() while 1: - data = sys.stdin.read(16) + data = sys.stdin.read(16).encode() if not data: break mdContext.update(data) diff --git a/Demo/tkinter/guido/AttrDialog.py b/Demo/tkinter/guido/AttrDialog.py deleted file mode 100755 index 5508e3b..0000000 --- a/Demo/tkinter/guido/AttrDialog.py +++ /dev/null @@ -1,451 +0,0 @@ - -# The options of a widget are described by the following attributes -# of the Pack and Widget dialogs: -# -# Dialog.current: {name: value} -# -- changes during Widget's lifetime -# -# Dialog.options: {name: (default, klass)} -# -- depends on widget class only -# -# Dialog.classes: {klass: (v0, v1, v2, ...) | 'boolean' | 'other'} -# -- totally static, though different between PackDialog and WidgetDialog -# (but even that could be unified) - -from tkinter import * - -class Option: - - varclass = StringVar # May be overridden - - def __init__(self, dialog, option): - self.dialog = dialog - self.option = option - self.master = dialog.top - self.default, self.klass = dialog.options[option] - self.var = self.varclass(self.master) - self.frame = Frame(self.master) - self.frame.pack(fill=X) - self.label = Label(self.frame, text=(option + ":")) - self.label.pack(side=LEFT) - self.update() - self.addoption() - - def refresh(self): - self.dialog.refresh() - self.update() - - def update(self): - try: - self.current = self.dialog.current[self.option] - except KeyError: - self.current = self.default - self.var.set(self.current) - - def set(self, e=None): # Should be overridden - pass - -class BooleanOption(Option): - - varclass = BooleanVar - - def addoption(self): - self.button = Checkbutton(self.frame, - text='on/off', - onvalue=1, - offvalue=0, - variable=self.var, - relief=RAISED, - borderwidth=2, - command=self.set) - self.button.pack(side=RIGHT) - -class EnumOption(Option): - - def addoption(self): - self.button = Menubutton(self.frame, - textvariable=self.var, - relief=RAISED, borderwidth=2) - self.button.pack(side=RIGHT) - self.menu = Menu(self.button) - self.button['menu'] = self.menu - for v in self.dialog.classes[self.klass]: - self.menu.add_radiobutton( - label=v, - variable=self.var, - value=v, - command=self.set) - -class StringOption(Option): - - def addoption(self): - self.entry = Entry(self.frame, - textvariable=self.var, - width=10, - relief=SUNKEN, - borderwidth=2) - self.entry.pack(side=RIGHT, fill=X, expand=1) - self.entry.bind('', self.set) - -class ReadonlyOption(Option): - - def addoption(self): - self.label = Label(self.frame, textvariable=self.var, - anchor=E) - self.label.pack(side=RIGHT) - -class Dialog: - - def __init__(self, master): - self.master = master - self.fixclasses() - self.refresh() - self.top = Toplevel(self.master) - self.top.title(self.__class__.__name__) - self.top.minsize(1, 1) - self.addchoices() - - def refresh(self): pass # Must override - - def fixclasses(self): pass # May override - - def addchoices(self): - self.choices = {} - list = [] - for k, dc in self.options.items(): - list.append((k, dc)) - list.sort() - for k, (d, c) in list: - try: - cl = self.classes[c] - except KeyError: - cl = 'unknown' - if type(cl) == TupleType: - cl = self.enumoption - elif cl == 'boolean': - cl = self.booleanoption - elif cl == 'readonly': - cl = self.readonlyoption - else: - cl = self.stringoption - self.choices[k] = cl(self, k) - - # Must override: - options = {} - classes = {} - - # May override: - booleanoption = BooleanOption - stringoption = StringOption - enumoption = EnumOption - readonlyoption = ReadonlyOption - -class PackDialog(Dialog): - - def __init__(self, widget): - self.widget = widget - Dialog.__init__(self, widget) - - def refresh(self): - self.current = self.widget.info() - self.current['.class'] = self.widget.winfo_class() - self.current['.name'] = self.widget._w - - class packoption: # Mix-in class - def set(self, e=None): - self.current = self.var.get() - try: - self.dialog.widget.pack(**{self.option: self.current}) - except TclError as msg: - print(msg) - self.refresh() - - class booleanoption(packoption, BooleanOption): pass - class enumoption(packoption, EnumOption): pass - class stringoption(packoption, StringOption): pass - class readonlyoption(packoption, ReadonlyOption): pass - - options = { - '.class': (None, 'Class'), - '.name': (None, 'Name'), - 'after': (None, 'Widget'), - 'anchor': ('center', 'Anchor'), - 'before': (None, 'Widget'), - 'expand': ('no', 'Boolean'), - 'fill': ('none', 'Fill'), - 'in': (None, 'Widget'), - 'ipadx': (0, 'Pad'), - 'ipady': (0, 'Pad'), - 'padx': (0, 'Pad'), - 'pady': (0, 'Pad'), - 'side': ('top', 'Side'), - } - - classes = { - 'Anchor': (N, NE, E, SE, S, SW, W, NW, CENTER), - 'Boolean': 'boolean', - 'Class': 'readonly', - 'Expand': 'boolean', - 'Fill': (NONE, X, Y, BOTH), - 'Name': 'readonly', - 'Pad': 'pixel', - 'Side': (TOP, RIGHT, BOTTOM, LEFT), - 'Widget': 'readonly', - } - -class RemotePackDialog(PackDialog): - - def __init__(self, master, app, widget): - self.master = master - self.app = app - self.widget = widget - self.refresh() - self.top = Toplevel(self.master) - self.top.title(self.app + ' PackDialog') - self.top.minsize(1, 1) - self.addchoices() - - def refresh(self): - try: - words = self.master.tk.splitlist( - self.master.send(self.app, - 'pack', - 'info', - self.widget)) - except TclError as msg: - print(msg) - return - dict = {} - for i in range(0, len(words), 2): - key = words[i][1:] - value = words[i+1] - dict[key] = value - dict['.class'] = self.master.send(self.app, - 'winfo', - 'class', - self.widget) - dict['.name'] = self.widget - self.current = dict - - class remotepackoption: # Mix-in class - def set(self, e=None): - self.current = self.var.get() - try: - self.dialog.master.send( - self.dialog.app, - 'pack', - 'config', - self.dialog.widget, - '-'+self.option, - self.dialog.master.tk.merge( - self.current)) - except TclError as msg: - print(msg) - self.refresh() - - class booleanoption(remotepackoption, BooleanOption): pass - class enumoption(remotepackoption, EnumOption): pass - class stringoption(remotepackoption, StringOption): pass - class readonlyoption(remotepackoption, ReadonlyOption): pass - -class WidgetDialog(Dialog): - - def __init__(self, widget): - self.widget = widget - self.klass = widget.winfo_class() - Dialog.__init__(self, widget) - - def fixclasses(self): - if self.klass in self.addclasses: - classes = {} - for c in (self.classes, - self.addclasses[self.klass]): - for k in c.keys(): - classes[k] = c[k] - self.classes = classes - - def refresh(self): - self.configuration = self.widget.config() - self.update() - self.current['.class'] = self.widget.winfo_class() - self.current['.name'] = self.widget._w - - def update(self): - self.current = {} - self.options = {} - for k, v in self.configuration.items(): - if len(v) > 4: - self.current[k] = v[4] - self.options[k] = v[3], v[2] # default, klass - self.options['.class'] = (None, 'Class') - self.options['.name'] = (None, 'Name') - - class widgetoption: # Mix-in class - def set(self, e=None): - self.current = self.var.get() - try: - self.dialog.widget[self.option] = self.current - except TclError as msg: - print(msg) - self.refresh() - - class booleanoption(widgetoption, BooleanOption): pass - class enumoption(widgetoption, EnumOption): pass - class stringoption(widgetoption, StringOption): pass - class readonlyoption(widgetoption, ReadonlyOption): pass - - # Universal classes - classes = { - 'Anchor': (N, NE, E, SE, S, SW, W, NW, CENTER), - 'Aspect': 'integer', - 'Background': 'color', - 'Bitmap': 'bitmap', - 'BorderWidth': 'pixel', - 'Class': 'readonly', - 'CloseEnough': 'double', - 'Command': 'command', - 'Confine': 'boolean', - 'Cursor': 'cursor', - 'CursorWidth': 'pixel', - 'DisabledForeground': 'color', - 'ExportSelection': 'boolean', - 'Font': 'font', - 'Foreground': 'color', - 'From': 'integer', - 'Geometry': 'geometry', - 'Height': 'pixel', - 'InsertWidth': 'time', - 'Justify': (LEFT, CENTER, RIGHT), - 'Label': 'string', - 'Length': 'pixel', - 'MenuName': 'widget', - 'Name': 'readonly', - 'OffTime': 'time', - 'OnTime': 'time', - 'Orient': (HORIZONTAL, VERTICAL), - 'Pad': 'pixel', - 'Relief': (RAISED, SUNKEN, FLAT, RIDGE, GROOVE), - 'RepeatDelay': 'time', - 'RepeatInterval': 'time', - 'ScrollCommand': 'command', - 'ScrollIncrement': 'pixel', - 'ScrollRegion': 'rectangle', - 'ShowValue': 'boolean', - 'SetGrid': 'boolean', - 'Sliderforeground': 'color', - 'SliderLength': 'pixel', - 'Text': 'string', - 'TickInterval': 'integer', - 'To': 'integer', - 'Underline': 'index', - 'Variable': 'variable', - 'Value': 'string', - 'Width': 'pixel', - 'Wrap': (NONE, CHAR, WORD), - } - - # Classes that (may) differ per widget type - _tristate = {'State': (NORMAL, ACTIVE, DISABLED)} - _bistate = {'State': (NORMAL, DISABLED)} - addclasses = { - 'Button': _tristate, - 'Radiobutton': _tristate, - 'Checkbutton': _tristate, - 'Entry': _bistate, - 'Text': _bistate, - 'Menubutton': _tristate, - 'Slider': _bistate, - } - -class RemoteWidgetDialog(WidgetDialog): - - def __init__(self, master, app, widget): - self.app = app - self.widget = widget - self.klass = master.send(self.app, - 'winfo', - 'class', - self.widget) - Dialog.__init__(self, master) - - def refresh(self): - try: - items = self.master.tk.splitlist( - self.master.send(self.app, - self.widget, - 'config')) - except TclError as msg: - print(msg) - return - dict = {} - for item in items: - words = self.master.tk.splitlist(item) - key = words[0][1:] - value = (key,) + words[1:] - dict[key] = value - self.configuration = dict - self.update() - self.current['.class'] = self.klass - self.current['.name'] = self.widget - - class remotewidgetoption: # Mix-in class - def set(self, e=None): - self.current = self.var.get() - try: - self.dialog.master.send( - self.dialog.app, - self.dialog.widget, - 'config', - '-'+self.option, - self.current) - except TclError as msg: - print(msg) - self.refresh() - - class booleanoption(remotewidgetoption, BooleanOption): pass - class enumoption(remotewidgetoption, EnumOption): pass - class stringoption(remotewidgetoption, StringOption): pass - class readonlyoption(remotewidgetoption, ReadonlyOption): pass - -def test(): - import sys - root = Tk() - root.minsize(1, 1) - if sys.argv[1:]: - remotetest(root, sys.argv[1]) - else: - frame = Frame(root, name='frame') - frame.pack(expand=1, fill=BOTH) - button = Button(frame, name='button', text='button') - button.pack(expand=1) - canvas = Canvas(frame, name='canvas') - canvas.pack() - fpd = PackDialog(frame) - fwd = WidgetDialog(frame) - bpd = PackDialog(button) - bwd = WidgetDialog(button) - cpd = PackDialog(canvas) - cwd = WidgetDialog(canvas) - root.mainloop() - -def remotetest(root, app): - from listtree import listtree - list = listtree(root, app) - list.bind('', opendialogs) - list.app = app # Pass it on to handler - -def opendialogs(e): - import string - list = e.widget - sel = list.curselection() - for i in sel: - item = list.get(i) - widget = string.split(item)[0] - RemoteWidgetDialog(list, list.app, widget) - if widget == '.': continue - try: - RemotePackDialog(list, list.app, widget) - except TclError as msg: - print(msg) - -test() diff --git a/Demo/tkinter/guido/ManPage.py b/Demo/tkinter/guido/ManPage.py deleted file mode 100755 index a9309a3..0000000 --- a/Demo/tkinter/guido/ManPage.py +++ /dev/null @@ -1,220 +0,0 @@ -# Widget to display a man page - -import re -from tkinter import * -from tkinter import _tkinter -from tkinter.scrolledtext import ScrolledText - -# XXX These fonts may have to be changed to match your system -BOLDFONT = '*-Courier-Bold-R-Normal-*-120-*' -ITALICFONT = '*-Courier-Medium-O-Normal-*-120-*' - -# XXX Recognizing footers is system dependent -# (This one works for IRIX 5.2 and Solaris 2.2) -footerprog = re.compile( - '^ Page [1-9][0-9]*[ \t]+\|^.*Last change:.*[1-9][0-9]*\n') -emptyprog = re.compile('^[ \t]*\n') -ulprog = re.compile('^[ \t]*[Xv!_][Xv!_ \t]*\n') - -# Basic Man Page class -- does not disable editing -class EditableManPage(ScrolledText): - - # Initialize instance - def __init__(self, master=None, **cnf): - # Initialize base class - ScrolledText.__init__(self, master, **cnf) - - # Define tags for formatting styles - self.tag_config('X', underline=1) - self.tag_config('!', font=BOLDFONT) - self.tag_config('_', font=ITALICFONT) - - # Set state to idle - self.fp = None - self.lineno = 0 - - # Test whether we are busy parsing a file - def busy(self): - return self.fp != None - - # Ensure we're not busy - def kill(self): - if self.busy(): - self._endparser() - - # Parse a file, in the background - def asyncparsefile(self, fp): - self._startparser(fp) - self.tk.createfilehandler(fp, _tkinter.READABLE, - self._filehandler) - - parsefile = asyncparsefile # Alias - - # I/O handler used by background parsing - def _filehandler(self, fp, mask): - nextline = self.fp.readline() - if not nextline: - self._endparser() - return - self._parseline(nextline) - - # Parse a file, now (cannot be aborted) - def syncparsefile(self, fp): - from select import select - def avail(fp=fp, tout=0.0, select=select): - return select([fp], [], [], tout)[0] - height = self.getint(self['height']) - self._startparser(fp) - while 1: - nextline = fp.readline() - if not nextline: - break - self._parseline(nextline) - self._endparser() - - # Initialize parsing from a particular file -- must not be busy - def _startparser(self, fp): - if self.busy(): - raise RuntimeError('startparser: still busy') - fp.fileno() # Test for file-ness - self.fp = fp - self.lineno = 0 - self.ok = 0 - self.empty = 0 - self.buffer = None - savestate = self['state'] - self['state'] = NORMAL - self.delete('1.0', END) - self['state'] = savestate - - # End parsing -- must be busy, need not be at EOF - def _endparser(self): - if not self.busy(): - raise RuntimeError('endparser: not busy') - if self.buffer: - self._parseline('') - try: - self.tk.deletefilehandler(self.fp) - except TclError as msg: - pass - self.fp.close() - self.fp = None - del self.ok, self.empty, self.buffer - - # Parse a single line - def _parseline(self, nextline): - if not self.buffer: - # Save this line -- we need one line read-ahead - self.buffer = nextline - return - if emptyprog.match(self.buffer) >= 0: - # Buffered line was empty -- set a flag - self.empty = 1 - self.buffer = nextline - return - textline = self.buffer - if ulprog.match(nextline) >= 0: - # Next line is properties for buffered line - propline = nextline - self.buffer = None - else: - # Next line is read-ahead - propline = None - self.buffer = nextline - if not self.ok: - # First non blank line after footer must be header - # -- skip that too - self.ok = 1 - self.empty = 0 - return - if footerprog.match(textline) >= 0: - # Footer -- start skipping until next non-blank line - self.ok = 0 - self.empty = 0 - return - savestate = self['state'] - self['state'] = NORMAL - if TkVersion >= 4.0: - self.mark_set('insert', 'end-1c') - else: - self.mark_set('insert', END) - if self.empty: - # One or more previous lines were empty - # -- insert one blank line in the text - self._insert_prop('\n') - self.lineno = self.lineno + 1 - self.empty = 0 - if not propline: - # No properties - self._insert_prop(textline) - else: - # Search for properties - p = '' - j = 0 - for i in range(min(len(propline), len(textline))): - if propline[i] != p: - if j < i: - self._insert_prop(textline[j:i], p) - j = i - p = propline[i] - self._insert_prop(textline[j:]) - self.lineno = self.lineno + 1 - self['state'] = savestate - - # Insert a string at the end, with at most one property (tag) - def _insert_prop(self, str, prop = ' '): - here = self.index(AtInsert()) - self.insert(AtInsert(), str) - if TkVersion <= 4.0: - tags = self.tag_names(here) - for tag in tags: - self.tag_remove(tag, here, AtInsert()) - if prop != ' ': - self.tag_add(prop, here, AtInsert()) - -# Readonly Man Page class -- disables editing, otherwise the same -class ReadonlyManPage(EditableManPage): - - # Initialize instance - def __init__(self, master=None, **cnf): - cnf['state'] = DISABLED - EditableManPage.__init__(self, master, **cnf) - -# Alias -ManPage = ReadonlyManPage - -# Test program. -# usage: ManPage [manpage]; or ManPage [-f] file -# -f means that the file is nroff -man output run through ul -i -def test(): - import os - import sys - # XXX This directory may be different on your system - MANDIR = '/usr/local/man/mann' - DEFAULTPAGE = 'Tcl' - formatted = 0 - if sys.argv[1:] and sys.argv[1] == '-f': - formatted = 1 - del sys.argv[1] - if sys.argv[1:]: - name = sys.argv[1] - else: - name = DEFAULTPAGE - if not formatted: - if name[-2:-1] != '.': - name = name + '.n' - name = os.path.join(MANDIR, name) - root = Tk() - root.minsize(1, 1) - manpage = ManPage(root, relief=SUNKEN, borderwidth=2) - manpage.pack(expand=1, fill=BOTH) - if formatted: - fp = open(name, 'r') - else: - fp = os.popen('nroff -man %s | ul -i' % name, 'r') - manpage.parsefile(fp) - root.mainloop() - -# Run the test program when called as a script -if __name__ == '__main__': - test() diff --git a/Demo/tkinter/guido/MimeViewer.py b/Demo/tkinter/guido/MimeViewer.py deleted file mode 100755 index 11701cd..0000000 --- a/Demo/tkinter/guido/MimeViewer.py +++ /dev/null @@ -1,143 +0,0 @@ -#! /usr/bin/env python - -# View a single MIME multipart message. -# Display each part as a box. - -import string -from types import * -from tkinter import * -from tkinter.scrolledtext import ScrolledText - -class MimeViewer: - def __init__(self, parent, title, msg): - self.title = title - self.msg = msg - self.frame = Frame(parent, {'relief': 'raised', 'bd': 2}) - self.frame.packing = {'expand': 0, 'fill': 'both'} - self.button = Checkbutton(self.frame, - {'text': title, - 'command': self.toggle}) - self.button.pack({'anchor': 'w'}) - headertext = msg.getheadertext( - lambda x: x != 'received' and x[:5] != 'x400-') - height = countlines(headertext, 4) - if height: - self.htext = ScrolledText(self.frame, - {'height': height, - 'width': 80, - 'wrap': 'none', - 'relief': 'raised', - 'bd': 2}) - self.htext.packing = {'expand': 1, 'fill': 'both', - 'after': self.button} - self.htext.insert('end', headertext) - else: - self.htext = Frame(self.frame, - {'relief': 'raised', 'bd': 2}) - self.htext.packing = {'side': 'top', - 'ipady': 2, - 'fill': 'x', - 'after': self.button} - body = msg.getbody() - if type(body) == StringType: - self.pad = None - height = countlines(body, 10) - if height: - self.btext = ScrolledText(self.frame, - {'height': height, - 'width': 80, - 'wrap': 'none', - 'relief': 'raised', - 'bd': 2}) - self.btext.packing = {'expand': 1, - 'fill': 'both'} - self.btext.insert('end', body) - else: - self.btext = None - self.parts = None - else: - self.pad = Frame(self.frame, - {'relief': 'flat', 'bd': 2}) - self.pad.packing = {'side': 'left', 'ipadx': 10, - 'fill': 'y', 'after': self.htext} - self.parts = [] - for i in range(len(body)): - p = MimeViewer(self.frame, - '%s.%d' % (title, i+1), - body[i]) - self.parts.append(p) - self.btext = None - self.collapsed = 1 - def pack(self): - self.frame.pack(self.frame.packing) - def destroy(self): - self.frame.destroy() - def show(self): - if self.collapsed: - self.button.invoke() - def toggle(self): - if self.collapsed: - self.explode() - else: - self.collapse() - def collapse(self): - self.collapsed = 1 - for comp in self.htext, self.btext, self.pad: - if comp: - comp.forget() - if self.parts: - for part in self.parts: - part.frame.forget() - self.frame.pack({'expand': 0}) - def explode(self): - self.collapsed = 0 - for comp in self.htext, self.btext, self.pad: - if comp: comp.pack(comp.packing) - if self.parts: - for part in self.parts: - part.pack() - self.frame.pack({'expand': 1}) - -def countlines(str, limit): - i = 0 - n = 0 - while n < limit: - i = string.find(str, '\n', i) - if i < 0: break - n = n+1 - i = i+1 - return n - -def main(): - import sys - import getopt - import mhlib - opts, args = getopt.getopt(sys.argv[1:], '') - for o, a in opts: - pass - message = None - folder = 'inbox' - for arg in args: - if arg[:1] == '+': - folder = arg[1:] - else: - message = string.atoi(arg) - - mh = mhlib.MH() - f = mh.openfolder(folder) - if not message: - message = f.getcurrent() - m = f.openmessage(message) - - root = Tk() - tk = root.tk - - top = MimeViewer(root, '+%s/%d' % (folder, message), m) - top.pack() - top.show() - - root.minsize(1, 1) - - tk.mainloop() - -if __name__ == '__main__': main() diff --git a/Demo/tkinter/guido/ShellWindow.py b/Demo/tkinter/guido/ShellWindow.py deleted file mode 100755 index fffcbc5..0000000 --- a/Demo/tkinter/guido/ShellWindow.py +++ /dev/null @@ -1,147 +0,0 @@ -import os -import sys -import string -from tkinter import * -from tkinter.scrolledtext import ScrolledText -from tkinter.dialog import Dialog -import signal - -BUFSIZE = 512 - -class ShellWindow(ScrolledText): - - def __init__(self, master=None, shell=None, **cnf): - if not shell: - try: - shell = os.environ['SHELL'] - except KeyError: - shell = '/bin/sh' - shell = shell + ' -i' - args = string.split(shell) - shell = args[0] - - ScrolledText.__init__(self, master, **cnf) - self.pos = '1.0' - self.bind('', self.inputhandler) - self.bind('', self.sigint) - self.bind('', self.sigterm) - self.bind('', self.sigkill) - self.bind('', self.sendeof) - - self.pid, self.fromchild, self.tochild = spawn(shell, args) - self.tk.createfilehandler(self.fromchild, READABLE, - self.outputhandler) - - def outputhandler(self, file, mask): - data = os.read(file, BUFSIZE) - if not data: - self.tk.deletefilehandler(file) - pid, sts = os.waitpid(self.pid, 0) - print('pid', pid, 'status', sts) - self.pid = None - detail = sts>>8 - cause = sts & 0xff - if cause == 0: - msg = "exit status %d" % detail - else: - msg = "killed by signal %d" % (cause & 0x7f) - if cause & 0x80: - msg = msg + " -- core dumped" - Dialog(self.master, - text=msg, - title="Exit status", - bitmap='warning', - default=0, - strings=('OK',)) - return - self.insert(END, data) - self.pos = self.index("end - 1 char") - self.yview_pickplace(END) - - def inputhandler(self, *args): - if not self.pid: - self.no_process() - return "break" - self.insert(END, "\n") - line = self.get(self.pos, "end - 1 char") - self.pos = self.index(END) - os.write(self.tochild, line) - return "break" - - def sendeof(self, *args): - if not self.pid: - self.no_process() - return "break" - os.close(self.tochild) - return "break" - - def sendsig(self, sig): - if not self.pid: - self.no_process() - return "break" - os.kill(self.pid, sig) - return "break" - - def sigint(self, *args): - return self.sendsig(signal.SIGINT) - - def sigquit(self, *args): - return self.sendsig(signal.SIGQUIT) - - def sigterm(self, *args): - return self.sendsig(signal.SIGTERM) - - def sigkill(self, *args): - return self.sendsig(signal.SIGKILL) - - def no_process(self): - Dialog(self.master, - text="No active process", - title="No process", - bitmap='error', - default=0, - strings=('OK',)) - -MAXFD = 100 # Max number of file descriptors (os.getdtablesize()???) - -def spawn(prog, args): - p2cread, p2cwrite = os.pipe() - c2pread, c2pwrite = os.pipe() - pid = os.fork() - if pid == 0: - # Child - for i in 0, 1, 2: - try: - os.close(i) - except os.error: - pass - if os.dup(p2cread) != 0: - sys.stderr.write('popen2: bad read dup\n') - if os.dup(c2pwrite) != 1: - sys.stderr.write('popen2: bad write dup\n') - if os.dup(c2pwrite) != 2: - sys.stderr.write('popen2: bad write dup\n') - os.closerange(3, MAXFD) - try: - os.execvp(prog, args) - finally: - sys.stderr.write('execvp failed\n') - os._exit(1) - os.close(p2cread) - os.close(c2pwrite) - return pid, c2pread, p2cwrite - -def test(): - shell = string.join(sys.argv[1:]) - root = Tk() - root.minsize(1, 1) - if shell: - w = ShellWindow(root, shell=shell) - else: - w = ShellWindow(root) - w.pack(expand=1, fill=BOTH) - w.focus_set() - w.tk.mainloop() - -if __name__ == '__main__': - test() diff --git a/Demo/tkinter/guido/attr_dialog.py b/Demo/tkinter/guido/attr_dialog.py new file mode 100644 index 0000000..229a558 --- /dev/null +++ b/Demo/tkinter/guido/attr_dialog.py @@ -0,0 +1,460 @@ + +# The options of a widget are described by the following attributes +# of the Pack and Widget dialogs: +# +# Dialog.current: {name: value} +# -- changes during Widget's lifetime +# +# Dialog.options: {name: (default, klass)} +# -- depends on widget class only +# +# Dialog.classes: {klass: (v0, v1, v2, ...) | 'boolean' | 'other'} +# -- totally static, though different between PackDialog and WidgetDialog +# (but even that could be unified) + +from tkinter import * + + +class Option: + + varclass = StringVar # May be overridden + + def __init__(self, dialog, option): + self.dialog = dialog + self.option = option + self.master = dialog.top + self.default, self.klass = dialog.options[option] + self.var = self.varclass(self.master) + self.frame = Frame(self.master) + self.frame.pack(fill=X) + self.label = Label(self.frame, text=(option + ":")) + self.label.pack(side=LEFT) + self.update() + self.addoption() + + def refresh(self): + self.dialog.refresh() + self.update() + + def update(self): + try: + self.current = self.dialog.current[self.option] + except KeyError: + self.current = self.default + self.var.set(self.current) + + def set(self, e=None): # Should be overridden + pass + + +class BooleanOption(Option): + + varclass = BooleanVar + + def addoption(self): + self.button = Checkbutton(self.frame, + text='on/off', + onvalue=1, + offvalue=0, + variable=self.var, + relief=RAISED, + borderwidth=2, + command=self.set) + self.button.pack(side=RIGHT) + + +class EnumOption(Option): + + def addoption(self): + self.button = Menubutton(self.frame, + textvariable=self.var, + relief=RAISED, borderwidth=2) + self.button.pack(side=RIGHT) + self.menu = Menu(self.button) + self.button['menu'] = self.menu + for v in self.dialog.classes[self.klass]: + self.menu.add_radiobutton( + label=v, + variable=self.var, + value=v, + command=self.set) + + +class StringOption(Option): + + def addoption(self): + self.entry = Entry(self.frame, + textvariable=self.var, + width=10, + relief=SUNKEN, + borderwidth=2) + self.entry.pack(side=RIGHT, fill=X, expand=1) + self.entry.bind('', self.set) + + +class ReadonlyOption(Option): + + def addoption(self): + self.label = Label(self.frame, textvariable=self.var, + anchor=E) + self.label.pack(side=RIGHT) + + +class Dialog: + + def __init__(self, master): + self.master = master + self.fixclasses() + self.refresh() + self.top = Toplevel(self.master) + self.top.title(self.__class__.__name__) + self.top.minsize(1, 1) + self.addchoices() + + def refresh(self): pass # Must override + + def fixclasses(self): pass # May override + + def addchoices(self): + self.choices = {} + list = [] + for k, dc in self.options.items(): + list.append((k, dc)) + list.sort() + for k, (d, c) in list: + try: + cl = self.classes[c] + except KeyError: + cl = 'unknown' + if type(cl) is tuple: + cl = self.enumoption + elif cl == 'boolean': + cl = self.booleanoption + elif cl == 'readonly': + cl = self.readonlyoption + else: + cl = self.stringoption + self.choices[k] = cl(self, k) + + # Must override: + options = {} + classes = {} + + # May override: + booleanoption = BooleanOption + stringoption = StringOption + enumoption = EnumOption + readonlyoption = ReadonlyOption + + +class PackDialog(Dialog): + + def __init__(self, widget): + self.widget = widget + Dialog.__init__(self, widget) + + def refresh(self): + self.current = self.widget.info() + self.current['.class'] = self.widget.winfo_class() + self.current['.name'] = self.widget._w + + class packoption: # Mix-in class + def set(self, e=None): + self.current = self.var.get() + try: + self.dialog.widget.pack(**{self.option: self.current}) + except TclError as msg: + print(msg) + self.refresh() + + class booleanoption(packoption, BooleanOption): pass + class enumoption(packoption, EnumOption): pass + class stringoption(packoption, StringOption): pass + class readonlyoption(packoption, ReadonlyOption): pass + + options = { + '.class': (None, 'Class'), + '.name': (None, 'Name'), + 'after': (None, 'Widget'), + 'anchor': ('center', 'Anchor'), + 'before': (None, 'Widget'), + 'expand': ('no', 'Boolean'), + 'fill': ('none', 'Fill'), + 'in': (None, 'Widget'), + 'ipadx': (0, 'Pad'), + 'ipady': (0, 'Pad'), + 'padx': (0, 'Pad'), + 'pady': (0, 'Pad'), + 'side': ('top', 'Side'), + } + + classes = { + 'Anchor': (N, NE, E, SE, S, SW, W, NW, CENTER), + 'Boolean': 'boolean', + 'Class': 'readonly', + 'Expand': 'boolean', + 'Fill': (NONE, X, Y, BOTH), + 'Name': 'readonly', + 'Pad': 'pixel', + 'Side': (TOP, RIGHT, BOTTOM, LEFT), + 'Widget': 'readonly', + } + +class RemotePackDialog(PackDialog): + + def __init__(self, master, app, widget): + self.master = master + self.app = app + self.widget = widget + self.refresh() + self.top = Toplevel(self.master) + self.top.title(self.app + ' PackDialog') + self.top.minsize(1, 1) + self.addchoices() + + def refresh(self): + try: + words = self.master.tk.splitlist( + self.master.send(self.app, + 'pack', + 'info', + self.widget)) + except TclError as msg: + print(msg) + return + dict = {} + for i in range(0, len(words), 2): + key = words[i][1:] + value = words[i+1] + dict[key] = value + dict['.class'] = self.master.send(self.app, + 'winfo', + 'class', + self.widget) + dict['.name'] = self.widget + self.current = dict + + class remotepackoption: # Mix-in class + def set(self, e=None): + self.current = self.var.get() + try: + self.dialog.master.send( + self.dialog.app, + 'pack', + 'config', + self.dialog.widget, + '-'+self.option, + self.dialog.master.tk.merge( + self.current)) + except TclError as msg: + print(msg) + self.refresh() + + class booleanoption(remotepackoption, BooleanOption): pass + class enumoption(remotepackoption, EnumOption): pass + class stringoption(remotepackoption, StringOption): pass + class readonlyoption(remotepackoption, ReadonlyOption): pass + + +class WidgetDialog(Dialog): + + def __init__(self, widget): + self.widget = widget + self.klass = widget.winfo_class() + Dialog.__init__(self, widget) + + def fixclasses(self): + if self.klass in self.addclasses: + classes = {} + for c in (self.classes, + self.addclasses[self.klass]): + for k in c.keys(): + classes[k] = c[k] + self.classes = classes + + def refresh(self): + self.configuration = self.widget.config() + self.update() + self.current['.class'] = self.widget.winfo_class() + self.current['.name'] = self.widget._w + + def update(self): + self.current = {} + self.options = {} + for k, v in self.configuration.items(): + if len(v) > 4: + self.current[k] = v[4] + self.options[k] = v[3], v[2] # default, klass + self.options['.class'] = (None, 'Class') + self.options['.name'] = (None, 'Name') + + class widgetoption: # Mix-in class + def set(self, e=None): + self.current = self.var.get() + try: + self.dialog.widget[self.option] = self.current + except TclError as msg: + print(msg) + self.refresh() + + class booleanoption(widgetoption, BooleanOption): pass + class enumoption(widgetoption, EnumOption): pass + class stringoption(widgetoption, StringOption): pass + class readonlyoption(widgetoption, ReadonlyOption): pass + + # Universal classes + classes = { + 'Anchor': (N, NE, E, SE, S, SW, W, NW, CENTER), + 'Aspect': 'integer', + 'Background': 'color', + 'Bitmap': 'bitmap', + 'BorderWidth': 'pixel', + 'Class': 'readonly', + 'CloseEnough': 'double', + 'Command': 'command', + 'Confine': 'boolean', + 'Cursor': 'cursor', + 'CursorWidth': 'pixel', + 'DisabledForeground': 'color', + 'ExportSelection': 'boolean', + 'Font': 'font', + 'Foreground': 'color', + 'From': 'integer', + 'Geometry': 'geometry', + 'Height': 'pixel', + 'InsertWidth': 'time', + 'Justify': (LEFT, CENTER, RIGHT), + 'Label': 'string', + 'Length': 'pixel', + 'MenuName': 'widget', + 'Name': 'readonly', + 'OffTime': 'time', + 'OnTime': 'time', + 'Orient': (HORIZONTAL, VERTICAL), + 'Pad': 'pixel', + 'Relief': (RAISED, SUNKEN, FLAT, RIDGE, GROOVE), + 'RepeatDelay': 'time', + 'RepeatInterval': 'time', + 'ScrollCommand': 'command', + 'ScrollIncrement': 'pixel', + 'ScrollRegion': 'rectangle', + 'ShowValue': 'boolean', + 'SetGrid': 'boolean', + 'Sliderforeground': 'color', + 'SliderLength': 'pixel', + 'Text': 'string', + 'TickInterval': 'integer', + 'To': 'integer', + 'Underline': 'index', + 'Variable': 'variable', + 'Value': 'string', + 'Width': 'pixel', + 'Wrap': (NONE, CHAR, WORD), + } + + # Classes that (may) differ per widget type + _tristate = {'State': (NORMAL, ACTIVE, DISABLED)} + _bistate = {'State': (NORMAL, DISABLED)} + addclasses = { + 'Button': _tristate, + 'Radiobutton': _tristate, + 'Checkbutton': _tristate, + 'Entry': _bistate, + 'Text': _bistate, + 'Menubutton': _tristate, + 'Slider': _bistate, + } + + +class RemoteWidgetDialog(WidgetDialog): + + def __init__(self, master, app, widget): + self.app = app + self.widget = widget + self.klass = master.send(self.app, + 'winfo', + 'class', + self.widget) + Dialog.__init__(self, master) + + def refresh(self): + try: + items = self.master.tk.splitlist( + self.master.send(self.app, + self.widget, + 'config')) + except TclError as msg: + print(msg) + return + dict = {} + for item in items: + words = self.master.tk.splitlist(item) + key = words[0][1:] + value = (key,) + words[1:] + dict[key] = value + self.configuration = dict + self.update() + self.current['.class'] = self.klass + self.current['.name'] = self.widget + + class remotewidgetoption: # Mix-in class + def set(self, e=None): + self.current = self.var.get() + try: + self.dialog.master.send( + self.dialog.app, + self.dialog.widget, + 'config', + '-'+self.option, + self.current) + except TclError as msg: + print(msg) + self.refresh() + + class booleanoption(remotewidgetoption, BooleanOption): pass + class enumoption(remotewidgetoption, EnumOption): pass + class stringoption(remotewidgetoption, StringOption): pass + class readonlyoption(remotewidgetoption, ReadonlyOption): pass + + +def test(): + import sys + root = Tk() + root.minsize(1, 1) + if sys.argv[1:]: + remotetest(root, sys.argv[1]) + else: + frame = Frame(root, name='frame') + frame.pack(expand=1, fill=BOTH) + button = Button(frame, name='button', text='button') + button.pack(expand=1) + canvas = Canvas(frame, name='canvas') + canvas.pack() + fpd = PackDialog(frame) + fwd = WidgetDialog(frame) + bpd = PackDialog(button) + bwd = WidgetDialog(button) + cpd = PackDialog(canvas) + cwd = WidgetDialog(canvas) + root.mainloop() + +def remotetest(root, app): + from listtree import listtree + list = listtree(root, app) + list.bind('', opendialogs) + list.app = app # Pass it on to handler + +def opendialogs(e): + list = e.widget + sel = list.curselection() + for i in sel: + item = list.get(i) + widget = item.split()[0] + RemoteWidgetDialog(list, list.app, widget) + if widget == '.': continue + try: + RemotePackDialog(list, list.app, widget) + except TclError as msg: + print(msg) + +test() diff --git a/Demo/tkinter/guido/canvasevents.py b/Demo/tkinter/guido/canvasevents.py index aeb0eb1..ffeb0ca 100644 --- a/Demo/tkinter/guido/canvasevents.py +++ b/Demo/tkinter/guido/canvasevents.py @@ -1,15 +1,41 @@ #! /usr/bin/env python from tkinter import * -from Canvas import Oval, Group, CanvasText -# Fix a bug in Canvas.Group as distributed in Python 1.4. The -# distributed bind() method is broken. This is what should be used: +# Since Canvas.Group is no longer present, the following class reproduces +# a subset of the old Group class that is used by this app. + +class Group: + def __init__(self, canvas, tag=None): + if tag is None: + tag = 'Group%d' % id(self) + + self.tag = self.id = tag + self.canvas = canvas + self.canvas.dtag(self.tag) + + def __str__(self): + return self.tag + + def _do(self, cmd, *args): + return self.canvas.tk.call(self.canvas._w, cmd, self.tag, *args) + + def addtag_withtag(self, tagOrId): + self._do('addtag', 'withtag', tagOrId) + + def bind(self, sequence=None, command=None, add=None): + return self.canvas.tag_bind(self.id, sequence, command, add) + + def move(self, x_amount, y_amount): + self._do('move', x_amount, y_amount) + + def dtag(self, tagToDelete=None): + self._do('dtag', tagToDelete) + + def tkraise(self, aboveThis=None): + self._do('raise', aboveThis) -class Group(Group): - def bind(self, sequence=None, command=None): - return self.canvas.tag_bind(self.id, sequence, command) class Object: @@ -29,7 +55,6 @@ class Object: All instance attributes are public since the derived class may need them. - """ def __init__(self, canvas, x=0, y=0, fill='red', text='object'): @@ -44,12 +69,10 @@ class Object: return str(self.group) def createitems(self, fill, text): - self.__oval = Oval(self.canvas, - self.x-20, self.y-10, self.x+20, self.y+10, - fill=fill, width=3) + self.__oval = self.canvas.create_oval(self.x - 20, self.y - 10, + self.x + 20, self.y + 20, fill=fill, width=3) self.group.addtag_withtag(self.__oval) - self.__text = CanvasText(self.canvas, - self.x, self.y, text=text) + self.__text = self.canvas.create_text(self.x, self.y, text=text) self.group.addtag_withtag(self.__text) def moveby(self, dx, dy): @@ -75,18 +98,15 @@ class Object: class Bottom(Object): - """An object to serve as the bottom of a pile.""" def createitems(self, *args): - self.__oval = Oval(self.canvas, - self.x-20, self.y-10, self.x+20, self.y+10, - fill='gray', outline='') + self.__oval = self.canvas.create_oval(self.x - 20, self.y - 10, + self.x + 20, self.y + 10, fill='gray', outline='') self.group.addtag_withtag(self.__oval) class Pile: - """A group of graphical objects.""" def __init__(self, canvas, x, y, tag=None): diff --git a/Demo/tkinter/guido/dialog.py b/Demo/tkinter/guido/dialog.py index 1832ba4..2a4a939 100755 --- a/Demo/tkinter/guido/dialog.py +++ b/Demo/tkinter/guido/dialog.py @@ -24,8 +24,7 @@ def dialog(master, title, text, bitmap, default, *args): # 2. Fill the top part with the bitmap and message. - msg = Message(top, width='3i', text=text, - font='-Adobe-Times-Medium-R-Normal-*-180-*') + msg = Message(top, width='3i', text=text) msg.pack(side=RIGHT, expand=1, fill=BOTH, padx='3m', pady='3m') if bitmap: bm = Label(top, bitmap=bitmap) diff --git a/Demo/tkinter/guido/electrons.py b/Demo/tkinter/guido/electrons.py index e3bf468..b5c9ec0 100755 --- a/Demo/tkinter/guido/electrons.py +++ b/Demo/tkinter/guido/electrons.py @@ -62,11 +62,11 @@ class Electrons: # Main program def main(): - import sys, string + import sys # First argument is number of electrons, default 30 if sys.argv[1:]: - n = string.atoi(sys.argv[1]) + n = int(sys.argv[1]) else: n = 30 diff --git a/Demo/tkinter/guido/hanoi.py b/Demo/tkinter/guido/hanoi.py index a29b1d7..34a0bba 100755 --- a/Demo/tkinter/guido/hanoi.py +++ b/Demo/tkinter/guido/hanoi.py @@ -125,11 +125,11 @@ class Tkhanoi: # Main program def main(): - import sys, string + import sys # First argument is number of pegs, default 4 if sys.argv[1:]: - n = string.atoi(sys.argv[1]) + n = int(sys.argv[1]) else: n = 4 diff --git a/Demo/tkinter/guido/listtree.py b/Demo/tkinter/guido/listtree.py index 625d20e..8db5b60 100755 --- a/Demo/tkinter/guido/listtree.py +++ b/Demo/tkinter/guido/listtree.py @@ -1,7 +1,6 @@ # List a remote app's widget tree (names and classes only) import sys -import string from tkinter import * @@ -13,8 +12,6 @@ def listtree(master, app): def listnodes(list, app, widget, level): klass = list.send(app, 'winfo', 'class', widget) -## i = string.rindex(widget, '.') -## list.insert(END, '%s%s (%s)' % ((level-1)*'. ', widget[i:], klass)) list.insert(END, '%s (%s)' % (widget, klass)) children = list.tk.splitlist( list.send(app, 'winfo', 'children', widget)) diff --git a/Demo/tkinter/guido/manpage.py b/Demo/tkinter/guido/manpage.py new file mode 100644 index 0000000..750c675 --- /dev/null +++ b/Demo/tkinter/guido/manpage.py @@ -0,0 +1,215 @@ +# Widget to display a man page + +import os +import re +import sys + +from tkinter import * +from tkinter.font import Font +from tkinter.scrolledtext import ScrolledText + +# XXX Recognizing footers is system dependent +# (This one works for IRIX 5.2 and Solaris 2.2) +footerprog = re.compile( + '^ Page [1-9][0-9]*[ \t]+\|^.*Last change:.*[1-9][0-9]*\n') +emptyprog = re.compile('^[ \t]*\n') +ulprog = re.compile('^[ \t]*[Xv!_][Xv!_ \t]*\n') + + +class EditableManPage(ScrolledText): + """Basic Man Page class -- does not disable editing.""" + + def __init__(self, master=None, **cnf): + ScrolledText.__init__(self, master, **cnf) + + bold = Font(font=self['font']).copy() + bold.config(weight='bold') + italic = Font(font=self['font']).copy() + italic.config(slant='italic') + + # Define tags for formatting styles + self.tag_config('X', underline=1) + self.tag_config('!', font=bold) + self.tag_config('_', font=italic) + + # Set state to idle + self.fp = None + self.lineno = 0 + + def busy(self): + """Test whether we are busy parsing a file.""" + return self.fp != None + + def kill(self): + """Ensure we're not busy.""" + if self.busy(): + self._endparser() + + def asyncparsefile(self, fp): + """Parse a file, in the background.""" + self._startparser(fp) + self.tk.createfilehandler(fp, READABLE, + self._filehandler) + + parsefile = asyncparsefile # Alias + + def _filehandler(self, fp, mask): + """I/O handler used by background parsing.""" + nextline = self.fp.readline() + if not nextline: + self._endparser() + return + self._parseline(nextline) + + def syncparsefile(self, fp): + """Parse a file, now (cannot be aborted).""" + self._startparser(fp) + while True: + nextline = fp.readline() + if not nextline: + break + self._parseline(nextline) + self._endparser() + + def _startparser(self, fp): + """Initialize parsing from a particular file -- must not be busy.""" + if self.busy(): + raise RuntimeError('startparser: still busy') + fp.fileno() # Test for file-ness + self.fp = fp + self.lineno = 0 + self.ok = 0 + self.empty = 0 + self.buffer = None + savestate = self['state'] + self['state'] = NORMAL + self.delete('1.0', END) + self['state'] = savestate + + def _endparser(self): + """End parsing -- must be busy, need not be at EOF.""" + if not self.busy(): + raise RuntimeError('endparser: not busy') + if self.buffer: + self._parseline('') + try: + self.tk.deletefilehandler(self.fp) + except TclError: + pass + self.fp.close() + self.fp = None + del self.ok, self.empty, self.buffer + + def _parseline(self, nextline): + """Parse a single line.""" + if not self.buffer: + # Save this line -- we need one line read-ahead + self.buffer = nextline + return + if emptyprog.match(self.buffer): + # Buffered line was empty -- set a flag + self.empty = 1 + self.buffer = nextline + return + textline = self.buffer + if ulprog.match(nextline): + # Next line is properties for buffered line + propline = nextline + self.buffer = None + else: + # Next line is read-ahead + propline = None + self.buffer = nextline + if not self.ok: + # First non blank line after footer must be header + # -- skip that too + self.ok = 1 + self.empty = 0 + return + if footerprog.match(textline): + # Footer -- start skipping until next non-blank line + self.ok = 0 + self.empty = 0 + return + savestate = self['state'] + self['state'] = NORMAL + if TkVersion >= 4.0: + self.mark_set('insert', 'end-1c') + else: + self.mark_set('insert', END) + if self.empty: + # One or more previous lines were empty + # -- insert one blank line in the text + self._insert_prop('\n') + self.lineno = self.lineno + 1 + self.empty = 0 + if not propline: + # No properties + self._insert_prop(textline) + else: + # Search for properties + p = '' + j = 0 + for i in range(min(len(propline), len(textline))): + if propline[i] != p: + if j < i: + self._insert_prop(textline[j:i], p) + j = i + p = propline[i] + self._insert_prop(textline[j:]) + self.lineno = self.lineno + 1 + self['state'] = savestate + + def _insert_prop(self, str, prop = ' '): + """Insert a string at the end, with at most one property (tag).""" + here = self.index(AtInsert()) + self.insert(AtInsert(), str) + if TkVersion <= 4.0: + tags = self.tag_names(here) + for tag in tags: + self.tag_remove(tag, here, AtInsert()) + if prop != ' ': + self.tag_add(prop, here, AtInsert()) + + +class ReadonlyManPage(EditableManPage): + """Readonly Man Page class -- disables editing, otherwise the same.""" + + def __init__(self, master=None, **cnf): + cnf['state'] = DISABLED + EditableManPage.__init__(self, master, **cnf) + +# Alias +ManPage = ReadonlyManPage + +# usage: ManPage [manpage]; or ManPage [-f] file +# -f means that the file is nroff -man output run through ul -i +def main(): + # XXX This directory may be different on your system + MANDIR = '' + DEFAULTPAGE = 'Tcl' + formatted = 0 + if sys.argv[1:] and sys.argv[1] == '-f': + formatted = 1 + del sys.argv[1] + if sys.argv[1:]: + name = sys.argv[1] + else: + name = DEFAULTPAGE + if not formatted: + if name[-2:-1] != '.': + name = name + '.n' + name = os.path.join(MANDIR, name) + root = Tk() + root.minsize(1, 1) + manpage = ManPage(root, relief=SUNKEN, borderwidth=2) + manpage.pack(expand=1, fill=BOTH) + if formatted: + fp = open(name, 'r') + else: + fp = os.popen('nroff -man -c %s | ul -i' % name, 'r') + manpage.parsefile(fp) + root.mainloop() + +if __name__ == '__main__': + main() diff --git a/Demo/tkinter/guido/mbox.py b/Demo/tkinter/guido/mbox.py index 45c384e..754a312 100755 --- a/Demo/tkinter/guido/mbox.py +++ b/Demo/tkinter/guido/mbox.py @@ -3,17 +3,15 @@ # Scan MH folder, display results in window import os -import sys import re +import sys import getopt -import string -import mhlib - +import mailbox from tkinter import * from dialog import dialog -mailbox = os.environ['HOME'] + '/Mail' +MBOXPATH = os.environ['HOME'] + '/Mail' def main(): global root, tk, top, mid, bot @@ -38,8 +36,8 @@ def main(): # Initialize MH - mh = mhlib.MH() - mhf = mh.openfolder(folder) + mh = mailbox.MH(MBOXPATH) + mhf = mh.get_folder(folder) # Build widget hierarchy @@ -171,7 +169,7 @@ def open_folder(e=None): return i = sel[0] folder = folderbox.get(i) - mhf = mh.openfolder(folder) + mhf = mh.get_folder(folder) rescan() def open_message(e=None): @@ -189,11 +187,12 @@ def open_message(e=None): tk.call('update', 'idletasks') i = sel[0] line = scanbox.get(i) - if scanparser.match(line) >= 0: - num = string.atoi(scanparser.group(1)) - m = mhf.openmessage(num) + m = scanparser.match(line) + if m: + num = int(m.group(1)) + m = mhf.get_message(num) if viewer: viewer.destroy() - from MimeViewer import MimeViewer + from mimeviewer import MimeViewer viewer = MimeViewer(bot, '+%s/%d' % (folder, num), m) viewer.pack() viewer.show() @@ -212,9 +211,11 @@ def remove_message(e=None): todo = [] for i in sel: line = scanbox.get(i) - if scanparser.match(line) >= 0: - todo.append(string.atoi(scanparser.group(1))) - mhf.removemessages(todo) + m = scanparser.match(line) + if m: + toremove = int(m.group(1)) + todo.append(toremove) + mhf.remove(toremove) rescan() fixfocus(min(todo), itop) @@ -240,12 +241,13 @@ def refile_message(e=None): todo = [] for i in sel: line = scanbox.get(i) - if scanparser.match(line) >= 0: - todo.append(string.atoi(scanparser.group(1))) + m = scanparser.match(line) + if m: + todo.append(int(m.group(1))) if lastrefile != refileto or not tofolder: lastrefile = refileto tofolder = None - tofolder = mh.openfolder(lastrefile) + tofolder = mh.get_folder(lastrefile) mhf.refilemessages(todo, tofolder) rescan() fixfocus(min(todo), itop) @@ -254,18 +256,18 @@ def fixfocus(near, itop): n = scanbox.size() for i in range(n): line = scanbox.get(repr(i)) - if scanparser.match(line) >= 0: - num = string.atoi(scanparser.group(1)) + m = scanparser.match(line) + if m: + num = int(m.group(1)) if num >= near: break else: i = 'end' - scanbox.select_from(i) scanbox.yview(itop) def setfolders(): folderbox.delete(0, 'end') - for fn in mh.listallfolders(): + for fn in mh.list_folders(): folderbox.insert('end', fn) def rescan(): @@ -278,6 +280,7 @@ def rescan(): scanbox.insert('end', line) def scanfolder(folder = 'inbox', sequence = 'all'): - return [line[:-1] for line in os.popen('scan +%s %s' % (folder, sequence), 'r').readlines()] + return [line[:-1] for line in + os.popen('scan +%s %s' % (folder, sequence), 'r').readlines()] main() diff --git a/Demo/tkinter/guido/mimeviewer.py b/Demo/tkinter/guido/mimeviewer.py new file mode 100755 index 0000000..babed8f --- /dev/null +++ b/Demo/tkinter/guido/mimeviewer.py @@ -0,0 +1,159 @@ +#! /usr/bin/env python3 + +# View a single MIME multipart message. +# Display each part as a box. + +import os +import sys +import getopt +import mailbox +from tkinter import * +from tkinter.scrolledtext import ScrolledText + +MBOXPATH = os.environ['HOME'] + '/Mail' + +class Error(Exception): + pass + +def getcurrent(self): + """Return the current message. Raise Error when there is none.""" + seqs = self.get_sequences() + try: + return max(seqs['cur']) + except (ValueError, KeyError): + raise Error("no cur message") + + +class MimeViewer: + def __init__(self, parent, title, msg): + self.title = title + self.msg = msg + self.frame = Frame(parent, {'relief': 'raised', 'bd': 2}) + self.frame.packing = {'expand': 0, 'fill': 'both'} + self.button = Checkbutton(self.frame, + {'text': title, + 'command': self.toggle}) + self.button.pack({'anchor': 'w'}) + headertext = [] + for item in msg.items(): + headertext.append("%s: %s" % item) + headertext = '\n'.join(headertext) + height = countlines(headertext, 4) + if height: + self.htext = ScrolledText(self.frame, + {'height': height, + 'width': 80, + 'wrap': 'none', + 'relief': 'raised', + 'bd': 2}) + self.htext.packing = {'expand': 1, 'fill': 'both', + 'after': self.button} + self.htext.insert('end', headertext) + else: + self.htext = Frame(self.frame, + {'relief': 'raised', 'bd': 2}) + self.htext.packing = {'side': 'top', + 'ipady': 2, + 'fill': 'x', + 'after': self.button} + body = msg.get_payload() + if type(body) == str: + self.pad = None + height = countlines(body, 10) + if height: + self.btext = ScrolledText(self.frame, + {'height': height, + 'width': 80, + 'wrap': 'none', + 'relief': 'raised', + 'bd': 2}) + self.btext.packing = {'expand': 1, + 'fill': 'both'} + self.btext.insert('end', body) + else: + self.btext = None + self.parts = None + else: + self.pad = Frame(self.frame, + {'relief': 'flat', 'bd': 2}) + self.pad.packing = {'side': 'left', 'ipadx': 10, + 'fill': 'y', 'after': self.htext} + self.parts = [] + for i in range(len(body)): + p = MimeViewer(self.frame, + '%s.%d' % (title, i+1), + body[i]) + self.parts.append(p) + self.btext = None + self.collapsed = 1 + def pack(self): + self.frame.pack(self.frame.packing) + def destroy(self): + self.frame.destroy() + def show(self): + if self.collapsed: + self.button.invoke() + def toggle(self): + if self.collapsed: + self.explode() + else: + self.collapse() + def collapse(self): + self.collapsed = 1 + for comp in self.htext, self.btext, self.pad: + if comp: + comp.forget() + if self.parts: + for part in self.parts: + part.frame.forget() + self.frame.pack({'expand': 0}) + def explode(self): + self.collapsed = 0 + for comp in self.htext, self.btext, self.pad: + if comp: comp.pack(comp.packing) + if self.parts: + for part in self.parts: + part.pack() + self.frame.pack({'expand': 1}) + +def countlines(str, limit): + i = 0 + n = 0 + while n < limit: + i = str.find('\n', i) + if i < 0: break + n = n+1 + i = i+1 + return n + +def main(): + opts, args = getopt.getopt(sys.argv[1:], '') + for o, a in opts: + pass + message = None + folder = 'inbox' + for arg in args: + if arg[:1] == '+': + folder = arg[1:] + else: + message = int(arg) + + mh = mailbox.MH(MBOXPATH) + f = mh.get_folder(folder) + if message is None: + message = getcurrent(f) + m = mailbox.MHMessage(f.get(message)) + + root = Tk() + tk = root.tk + + top = MimeViewer(root, '+%s/%d' % (folder, message), m) + top.pack() + top.show() + + root.minsize(1, 1) + + tk.mainloop() + +if __name__ == '__main__': + main() diff --git a/Demo/tkinter/guido/rmt.py b/Demo/tkinter/guido/rmt.py index 7b3f700..350d60b 100755 --- a/Demo/tkinter/guido/rmt.py +++ b/Demo/tkinter/guido/rmt.py @@ -28,7 +28,7 @@ s = Scrollbar(f, relief=FLAT) s.pack(side=RIGHT, fill=Y) t = Text(f, relief=RAISED, borderwidth=2, yscrollcommand=s.set, setgrid=1) t.pack(side=LEFT, fill=BOTH, expand=1) -t.tag_config('bold', font='-Adobe-Courier-Bold-R-Normal-*-120-*') +t.tag_config('bold') s['command'] = t.yview root.title('Tk Remote Controller') diff --git a/Demo/tkinter/guido/shell_window.py b/Demo/tkinter/guido/shell_window.py new file mode 100644 index 0000000..c5a0401 --- /dev/null +++ b/Demo/tkinter/guido/shell_window.py @@ -0,0 +1,146 @@ +import os +import sys +from tkinter import * +from tkinter.scrolledtext import ScrolledText +from tkinter.dialog import Dialog +import signal + +BUFSIZE = 512 + +class ShellWindow(ScrolledText): + + def __init__(self, master=None, shell=None, **cnf): + if not shell: + try: + shell = os.environ['SHELL'] + except KeyError: + shell = '/bin/sh' + shell = shell + ' -i' + args = shell.split() + shell = args[0] + + ScrolledText.__init__(self, master, **cnf) + self.pos = '1.0' + self.bind('', self.inputhandler) + self.bind('', self.sigint) + self.bind('', self.sigterm) + self.bind('', self.sigkill) + self.bind('', self.sendeof) + + self.pid, self.fromchild, self.tochild = spawn(shell, args) + self.tk.createfilehandler(self.fromchild, READABLE, + self.outputhandler) + + def outputhandler(self, file, mask): + data = os.read(file, BUFSIZE).decode() + if not data: + self.tk.deletefilehandler(file) + pid, sts = os.waitpid(self.pid, 0) + print('pid', pid, 'status', sts) + self.pid = None + detail = sts>>8 + cause = sts & 0xff + if cause == 0: + msg = "exit status %d" % detail + else: + msg = "killed by signal %d" % (cause & 0x7f) + if cause & 0x80: + msg = msg + " -- core dumped" + Dialog(self.master, + text=msg, + title="Exit status", + bitmap='warning', + default=0, + strings=('OK',)) + return + self.insert(END, data) + self.pos = self.index("end - 1 char") + self.yview_pickplace(END) + + def inputhandler(self, *args): + if not self.pid: + self.no_process() + return "break" + self.insert(END, "\n") + line = self.get(self.pos, "end - 1 char") + self.pos = self.index(END) + os.write(self.tochild, line.encode()) + return "break" + + def sendeof(self, *args): + if not self.pid: + self.no_process() + return "break" + os.close(self.tochild) + return "break" + + def sendsig(self, sig): + if not self.pid: + self.no_process() + return "break" + os.kill(self.pid, sig) + return "break" + + def sigint(self, *args): + return self.sendsig(signal.SIGINT) + + def sigquit(self, *args): + return self.sendsig(signal.SIGQUIT) + + def sigterm(self, *args): + return self.sendsig(signal.SIGTERM) + + def sigkill(self, *args): + return self.sendsig(signal.SIGKILL) + + def no_process(self): + Dialog(self.master, + text="No active process", + title="No process", + bitmap='error', + default=0, + strings=('OK',)) + +MAXFD = 100 # Max number of file descriptors (os.getdtablesize()???) + +def spawn(prog, args): + p2cread, p2cwrite = os.pipe() + c2pread, c2pwrite = os.pipe() + pid = os.fork() + if pid == 0: + # Child + for i in 0, 1, 2: + try: + os.close(i) + except os.error: + pass + if os.dup(p2cread) != 0: + sys.stderr.write('popen2: bad read dup\n') + if os.dup(c2pwrite) != 1: + sys.stderr.write('popen2: bad write dup\n') + if os.dup(c2pwrite) != 2: + sys.stderr.write('popen2: bad write dup\n') + os.closerange(3, MAXFD) + try: + os.execvp(prog, args) + finally: + sys.stderr.write('execvp failed\n') + os._exit(1) + os.close(p2cread) + os.close(c2pwrite) + return pid, c2pread, p2cwrite + +def test(): + shell = ' '.join(sys.argv[1: ]) + root = Tk() + root.minsize(1, 1) + if shell: + w = ShellWindow(root, shell=shell) + else: + w = ShellWindow(root) + w.pack(expand=1, fill=BOTH) + w.focus_set() + w.tk.mainloop() + +if __name__ == '__main__': + test() diff --git a/Demo/tkinter/guido/solitaire.py b/Demo/tkinter/guido/solitaire.py index b2a2a66..43106e1 100755 --- a/Demo/tkinter/guido/solitaire.py +++ b/Demo/tkinter/guido/solitaire.py @@ -22,20 +22,10 @@ know! # Imports -import math import random from tkinter import * -from Canvas import Rectangle, CanvasText, Group, Window - - -# Fix a bug in Canvas.Group as distributed in Python 1.4. The -# distributed bind() method is broken. Rather than asking you to fix -# the source, we fix it here by deriving a subclass: - -class Group(Group): - def bind(self, sequence=None, command=None): - return self.canvas.tag_bind(self.id, sequence, command) +from canvasevents import Group # Constants determining the size and lay-out of cards and stacks. We @@ -165,20 +155,22 @@ class Card: self.face_shown = 0 self.x = self.y = 0 + self.canvas = canvas self.group = Group(canvas) text = "%s %s" % (VALNAMES[value], suit) - self.__text = CanvasText(canvas, CARDWIDTH//2, 0, - anchor=N, fill=self.color, text=text) + self.__text = canvas.create_text(CARDWIDTH // 2, 0, anchor=N, + fill=self.color, text=text) self.group.addtag_withtag(self.__text) - self.__rect = Rectangle(canvas, 0, 0, CARDWIDTH, CARDHEIGHT, - outline='black', fill='white') + self.__rect = canvas.create_rectangle(0, 0, CARDWIDTH, CARDHEIGHT, + outline='black', fill='white') self.group.addtag_withtag(self.__rect) - self.__back = Rectangle(canvas, MARGIN, MARGIN, - CARDWIDTH-MARGIN, CARDHEIGHT-MARGIN, - outline='black', fill='blue') + self.__back = canvas.create_rectangle(MARGIN, MARGIN, + CARDWIDTH - MARGIN, + CARDHEIGHT - MARGIN, + outline='black', fill='blue') self.group.addtag_withtag(self.__back) def __repr__(self): @@ -202,15 +194,15 @@ class Card: def showface(self): """Turn the card's face up.""" self.tkraise() - self.__rect.tkraise() - self.__text.tkraise() + self.canvas.tag_raise(self.__rect) + self.canvas.tag_raise(self.__text) self.face_shown = 1 def showback(self): """Turn the card's face down.""" self.tkraise() - self.__rect.tkraise() - self.__back.tkraise() + self.canvas.tag_raise(self.__rect) + self.canvas.tag_raise(self.__back) self.face_shown = 0 @@ -400,10 +392,9 @@ class Deck(Stack): """ def makebottom(self): - bottom = Rectangle(self.game.canvas, - self.x, self.y, - self.x+CARDWIDTH, self.y+CARDHEIGHT, - outline='black', fill=BACKGROUND) + bottom = self.game.canvas.create_rectangle(self.x, self.y, + self.x + CARDWIDTH, self.y + CARDHEIGHT, outline='black', + fill=BACKGROUND) self.group.addtag_withtag(bottom) def fill(self): @@ -435,7 +426,7 @@ class Deck(Stack): def randperm(n): """Function returning a random permutation of range(n).""" - r = range(n) + r = list(range(n)) x = [] while r: i = random.choice(r) @@ -478,10 +469,8 @@ class OpenStack(Stack): class SuitStack(OpenStack): def makebottom(self): - bottom = Rectangle(self.game.canvas, - self.x, self.y, - self.x+CARDWIDTH, self.y+CARDHEIGHT, - outline='black', fill='') + bottom = self.game.canvas.create_rectangle(self.x, self.y, + self.x + CARDWIDTH, self.y + CARDHEIGHT, outline='black', fill='') def userclickhandler(self): pass @@ -540,8 +529,8 @@ class Solitaire: background=BACKGROUND, activebackground="green", command=self.deal) - Window(self.canvas, MARGIN, 3*YSPACING + 20, - window=self.dealbutton, anchor=SW) + self.canvas.create_window(MARGIN, 3 * YSPACING + 20, + window=self.dealbutton, anchor=SW) x = MARGIN y = MARGIN diff --git a/Demo/tkinter/guido/sortvisu.py b/Demo/tkinter/guido/sortvisu.py index 0c71fc9..326baec 100644 --- a/Demo/tkinter/guido/sortvisu.py +++ b/Demo/tkinter/guido/sortvisu.py @@ -18,9 +18,7 @@ stand-alone application. """ - from tkinter import * -from Canvas import Line, Rectangle import random @@ -31,6 +29,9 @@ WIDTH = 6 class Array: + class Cancelled(BaseException): + pass + def __init__(self, master, data=None): self.master = master self.frame = Frame(self.master) @@ -41,9 +42,9 @@ class Array: self.canvas.pack() self.report = Label(self.frame) self.report.pack() - self.left = Line(self.canvas, 0, 0, 0, 0) - self.right = Line(self.canvas, 0, 0, 0, 0) - self.pivot = Line(self.canvas, 0, 0, 0, 0) + self.left = self.canvas.create_line(0, 0, 0, 0) + self.right = self.canvas.create_line(0, 0, 0, 0) + self.pivot = self.canvas.create_line(0, 0, 0, 0) self.items = [] self.size = self.maxvalue = 0 if data: @@ -82,8 +83,6 @@ class Array: if self.in_mainloop: self.master.quit() - Cancelled = "Array.Cancelled" # Exception - def wait(self, msecs): if self.speed == "fastest": msecs = 0 @@ -110,15 +109,15 @@ class Array: for i in range(self.size): item = self.items[i] if first <= i < last: - item.item.config(fill='red') + self.canvas.itemconfig(item, fill='red') else: - item.item.config(fill='orange') + self.canvas.itemconfig(item, fill='orange') self.hide_left_right_pivot() def hide_partition(self): for i in range(self.size): item = self.items[i] - item.item.config(fill='red') + self.canvas.itemconfig(item, fill='red') self.hide_left_right_pivot() def show_left(self, left): @@ -127,7 +126,7 @@ class Array: return x1, y1, x2, y2 = self.items[left].position() ## top, bot = HIRO - self.left.coords([(x1-2, 0), (x1-2, 9999)]) + self.canvas.coords(self.left, (x1 - 2, 0, x1 - 2, 9999)) self.master.update() def show_right(self, right): @@ -135,7 +134,7 @@ class Array: self.hide_right() return x1, y1, x2, y2 = self.items[right].position() - self.right.coords(((x2+2, 0), (x2+2, 9999))) + self.canvas.coords(self.right, (x2 + 2, 0, x2 + 2, 9999)) self.master.update() def hide_left_right_pivot(self): @@ -144,17 +143,17 @@ class Array: self.hide_pivot() def hide_left(self): - self.left.coords(((0, 0), (0, 0))) + self.canvas.coords(self.left, (0, 0, 0, 0)) def hide_right(self): - self.right.coords(((0, 0), (0, 0))) + self.canvas.coords(self.right, (0, 0, 0, 0)) def show_pivot(self, pivot): x1, y1, x2, y2 = self.items[pivot].position() - self.pivot.coords(((0, y1-2), (9999, y1-2))) + self.canvas.coords(self.pivot, (0, y1 - 2, 9999, y1 - 2)) def hide_pivot(self): - self.pivot.coords(((0, 0), (0, 0))) + self.canvas.coords(self.pivot, (0, 0, 0, 0)) def swap(self, i, j): if i == j: return @@ -199,28 +198,30 @@ class ArrayItem: self.array = array self.index = index self.value = value + self.canvas = array.canvas x1, y1, x2, y2 = self.position() - self.item = Rectangle(array.canvas, x1, y1, x2, y2, - fill='red', outline='black', width=1) - self.item.bind('', self.mouse_down) - self.item.bind('', self.mouse_move) - self.item.bind('', self.mouse_up) + self.item_id = array.canvas.create_rectangle(x1, y1, x2, y2, + fill='red', outline='black', width=1) + self.canvas.tag_bind(self.item_id, '', self.mouse_down) + self.canvas.tag_bind(self.item_id, '', self.mouse_move) + self.canvas.tag_bind(self.item_id, '', self.mouse_up) def delete(self): - item = self.item + item_id = self.item_id self.array = None - self.item = None - item.delete() + self.item_id = None + self.canvas.delete(item_id) def mouse_down(self, event): self.lastx = event.x self.lasty = event.y self.origx = event.x self.origy = event.y - self.item.tkraise() + self.canvas.tag_raise(self.item_id) def mouse_move(self, event): - self.item.move(event.x - self.lastx, event.y - self.lasty) + self.canvas.move(self.item_id, + event.x - self.lastx, event.y - self.lasty) self.lastx = event.x self.lasty = event.y @@ -235,7 +236,7 @@ class ArrayItem: self.array.items[here], self.array.items[i] = other, self self.index = i x1, y1, x2, y2 = self.position() - self.item.coords(((x1, y1), (x2, y2))) + self.canvas.coords(self.item_id, (x1, y1, x2, y2)) other.setindex(here) def setindex(self, index): @@ -247,9 +248,9 @@ class ArrayItem: self.index = index newpts = self.position() trajectory = interpolate(oldpts, newpts, nsteps) - self.item.tkraise() + self.canvas.tag_raise(self.item_id) for pts in trajectory: - self.item.coords((pts[:2], pts[2:])) + self.canvas.coords(self.item_id, pts) self.array.wait(50) def swapwith(self, other): @@ -262,61 +263,63 @@ class ArrayItem: self.index, other.index = other.index, self.index mynewpts = self.position() othernewpts = other.position() - myfill = self.item['fill'] - otherfill = other.item['fill'] - self.item.config(fill='green') - other.item.config(fill='yellow') + myfill = self.canvas.itemcget(self.item_id, 'fill') + otherfill = self.canvas.itemcget(other.item_id, 'fill') + self.canvas.itemconfig(self.item_id, fill='green') + self.canvas.itemconfig(other.item_id, fill='yellow') self.array.master.update() if self.array.speed == "single-step": - self.item.coords((mynewpts[:2], mynewpts[2:])) - other.item.coords((othernewpts[:2], othernewpts[2:])) + self.canvas.coords(self.item_id, mynewpts) + self.canvas.coords(other.item_id, othernewpts) self.array.master.update() - self.item.config(fill=myfill) - other.item.config(fill=otherfill) + self.canvas.itemconfig(self.item_id, fill=myfill) + self.canvas.itemconfig(other.item_id, fill=otherfill) self.array.wait(0) return mytrajectory = interpolate(myoldpts, mynewpts, nsteps) othertrajectory = interpolate(otheroldpts, othernewpts, nsteps) if self.value > other.value: - self.item.tkraise() - other.item.tkraise() + self.canvas.tag_raise(self.item_id) + self.canvas.tag_raise(other.item_id) else: - other.item.tkraise() - self.item.tkraise() + self.canvas.tag_raise(other.item_id) + self.canvas.tag_raise(self.item_id) try: for i in range(len(mytrajectory)): mypts = mytrajectory[i] otherpts = othertrajectory[i] - self.item.coords((mypts[:2], mypts[2:])) - other.item.coords((otherpts[:2], otherpts[2:])) + self.canvas.coords(self.item_id, mypts) + self.canvas.coords(other.item_id, otherpts) self.array.wait(50) finally: mypts = mytrajectory[-1] otherpts = othertrajectory[-1] - self.item.coords((mypts[:2], mypts[2:])) - other.item.coords((otherpts[:2], otherpts[2:])) - self.item.config(fill=myfill) - other.item.config(fill=otherfill) + self.canvas.coords(self.item_id, mypts) + self.canvas.coords(other.item_id, otherpts) + self.canvas.itemconfig(self.item_id, fill=myfill) + self.canvas.itemconfig(other.item_id, fill=otherfill) def compareto(self, other): - myfill = self.item['fill'] - otherfill = other.item['fill'] - outcome = cmp(self.value, other.value) - if outcome < 0: + myfill = self.canvas.itemcget(self.item_id, 'fill') + otherfill = self.canvas.itemcget(other.item_id, 'fill') + if self.value < other.value: myflash = 'white' otherflash = 'black' - elif outcome > 0: + outcome = -1 + elif self.value > other.value: myflash = 'black' otherflash = 'white' + outcome = 1 else: myflash = otherflash = 'grey' + outcome = 0 try: - self.item.config(fill=myflash) - other.item.config(fill=otherflash) + self.canvas.itemconfig(self.item_id, fill=myflash) + self.canvas.itemconfig(other.item_id, fill=otherflash) self.array.wait(500) finally: - self.item.config(fill=myfill) - other.item.config(fill=otherfill) + self.canvas.itemconfig(self.item_id, fill=myfill) + self.canvas.itemconfig(other.item_id, fill=otherfill) return outcome def position(self): @@ -429,7 +432,7 @@ def quicksort(array): j = j-1 continue array.message("Choosing pivot") - j, i, k = first, (first+last)//2, last-1 + j, i, k = first, (first+last) // 2, last-1 if array.compare(k, i) < 0: array.swap(k, i) if array.compare(k, j) < 0: @@ -519,7 +522,7 @@ class SortDemo: self.v_size = MyIntVar(self.master, self) self.v_size.set(size) - sizes = [1, 2, 3, 4] + range(5, 55, 5) + sizes = [1, 2, 3, 4] + list(range(5, 55, 5)) if self.size not in sizes: sizes.append(self.size) sizes.sort() diff --git a/Demo/tkinter/guido/ss1.py b/Demo/tkinter/guido/ss1.py index a6c8c21..8b07489 100644 --- a/Demo/tkinter/guido/ss1.py +++ b/Demo/tkinter/guido/ss1.py @@ -3,7 +3,7 @@ import os import re import sys -import cgi +import html from xml.parsers import expat LEFT, CENTER, RIGHT = "LEFT", "CENTER", "RIGHT" @@ -201,7 +201,7 @@ class Sheet: if hasattr(cell, 'xml'): cellxml = cell.xml() else: - cellxml = '%s' % cgi.escape(cell) + cellxml = '%s' % html.escape(cell) out.append('\n %s\n' % (y, x, cellxml)) out.append('') @@ -216,7 +216,7 @@ class Sheet: f.close() def load(self, filename): - f = open(filename, 'r') + f = open(filename, 'rb') SheetParser(self).parsefile(f) f.close() @@ -382,7 +382,7 @@ class StringCell(BaseCell): return s % ( align2xml[self.alignment], self.fmt, - cgi.escape(self.text)) + html.escape(self.text)) class FormulaCell(BaseCell): diff --git a/Demo/tkinter/guido/svkill.py b/Demo/tkinter/guido/svkill.py index 0dd9f95..e63a32b 100755 --- a/Demo/tkinter/guido/svkill.py +++ b/Demo/tkinter/guido/svkill.py @@ -7,8 +7,6 @@ from tkinter import * if TkVersion < 4.0: raise ImportError("This version of svkill requires Tk 4.0 or later") -from string import splitfields -from string import split import subprocess import os @@ -40,14 +38,14 @@ class Kill(Frame): ] def kill(self, selected): c = self.format_list[self.format.get()][2] - pid = split(selected)[c] + pid = selected.split()[c] os.system('kill -9 ' + pid) self.do_update() def do_update(self): format = self.format_list[self.format.get()][1] view = self.view_list[self.view.get()][1] s = subprocess.getoutput('ps %s %s' % (view, format)) - list = splitfields(s, '\n') + list = s.split('\n') self.header.set(list[0] + ' ') del list[0] self.frame.list.delete(0, AtEnd()) @@ -97,14 +95,12 @@ class Kill(Frame): self.header = StringVar(self) self.frame.label = Label( self.frame, relief=FLAT, anchor=NW, borderwidth=0, - font='*-Courier-Bold-R-Normal-*-120-*', textvariable=self.header) self.frame.label.pack(fill=Y, anchor=W) self.frame.vscroll = Scrollbar(self.frame, orient=VERTICAL) self.frame.list = Listbox( self.frame, relief=SUNKEN, - font='*-Courier-Medium-R-Normal-*-120-*', width=40, height=10, selectbackground='#eed5b7', selectborderwidth=0, diff --git a/Demo/tkinter/guido/tkman.py b/Demo/tkinter/guido/tkman.py index 52b6d03..1baed88 100755 --- a/Demo/tkinter/guido/tkman.py +++ b/Demo/tkinter/guido/tkman.py @@ -2,15 +2,15 @@ # Tk man page browser -- currently only shows the Tcl/Tk man pages -import sys import os -import string import re +import sys from tkinter import * -from ManPage import ManPage -MANNDIRLIST = ['/depot/sundry/man/mann','/usr/local/man/mann'] -MAN3DIRLIST = ['/depot/sundry/man/man3','/usr/local/man/man3'] +from manpage import ManPage + +MANNDIRLIST = ['/usr/local/man/mann', '/usr/share/man/mann'] +MAN3DIRLIST = ['/usr/local/man/man3', '/usr/share/man/man3'] foundmanndir = 0 for dir in MANNDIRLIST: @@ -197,7 +197,7 @@ class SelectionBox: def show_page(self, name): file = '%s/%s.?' % (self.chaptervar.get(), name) - fp = os.popen('nroff -man %s | ul -i' % file, 'r') + fp = os.popen('nroff -man -c %s | ul -i' % file, 'r') self.text.kill() self.title['text'] = name self.text.parsefile(fp) @@ -221,9 +221,9 @@ class SelectionBox: print('Regex error:', msg) return here = self.text.index(AtInsert()) - lineno = string.atoi(here[:string.find(here, '.')]) + lineno = int(here[:here.find('.')]) end = self.text.index(AtEnd()) - endlineno = string.atoi(end[:string.find(end, '.')]) + endlineno = int(end[:end.find('.')]) wraplineno = lineno found = 0 while 1: @@ -237,9 +237,9 @@ class SelectionBox: line = self.text.get('%d.0 linestart' % lineno, '%d.0 lineend' % lineno) i = prog.search(line) - if i >= 0: + if i: found = 1 - n = max(1, len(prog.group(0))) + n = max(1, len(i.group(0))) try: self.text.tag_remove('sel', AtSelFirst(), @@ -247,10 +247,10 @@ class SelectionBox: except TclError: pass self.text.tag_add('sel', - '%d.%d' % (lineno, i), - '%d.%d' % (lineno, i+n)) + '%d.%d' % (lineno, i.start()), + '%d.%d' % (lineno, i.start()+n)) self.text.mark_set(AtInsert(), - '%d.%d' % (lineno, i)) + '%d.%d' % (lineno, i.start())) self.text.yview_pickplace(AtInsert()) break if not found: diff --git a/Demo/tkinter/guido/wish.py b/Demo/tkinter/guido/wish.py index bebab1e..332501d 100755 --- a/Demo/tkinter/guido/wish.py +++ b/Demo/tkinter/guido/wish.py @@ -4,21 +4,25 @@ import _tkinter import os import sys -tk = _tkinter.create(os.environ['DISPLAY'], 'wish', 'Tk', 1) +tk = _tkinter.create(os.environ['DISPLAY'], 'wish', 'Tk', 1, 1) tk.call('update') cmd = '' -while 1: - if cmd: prompt = '' - else: prompt = '% ' +while True: + if cmd: + prompt = '' + else: + prompt = '% ' try: sys.stdout.write(prompt) sys.stdout.flush() line = sys.stdin.readline() + if not line: + break except EOFError: break - cmd = cmd + (line + '\n') + cmd += line if tk.getboolean(tk.call('info', 'complete', cmd)): tk.record(line) try: diff --git a/Demo/tkinter/matt/bind-w-mult-calls-p-type.py b/Demo/tkinter/matt/bind-w-mult-calls-p-type.py index af0ec81..0da7c37 100644 --- a/Demo/tkinter/matt/bind-w-mult-calls-p-type.py +++ b/Demo/tkinter/matt/bind-w-mult-calls-p-type.py @@ -1,5 +1,4 @@ from tkinter import * -import string # This program shows how to use a simple type-in box diff --git a/Demo/tkinter/matt/entry-with-shared-variable.py b/Demo/tkinter/matt/entry-with-shared-variable.py index 473a596..7d93da7 100644 --- a/Demo/tkinter/matt/entry-with-shared-variable.py +++ b/Demo/tkinter/matt/entry-with-shared-variable.py @@ -1,5 +1,4 @@ from tkinter import * -import string # This program shows how to make a typein box shadow a program variable. @@ -35,7 +34,7 @@ class App(Frame): # because it's being looked at by the entry widget, changing # the variable changes the entry widget display automatically. # the strange get/set operators are clunky, true... - str = string.upper(self.contents.get()) + str = self.contents.get().upper() self.contents.set(str) def print_contents(self, event): diff --git a/Demo/tkinter/matt/pong-demo-1.py b/Demo/tkinter/matt/pong-demo-1.py index 09f9f2e..82a5dc0 100644 --- a/Demo/tkinter/matt/pong-demo-1.py +++ b/Demo/tkinter/matt/pong-demo-1.py @@ -1,7 +1,5 @@ from tkinter import * -import string - class Pong(Frame): def createWidgets(self): diff --git a/Demo/tkinter/matt/printing-coords-of-items.py b/Demo/tkinter/matt/printing-coords-of-items.py index 26a4649..771a60d 100644 --- a/Demo/tkinter/matt/printing-coords-of-items.py +++ b/Demo/tkinter/matt/printing-coords-of-items.py @@ -35,7 +35,7 @@ class Test(Frame): # the "current" tag is applied to the object the cursor is over. # this happens automatically. self.draw.itemconfig(CURRENT, fill="red") - print(self.draw.coords(CURRENT)) + print(list(self.draw.coords(CURRENT))) def mouseLeave(self, event): # the "current" tag is applied to the object the cursor is over. diff --git a/Doc/library/locale.rst b/Doc/library/locale.rst index 601c949..9581186 100644 --- a/Doc/library/locale.rst +++ b/Doc/library/locale.rst @@ -529,7 +529,7 @@ catalogs, and the C library's search algorithms for locating message catalogs. Python applications should normally find no need to invoke these functions, and should use :mod:`gettext` instead. A known exception to this rule are -applications that link use additional C libraries which internally invoke +applications that link with additional C libraries which internally invoke :cfunc:`gettext` or :func:`dcgettext`. For these applications, it may be necessary to bind the text domain, so that the libraries can properly locate their message catalogs. diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index c4ee87e..f726a02 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -792,9 +792,9 @@ For example: >>> a.send([1, 'hello', None]) >>> b.recv() [1, 'hello', None] - >>> b.send_bytes('thank you') + >>> b.send_bytes(b'thank you') >>> a.recv_bytes() - 'thank you' + b'thank you' >>> import array >>> arr1 = array.array('i', range(5)) >>> arr2 = array.array('i', [0] * 10) diff --git a/Doc/library/re.rst b/Doc/library/re.rst index 448bcb7..49c241d 100644 --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -229,7 +229,7 @@ The special characters are: undefined. ``(?:...)`` - A non-grouping version of regular parentheses. Matches whatever regular + A non-capturing version of regular parentheses. Matches whatever regular expression is inside the parentheses, but the substring matched by the group *cannot* be retrieved after performing a match or referenced later in the pattern. diff --git a/Doc/library/string.rst b/Doc/library/string.rst index 409f461..a5d11de 100644 --- a/Doc/library/string.rst +++ b/Doc/library/string.rst @@ -114,7 +114,7 @@ implementation as the built-in :meth:`format` method. Loop over the format_string and return an iterable of tuples (*literal_text*, *field_name*, *format_spec*, *conversion*). This is used - by :meth:`vformat` to break the string in to either literal text, or + by :meth:`vformat` to break the string into either literal text, or replacement fields. The values in the tuple conceptually represent a span of literal text diff --git a/Doc/library/warnings.rst b/Doc/library/warnings.rst index 36d47ad..e62be55 100644 --- a/Doc/library/warnings.rst +++ b/Doc/library/warnings.rst @@ -159,6 +159,20 @@ ImportWarning can also be enabled explicitly in Python code using:: warnings.simplefilter('default', ImportWarning) +Default Warning Filters +~~~~~~~~~~~~~~~~~~~~~~~ + +By default, Python installs several warning filters, which can be overridden by +the command-line options passed to :option:`-W` and calls to +:func:`filterwarnings`. + +* :exc:`PendingDeprecationWarning`, and :exc:`ImportWarning` are ignored. + +* :exc:`BytesWarning` is ignored unless the :option:`-b` option is given once or + twice; in this case this warning is either printed (``-b``) or turned into an + exception (``-bb``). + + .. _warning-suppress: Temporarily Suppressing Warnings diff --git a/Doc/tools/sphinxext/susp-ignored.csv b/Doc/tools/sphinxext/susp-ignored.csv index dffd32c..4d4db94 100644 --- a/Doc/tools/sphinxext/susp-ignored.csv +++ b/Doc/tools/sphinxext/susp-ignored.csv @@ -207,14 +207,14 @@ library/nntplib,272,:bytes,:bytes library/nntplib,272,:lines,:lines library/nntplib,272,:lines,"['xref', 'from', ':lines', ':bytes', 'references', 'date', 'message-id', 'subject']" library/nntplib,272,:bytes,"['xref', 'from', ':lines', ':bytes', 'references', 'date', 'message-id', 'subject']" -library/pickle,567,:memory,"conn = sqlite3.connect("":memory:"")" -library/profile,293,:lineno,"(sort by filename:lineno)," -library/socket,261,::,"(10, 1, 6, '', ('2001:888:2000:d::a2', 80, 0, 0))]" +library/pickle,,:memory,"conn = sqlite3.connect("":memory:"")" +library/profile,,:lineno,"(sort by filename:lineno)," +library/socket,,::,"(10, 1, 6, '', ('2001:888:2000:d::a2', 80, 0, 0))]" library/stdtypes,1026,:end,s[start:end] library/stdtypes,1195,:end,s[start:end] -library/urllib.request,64,:close,Connection:close -library/urllib.request,901,:password,"""joe:password@python.org""" -library/urllib.request,1064,:lang,"xmlns=""http://www.w3.org/1999/xhtml"" xml:lang=""en"" lang=""en"">\n\n\n" +library/urllib.request,,:close,Connection:close +library/urllib.request,,:password,"""joe:password@python.org""" +library/urllib.request,,:lang,"xmlns=""http://www.w3.org/1999/xhtml"" xml:lang=""en"" lang=""en"">\n\n\n" library/xmlrpc.client,103,:pass,http://user:pass@host:port/path library/xmlrpc.client,103,:port,http://user:pass@host:port/path library/xmlrpc.client,103,:pass,user:pass diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 987a425..38ad140 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -635,7 +635,7 @@ else: sys.stdout.write("\nSSLError is %s\n" % x.args[1]) except socket.error as x: if support.verbose: - sys.stdout.write("\nsocket.error is %s\n" % x[1]) + sys.stdout.write("\nsocket.error is %s\n" % x.args[1]) else: self.fail("Use of invalid cert should have failed!") finally: diff --git a/Misc/developers.txt b/Misc/developers.txt index 7ae68ca..0c34613 100644 --- a/Misc/developers.txt +++ b/Misc/developers.txt @@ -23,6 +23,9 @@ transliteration too. Permissions History ------------------- +- David Malcolm was given commit access on Oct 27 2010 by GFB, + at recommendation by Antoine Pitrou and Raymond Hettinger. + - Tal Einat was given commit access on Oct 4 2010 by MvL, for improving IDLE. diff --git a/Parser/tokenizer.h b/Parser/tokenizer.h index c153cbf..6c1742f 100644 --- a/Parser/tokenizer.h +++ b/Parser/tokenizer.h @@ -15,7 +15,7 @@ extern "C" { enum decoding_state { STATE_INIT, STATE_RAW, - STATE_NORMAL, /* have a codec associated with input */ + STATE_NORMAL /* have a codec associated with input */ }; /* Tokenizer state */ diff --git a/Tools/pynche/pyColorChooser.py b/Tools/pynche/pyColorChooser.py index 9507847..3286047 100644 --- a/Tools/pynche/pyColorChooser.py +++ b/Tools/pynche/pyColorChooser.py @@ -31,7 +31,7 @@ class Chooser: if dbfile != self.__databasefile: colordb = ColorDB.get_colordb(dbfile) if not self.__master: - from Tkinter import Tk + from tkinter import Tk self.__master = Tk() if not self.__pw: self.__pw, self.__sb = \ @@ -92,7 +92,7 @@ def save(): # test stuff if __name__ == '__main__': - from Tkinter import * + from tkinter import * class Tester: def __init__(self): diff --git a/Tools/ssl/get-remote-certificate.py b/Tools/ssl/get-remote-certificate.py index b63428a..ab851ef 100644 --- a/Tools/ssl/get-remote-certificate.py +++ b/Tools/ssl/get-remote-certificate.py @@ -6,11 +6,14 @@ # # By Bill Janssen. +import re +import os +import ssl import sys +import tempfile -def fetch_server_certificate (host, port): - import re, tempfile, os, ssl +def fetch_server_certificate (host, port): def subproc(cmd): from subprocess import Popen, PIPE, STDOUT @@ -20,15 +23,15 @@ def fetch_server_certificate (host, port): return status, output def strip_to_x509_cert(certfile_contents, outfile=None): - m = re.search(r"^([-]+BEGIN CERTIFICATE[-]+[\r]*\n" - r".*[\r]*^[-]+END CERTIFICATE[-]+)$", + m = re.search(br"^([-]+BEGIN CERTIFICATE[-]+[\r]*\n" + br".*[\r]*^[-]+END CERTIFICATE[-]+)$", certfile_contents, re.MULTILINE | re.DOTALL) if not m: return None else: tn = tempfile.mktemp() - fp = open(tn, "w") - fp.write(m.group(1) + "\n") + fp = open(tn, "wb") + fp.write(m.group(1) + b"\n") fp.close() try: tn2 = (outfile or tempfile.mktemp()) @@ -67,6 +70,7 @@ def fetch_server_certificate (host, port): (host, port)) return certtext + if __name__ == "__main__": if len(sys.argv) < 2: sys.stderr.write( @@ -75,5 +79,5 @@ if __name__ == "__main__": sys.exit(1) for arg in sys.argv[1:]: host, port = arg.split(":") - sys.stdout.write(fetch_server_certificate(host, int(port))) + sys.stdout.buffer.write(fetch_server_certificate(host, int(port))) sys.exit(0) -- cgit v0.12