summaryrefslogtreecommitdiffstats
path: root/Tools
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2022-10-03 15:09:02 (GMT)
committerGitHub <noreply@github.com>2022-10-03 15:09:02 (GMT)
commit64fe34371722d90448e0d1a0c04e7ed106f5f70a (patch)
tree3469166def39cfc26dfdce75062fddd5ab0d1d98 /Tools
parente6f9ec5c031bd996fcd5f463c407beef0b743b49 (diff)
downloadcpython-64fe34371722d90448e0d1a0c04e7ed106f5f70a.zip
cpython-64fe34371722d90448e0d1a0c04e7ed106f5f70a.tar.gz
cpython-64fe34371722d90448e0d1a0c04e7ed106f5f70a.tar.bz2
gh-97681: Remove Tools/demo/ directory (#97682)
Remove the Tools/demo/ directory which contained old demo scripts. A copy can be found in the old-demos project: https://github.com/gvanrossum/old-demos Remove the following old demo scripts: * beer.py * eiffel.py * hanoi.py * life.py * markov.py * mcast.py * queens.py * redemo.py * rpython.py * rpythond.py * sortvisu.py * spreadsheet.py * vector.py Changes: * Remove a reference to the redemo.py script in the regex howto documentation. * Remove a reference to the removed Tools/demo/ directory in the curses documentation. * Update PC/layout/ to remove the reference to Tools/demo/ directory.
Diffstat (limited to 'Tools')
-rw-r--r--Tools/README2
-rw-r--r--Tools/demo/README16
-rwxr-xr-xTools/demo/beer.py25
-rwxr-xr-xTools/demo/eiffel.py146
-rwxr-xr-xTools/demo/hanoi.py154
-rwxr-xr-xTools/demo/life.py262
-rwxr-xr-xTools/demo/markov.py125
-rwxr-xr-xTools/demo/mcast.py82
-rwxr-xr-xTools/demo/queens.py85
-rwxr-xr-xTools/demo/redemo.py171
-rwxr-xr-xTools/demo/rpython.py37
-rwxr-xr-xTools/demo/rpythond.py58
-rwxr-xr-xTools/demo/sortvisu.py635
-rwxr-xr-xTools/demo/spreadsheet.py829
-rwxr-xr-xTools/demo/vector.py94
15 files changed, 0 insertions, 2721 deletions
diff --git a/Tools/README b/Tools/README
index f8bfbc0..04612b8 100644
--- a/Tools/README
+++ b/Tools/README
@@ -5,8 +5,6 @@ buildbot Batchfiles for running on Windows buildbot workers.
ccbench A Python threads-based concurrency benchmark. (*)
-demo Several Python programming demos.
-
freeze Create a stand-alone executable from a Python program.
gdb Python code to be run inside gdb, to make it easier to
diff --git a/Tools/demo/README b/Tools/demo/README
deleted file mode 100644
index 9fccb97..0000000
--- a/Tools/demo/README
+++ /dev/null
@@ -1,16 +0,0 @@
-This directory contains a collection of demonstration scripts for
-various aspects of Python programming.
-
-beer.py Well-known programming example: Bottles of beer.
-eiffel.py Python advanced magic: A metaclass for Eiffel post/preconditions.
-hanoi.py Well-known programming example: Towers of Hanoi.
-life.py Curses programming: Simple game-of-life.
-markov.py Algorithms: Markov chain simulation.
-mcast.py Network programming: Send and receive UDP multicast packets.
-queens.py Well-known programming example: N-Queens problem.
-redemo.py Regular Expressions: GUI script to test regexes.
-rpython.py Network programming: Small client for remote code execution.
-rpythond.py Network programming: Small server for remote code execution.
-sortvisu.py GUI programming: Visualization of different sort algorithms.
-spreadsheet.py GUI/Application programming: A simple spreadsheet application.
-vector.py Python basics: A vector class demonstrating special methods.
diff --git a/Tools/demo/beer.py b/Tools/demo/beer.py
deleted file mode 100755
index af58380..0000000
--- a/Tools/demo/beer.py
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-A Python version of the classic "bottles of beer on the wall" programming
-example.
-
-By Guido van Rossum, demystified after a version by Fredrik Lundh.
-"""
-
-import sys
-
-n = 100
-if sys.argv[1:]:
- n = int(sys.argv[1])
-
-def bottle(n):
- if n == 0: return "no more bottles of beer"
- if n == 1: return "one bottle of beer"
- return str(n) + " bottles of beer"
-
-for i in range(n, 0, -1):
- print(bottle(i), "on the wall,")
- print(bottle(i) + ".")
- print("Take one down, pass it around,")
- print(bottle(i-1), "on the wall.")
diff --git a/Tools/demo/eiffel.py b/Tools/demo/eiffel.py
deleted file mode 100755
index a76c232..0000000
--- a/Tools/demo/eiffel.py
+++ /dev/null
@@ -1,146 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-Support Eiffel-style preconditions and postconditions for functions.
-
-An example for Python metaclasses.
-"""
-
-import unittest
-from types import FunctionType as function
-
-class EiffelBaseMetaClass(type):
-
- def __new__(meta, name, bases, dict):
- meta.convert_methods(dict)
- return super(EiffelBaseMetaClass, meta).__new__(
- meta, name, bases, dict)
-
- @classmethod
- def convert_methods(cls, dict):
- """Replace functions in dict with EiffelMethod wrappers.
-
- The dict is modified in place.
-
- If a method ends in _pre or _post, it is removed from the dict
- regardless of whether there is a corresponding method.
- """
- # find methods with pre or post conditions
- methods = []
- for k, v in dict.items():
- if k.endswith('_pre') or k.endswith('_post'):
- assert isinstance(v, function)
- elif isinstance(v, function):
- methods.append(k)
- for m in methods:
- pre = dict.get("%s_pre" % m)
- post = dict.get("%s_post" % m)
- if pre or post:
- dict[m] = cls.make_eiffel_method(dict[m], pre, post)
-
-
-class EiffelMetaClass1(EiffelBaseMetaClass):
- # an implementation of the "eiffel" meta class that uses nested functions
-
- @staticmethod
- def make_eiffel_method(func, pre, post):
- def method(self, *args, **kwargs):
- if pre:
- pre(self, *args, **kwargs)
- rv = func(self, *args, **kwargs)
- if post:
- post(self, rv, *args, **kwargs)
- return rv
-
- if func.__doc__:
- method.__doc__ = func.__doc__
-
- return method
-
-
-class EiffelMethodWrapper:
-
- def __init__(self, inst, descr):
- self._inst = inst
- self._descr = descr
-
- def __call__(self, *args, **kwargs):
- return self._descr.callmethod(self._inst, args, kwargs)
-
-
-class EiffelDescriptor:
-
- def __init__(self, func, pre, post):
- self._func = func
- self._pre = pre
- self._post = post
-
- self.__name__ = func.__name__
- self.__doc__ = func.__doc__
-
- def __get__(self, obj, cls=None):
- return EiffelMethodWrapper(obj, self)
-
- def callmethod(self, inst, args, kwargs):
- if self._pre:
- self._pre(inst, *args, **kwargs)
- x = self._func(inst, *args, **kwargs)
- if self._post:
- self._post(inst, x, *args, **kwargs)
- return x
-
-
-class EiffelMetaClass2(EiffelBaseMetaClass):
- # an implementation of the "eiffel" meta class that uses descriptors
-
- make_eiffel_method = EiffelDescriptor
-
-
-class Tests(unittest.TestCase):
-
- def testEiffelMetaClass1(self):
- self._test(EiffelMetaClass1)
-
- def testEiffelMetaClass2(self):
- self._test(EiffelMetaClass2)
-
- def _test(self, metaclass):
- class Eiffel(metaclass=metaclass):
- pass
-
- class Test(Eiffel):
- def m(self, arg):
- """Make it a little larger"""
- return arg + 1
-
- def m2(self, arg):
- """Make it a little larger"""
- return arg + 1
-
- def m2_pre(self, arg):
- assert arg > 0
-
- def m2_post(self, result, arg):
- assert result > arg
-
- class Sub(Test):
- def m2(self, arg):
- return arg**2
-
- def m2_post(self, Result, arg):
- super(Sub, self).m2_post(Result, arg)
- assert Result < 100
-
- t = Test()
- self.assertEqual(t.m(1), 2)
- self.assertEqual(t.m2(1), 2)
- self.assertRaises(AssertionError, t.m2, 0)
-
- s = Sub()
- self.assertRaises(AssertionError, s.m2, 1)
- self.assertRaises(AssertionError, s.m2, 10)
- self.assertEqual(s.m2(5), 25)
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/Tools/demo/hanoi.py b/Tools/demo/hanoi.py
deleted file mode 100755
index 8db895c..0000000
--- a/Tools/demo/hanoi.py
+++ /dev/null
@@ -1,154 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-Animated Towers of Hanoi using Tk with optional bitmap file in background.
-
-Usage: hanoi.py [n [bitmapfile]]
-
-n is the number of pieces to animate; default is 4, maximum 15.
-
-The bitmap file can be any X11 bitmap file (look in /usr/include/X11/bitmaps for
-samples); it is displayed as the background of the animation. Default is no
-bitmap.
-"""
-
-from tkinter import Tk, Canvas
-
-# Basic Towers-of-Hanoi algorithm: move n pieces from a to b, using c
-# as temporary. For each move, call report()
-def hanoi(n, a, b, c, report):
- if n <= 0: return
- hanoi(n-1, a, c, b, report)
- report(n, a, b)
- hanoi(n-1, c, b, a, report)
-
-
-# The graphical interface
-class Tkhanoi:
-
- # Create our objects
- def __init__(self, n, bitmap=None):
- self.n = n
- self.tk = tk = Tk()
- self.canvas = c = Canvas(tk)
- c.pack()
- width, height = tk.getint(c['width']), tk.getint(c['height'])
-
- # Add background bitmap
- if bitmap:
- self.bitmap = c.create_bitmap(width//2, height//2,
- bitmap=bitmap,
- foreground='blue')
-
- # Generate pegs
- pegwidth = 10
- pegheight = height//2
- pegdist = width//3
- x1, y1 = (pegdist-pegwidth)//2, height*1//3
- x2, y2 = x1+pegwidth, y1+pegheight
- self.pegs = []
- p = c.create_rectangle(x1, y1, x2, y2, fill='black')
- self.pegs.append(p)
- x1, x2 = x1+pegdist, x2+pegdist
- p = c.create_rectangle(x1, y1, x2, y2, fill='black')
- self.pegs.append(p)
- x1, x2 = x1+pegdist, x2+pegdist
- p = c.create_rectangle(x1, y1, x2, y2, fill='black')
- self.pegs.append(p)
- self.tk.update()
-
- # Generate pieces
- pieceheight = pegheight//16
- maxpiecewidth = pegdist*2//3
- minpiecewidth = 2*pegwidth
- self.pegstate = [[], [], []]
- self.pieces = {}
- x1, y1 = (pegdist-maxpiecewidth)//2, y2-pieceheight-2
- x2, y2 = x1+maxpiecewidth, y1+pieceheight
- dx = (maxpiecewidth-minpiecewidth) // (2*max(1, n-1))
- for i in range(n, 0, -1):
- p = c.create_rectangle(x1, y1, x2, y2, fill='red')
- self.pieces[i] = p
- self.pegstate[0].append(i)
- x1, x2 = x1 + dx, x2-dx
- y1, y2 = y1 - pieceheight-2, y2-pieceheight-2
- self.tk.update()
- self.tk.after(25)
-
- # Run -- never returns
- def run(self):
- while True:
- hanoi(self.n, 0, 1, 2, self.report)
- hanoi(self.n, 1, 2, 0, self.report)
- hanoi(self.n, 2, 0, 1, self.report)
- hanoi(self.n, 0, 2, 1, self.report)
- hanoi(self.n, 2, 1, 0, self.report)
- hanoi(self.n, 1, 0, 2, self.report)
-
- # Reporting callback for the actual hanoi function
- def report(self, i, a, b):
- if self.pegstate[a][-1] != i: raise RuntimeError # Assertion
- del self.pegstate[a][-1]
- p = self.pieces[i]
- c = self.canvas
-
- # Lift the piece above peg a
- ax1, ay1, ax2, ay2 = c.bbox(self.pegs[a])
- while True:
- x1, y1, x2, y2 = c.bbox(p)
- if y2 < ay1: break
- c.move(p, 0, -1)
- self.tk.update()
-
- # Move it towards peg b
- bx1, by1, bx2, by2 = c.bbox(self.pegs[b])
- newcenter = (bx1+bx2)//2
- while True:
- x1, y1, x2, y2 = c.bbox(p)
- center = (x1+x2)//2
- if center == newcenter: break
- if center > newcenter: c.move(p, -1, 0)
- else: c.move(p, 1, 0)
- self.tk.update()
-
- # Move it down on top of the previous piece
- pieceheight = y2-y1
- newbottom = by2 - pieceheight*len(self.pegstate[b]) - 2
- while True:
- x1, y1, x2, y2 = c.bbox(p)
- if y2 >= newbottom: break
- c.move(p, 0, 1)
- self.tk.update()
-
- # Update peg state
- self.pegstate[b].append(i)
-
-
-def main():
- import sys
-
- # First argument is number of pegs, default 4
- if sys.argv[1:]:
- n = int(sys.argv[1])
- else:
- n = 4
-
- # Second argument is bitmap file, default none
- if sys.argv[2:]:
- bitmap = sys.argv[2]
- # Reverse meaning of leading '@' compared to Tk
- if bitmap[0] == '@': bitmap = bitmap[1:]
- else: bitmap = '@' + bitmap
- else:
- bitmap = None
-
- # Create the graphical objects...
- h = Tkhanoi(n, bitmap)
-
- # ...and run!
- h.run()
-
-
-# Call main when run as script
-if __name__ == '__main__':
- main()
diff --git a/Tools/demo/life.py b/Tools/demo/life.py
deleted file mode 100755
index fc4cb49..0000000
--- a/Tools/demo/life.py
+++ /dev/null
@@ -1,262 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-A curses-based version of Conway's Game of Life.
-
-An empty board will be displayed, and the following commands are available:
- E : Erase the board
- R : Fill the board randomly
- S : Step for a single generation
- C : Update continuously until a key is struck
- Q : Quit
- Cursor keys : Move the cursor around the board
- Space or Enter : Toggle the contents of the cursor's position
-
-Contributed by Andrew Kuchling, Mouse support and color by Dafydd Crosby.
-"""
-
-import curses
-import random
-
-
-class LifeBoard:
- """Encapsulates a Life board
-
- Attributes:
- X,Y : horizontal and vertical size of the board
- state : dictionary mapping (x,y) to 0 or 1
-
- Methods:
- display(update_board) -- If update_board is true, compute the
- next generation. Then display the state
- of the board and refresh the screen.
- erase() -- clear the entire board
- make_random() -- fill the board randomly
- set(y,x) -- set the given cell to Live; doesn't refresh the screen
- toggle(y,x) -- change the given cell from live to dead, or vice
- versa, and refresh the screen display
-
- """
- def __init__(self, scr, char=ord('*')):
- """Create a new LifeBoard instance.
-
- scr -- curses screen object to use for display
- char -- character used to render live cells (default: '*')
- """
- self.state = {}
- self.scr = scr
- Y, X = self.scr.getmaxyx()
- self.X, self.Y = X - 2, Y - 2 - 1
- self.char = char
- self.scr.clear()
-
- # Draw a border around the board
- border_line = '+' + (self.X * '-') + '+'
- self.scr.addstr(0, 0, border_line)
- self.scr.addstr(self.Y + 1, 0, border_line)
- for y in range(0, self.Y):
- self.scr.addstr(1 + y, 0, '|')
- self.scr.addstr(1 + y, self.X + 1, '|')
- self.scr.refresh()
-
- def set(self, y, x):
- """Set a cell to the live state"""
- if x < 0 or self.X <= x or y < 0 or self.Y <= y:
- raise ValueError("Coordinates out of range %i,%i" % (y, x))
- self.state[x, y] = 1
-
- def toggle(self, y, x):
- """Toggle a cell's state between live and dead"""
- if x < 0 or self.X <= x or y < 0 or self.Y <= y:
- raise ValueError("Coordinates out of range %i,%i" % (y, x))
- if (x, y) in self.state:
- del self.state[x, y]
- self.scr.addch(y + 1, x + 1, ' ')
- else:
- self.state[x, y] = 1
- if curses.has_colors():
- # Let's pick a random color!
- self.scr.attrset(curses.color_pair(random.randrange(1, 7)))
- self.scr.addch(y + 1, x + 1, self.char)
- self.scr.attrset(0)
- self.scr.refresh()
-
- def erase(self):
- """Clear the entire board and update the board display"""
- self.state = {}
- self.display(update_board=False)
-
- def display(self, update_board=True):
- """Display the whole board, optionally computing one generation"""
- M, N = self.X, self.Y
- if not update_board:
- for i in range(0, M):
- for j in range(0, N):
- if (i, j) in self.state:
- self.scr.addch(j + 1, i + 1, self.char)
- else:
- self.scr.addch(j + 1, i + 1, ' ')
- self.scr.refresh()
- return
-
- d = {}
- self.boring = 1
- for i in range(0, M):
- L = range(max(0, i - 1), min(M, i + 2))
- for j in range(0, N):
- s = 0
- live = (i, j) in self.state
- for k in range(max(0, j - 1), min(N, j + 2)):
- for l in L:
- if (l, k) in self.state:
- s += 1
- s -= live
- if s == 3:
- # Birth
- d[i, j] = 1
- if curses.has_colors():
- # Let's pick a random color!
- self.scr.attrset(curses.color_pair(
- random.randrange(1, 7)))
- self.scr.addch(j + 1, i + 1, self.char)
- self.scr.attrset(0)
- if not live:
- self.boring = 0
- elif s == 2 and live:
- # Survival
- d[i, j] = 1
- elif live:
- # Death
- self.scr.addch(j + 1, i + 1, ' ')
- self.boring = 0
- self.state = d
- self.scr.refresh()
-
- def make_random(self):
- "Fill the board with a random pattern"
- self.state = {}
- for i in range(0, self.X):
- for j in range(0, self.Y):
- if random.random() > 0.5:
- self.set(j, i)
-
-
-def erase_menu(stdscr, menu_y):
- "Clear the space where the menu resides"
- stdscr.move(menu_y, 0)
- stdscr.clrtoeol()
- stdscr.move(menu_y + 1, 0)
- stdscr.clrtoeol()
-
-
-def display_menu(stdscr, menu_y):
- "Display the menu of possible keystroke commands"
- erase_menu(stdscr, menu_y)
-
- # If color, then light the menu up :-)
- if curses.has_colors():
- stdscr.attrset(curses.color_pair(1))
- stdscr.addstr(menu_y, 4,
- 'Use the cursor keys to move, and space or Enter to toggle a cell.')
- stdscr.addstr(menu_y + 1, 4,
- 'E)rase the board, R)andom fill, S)tep once or C)ontinuously, Q)uit')
- stdscr.attrset(0)
-
-
-def keyloop(stdscr):
- # Clear the screen and display the menu of keys
- stdscr.clear()
- stdscr_y, stdscr_x = stdscr.getmaxyx()
- menu_y = (stdscr_y - 3) - 1
- display_menu(stdscr, menu_y)
-
- # If color, then initialize the color pairs
- if curses.has_colors():
- curses.init_pair(1, curses.COLOR_BLUE, 0)
- curses.init_pair(2, curses.COLOR_CYAN, 0)
- curses.init_pair(3, curses.COLOR_GREEN, 0)
- curses.init_pair(4, curses.COLOR_MAGENTA, 0)
- curses.init_pair(5, curses.COLOR_RED, 0)
- curses.init_pair(6, curses.COLOR_YELLOW, 0)
- curses.init_pair(7, curses.COLOR_WHITE, 0)
-
- # Set up the mask to listen for mouse events
- curses.mousemask(curses.BUTTON1_CLICKED)
-
- # Allocate a subwindow for the Life board and create the board object
- subwin = stdscr.subwin(stdscr_y - 3, stdscr_x, 0, 0)
- board = LifeBoard(subwin, char=ord('*'))
- board.display(update_board=False)
-
- # xpos, ypos are the cursor's position
- xpos, ypos = board.X // 2, board.Y // 2
-
- # Main loop:
- while True:
- stdscr.move(1 + ypos, 1 + xpos) # Move the cursor
- c = stdscr.getch() # Get a keystroke
- if 0 < c < 256:
- c = chr(c)
- if c in ' \n':
- board.toggle(ypos, xpos)
- elif c in 'Cc':
- erase_menu(stdscr, menu_y)
- stdscr.addstr(menu_y, 6, ' Hit any key to stop continuously '
- 'updating the screen.')
- stdscr.refresh()
- # Activate nodelay mode; getch() will return -1
- # if no keystroke is available, instead of waiting.
- stdscr.nodelay(1)
- while True:
- c = stdscr.getch()
- if c != -1:
- break
- stdscr.addstr(0, 0, '/')
- stdscr.refresh()
- board.display()
- stdscr.addstr(0, 0, '+')
- stdscr.refresh()
-
- stdscr.nodelay(0) # Disable nodelay mode
- display_menu(stdscr, menu_y)
-
- elif c in 'Ee':
- board.erase()
- elif c in 'Qq':
- break
- elif c in 'Rr':
- board.make_random()
- board.display(update_board=False)
- elif c in 'Ss':
- board.display()
- else:
- # Ignore incorrect keys
- pass
- elif c == curses.KEY_UP and ypos > 0:
- ypos -= 1
- elif c == curses.KEY_DOWN and ypos + 1 < board.Y:
- ypos += 1
- elif c == curses.KEY_LEFT and xpos > 0:
- xpos -= 1
- elif c == curses.KEY_RIGHT and xpos + 1 < board.X:
- xpos += 1
- elif c == curses.KEY_MOUSE:
- mouse_id, mouse_x, mouse_y, mouse_z, button_state = curses.getmouse()
- if (mouse_x > 0 and mouse_x < board.X + 1 and
- mouse_y > 0 and mouse_y < board.Y + 1):
- xpos = mouse_x - 1
- ypos = mouse_y - 1
- board.toggle(ypos, xpos)
- else:
- # They've clicked outside the board
- curses.flash()
- else:
- # Ignore incorrect keys
- pass
-
-
-def main(stdscr):
- keyloop(stdscr) # Enter the main loop
-
-if __name__ == '__main__':
- curses.wrapper(main)
diff --git a/Tools/demo/markov.py b/Tools/demo/markov.py
deleted file mode 100755
index 9729f38..0000000
--- a/Tools/demo/markov.py
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-Markov chain simulation of words or characters.
-"""
-
-class Markov:
- def __init__(self, histsize, choice):
- self.histsize = histsize
- self.choice = choice
- self.trans = {}
-
- def add(self, state, next):
- self.trans.setdefault(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 True:
- subseq = seq[max(0, len(seq)-n):]
- options = trans[subseq]
- next = choice(options)
- if not next:
- break
- seq += next
- return seq
-
-
-def test():
- import sys, random, getopt
- args = sys.argv[1:]
- try:
- opts, args = getopt.getopt(args, '0123456789cdwq')
- except getopt.error:
- print('Usage: %s [-#] [-cddqw] [file] ...' % sys.argv[0])
- 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.')
- sys.exit(2)
- histsize = 2
- do_words = False
- debug = 1
- for o, a in opts:
- if '-0' <= o <= '-9': histsize = int(o[1:])
- if o == '-c': do_words = False
- if o == '-d': debug += 1
- if o == '-q': debug = 0
- if o == '-w': do_words = True
- if not args:
- args = ['-']
-
- m = Markov(histsize, random.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')
- with f:
- if debug: print('processing', filename, '...')
- text = f.read()
- paralist = text.split('\n\n')
- for para in paralist:
- if debug > 1: print('feeding ...')
- words = para.split()
- if words:
- if do_words:
- data = tuple(words)
- else:
- data = ' '.join(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(repr(key), m.trans[key])
- if histsize == 0: print(repr(''), m.trans[''])
- print()
- while True:
- data = m.get()
- if do_words:
- words = data
- else:
- words = data.split()
- n = 0
- limit = 72
- for w in words:
- if n + len(w) > limit:
- print()
- n = 0
- print(w, end=' ')
- n += len(w) + 1
- print()
- print()
-
-if __name__ == "__main__":
- test()
diff --git a/Tools/demo/mcast.py b/Tools/demo/mcast.py
deleted file mode 100755
index 924c7c3..0000000
--- a/Tools/demo/mcast.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-Send/receive UDP multicast packets.
-Requires that your OS kernel supports IP multicast.
-
-Usage:
- mcast -s (sender, IPv4)
- mcast -s -6 (sender, IPv6)
- mcast (receivers, IPv4)
- mcast -6 (receivers, IPv6)
-"""
-
-MYPORT = 8123
-MYGROUP_4 = '225.0.0.250'
-MYGROUP_6 = 'ff15:7079:7468:6f6e:6465:6d6f:6d63:6173'
-MYTTL = 1 # Increase to reach other networks
-
-import time
-import struct
-import socket
-import sys
-
-def main():
- group = MYGROUP_6 if "-6" in sys.argv[1:] else MYGROUP_4
-
- if "-s" in sys.argv[1:]:
- sender(group)
- else:
- receiver(group)
-
-
-def sender(group):
- addrinfo = socket.getaddrinfo(group, None)[0]
-
- s = socket.socket(addrinfo[0], socket.SOCK_DGRAM)
-
- # Set Time-to-live (optional)
- ttl_bin = struct.pack('@i', MYTTL)
- if addrinfo[0] == socket.AF_INET: # IPv4
- s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl_bin)
- else:
- s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, ttl_bin)
-
- while True:
- data = repr(time.time()).encode('utf-8') + b'\0'
- s.sendto(data, (addrinfo[4][0], MYPORT))
- time.sleep(1)
-
-
-def receiver(group):
- # Look up multicast group address in name server and find out IP version
- addrinfo = socket.getaddrinfo(group, None)[0]
-
- # Create a socket
- s = socket.socket(addrinfo[0], socket.SOCK_DGRAM)
-
- # Allow multiple copies of this program on one machine
- # (not strictly needed)
- s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-
- # Bind it to the port
- s.bind(('', MYPORT))
-
- group_bin = socket.inet_pton(addrinfo[0], addrinfo[4][0])
- # Join group
- if addrinfo[0] == socket.AF_INET: # IPv4
- mreq = group_bin + struct.pack('=I', socket.INADDR_ANY)
- s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
- else:
- mreq = group_bin + struct.pack('@I', 0)
- s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
-
- # Loop, printing any data we receive
- while True:
- data, sender = s.recvfrom(1500)
- while data[-1:] == '\0': data = data[:-1] # Strip trailing \0's
- print(str(sender) + ' ' + repr(data))
-
-
-if __name__ == '__main__':
- main()
diff --git a/Tools/demo/queens.py b/Tools/demo/queens.py
deleted file mode 100755
index dcc1bae..0000000
--- a/Tools/demo/queens.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-N queens problem.
-
-The (well-known) problem is due to Niklaus Wirth.
-
-This solution is inspired by Dijkstra (Structured Programming). It is
-a classic recursive backtracking approach.
-"""
-
-N = 8 # Default; command line overrides
-
-class Queens:
-
- def __init__(self, n=N):
- self.n = n
- self.reset()
-
- def reset(self):
- n = self.n
- self.y = [None] * n # Where is the queen in column x
- self.row = [0] * n # Is row[y] safe?
- self.up = [0] * (2*n-1) # Is upward diagonal[x-y] safe?
- self.down = [0] * (2*n-1) # Is downward diagonal[x+y] safe?
- self.nfound = 0 # Instrumentation
-
- def solve(self, x=0): # Recursive solver
- for y in range(self.n):
- if self.safe(x, y):
- self.place(x, y)
- if x+1 == self.n:
- self.display()
- else:
- self.solve(x+1)
- self.remove(x, y)
-
- def safe(self, x, y):
- return not self.row[y] and not self.up[x-y] and not self.down[x+y]
-
- def place(self, x, y):
- self.y[x] = y
- self.row[y] = 1
- self.up[x-y] = 1
- self.down[x+y] = 1
-
- def remove(self, x, y):
- self.y[x] = None
- self.row[y] = 0
- self.up[x-y] = 0
- self.down[x+y] = 0
-
- silent = 0 # If true, count solutions only
-
- def display(self):
- self.nfound = self.nfound + 1
- if self.silent:
- return
- print('+-' + '--'*self.n + '+')
- for y in range(self.n-1, -1, -1):
- print('|', end=' ')
- for x in range(self.n):
- if self.y[x] == y:
- print("Q", end=' ')
- else:
- print(".", end=' ')
- print('|')
- print('+-' + '--'*self.n + '+')
-
-def main():
- import sys
- silent = 0
- n = N
- if sys.argv[1:2] == ['-n']:
- silent = 1
- del sys.argv[1]
- if sys.argv[1:]:
- n = int(sys.argv[1])
- q = Queens(n)
- q.silent = silent
- q.solve()
- print("Found", q.nfound, "solutions.")
-
-if __name__ == "__main__":
- main()
diff --git a/Tools/demo/redemo.py b/Tools/demo/redemo.py
deleted file mode 100755
index f801dfc..0000000
--- a/Tools/demo/redemo.py
+++ /dev/null
@@ -1,171 +0,0 @@
-#!/usr/bin/env python3
-
-"""Basic regular expression demonstration facility (Perl style syntax)."""
-
-from tkinter import *
-import re
-
-class ReDemo:
-
- def __init__(self, master):
- self.master = master
-
- self.promptdisplay = Label(self.master, anchor=W,
- text="Enter a Perl-style regular expression:")
- self.promptdisplay.pack(side=TOP, fill=X)
-
- self.regexdisplay = Entry(self.master)
- self.regexdisplay.pack(fill=X)
- self.regexdisplay.focus_set()
-
- self.addoptions()
-
- self.statusdisplay = Label(self.master, text="", anchor=W)
- self.statusdisplay.pack(side=TOP, fill=X)
-
- self.labeldisplay = Label(self.master, anchor=W,
- text="Enter a string to search:")
- self.labeldisplay.pack(fill=X)
- self.labeldisplay.pack(fill=X)
-
- self.showframe = Frame(master)
- self.showframe.pack(fill=X, anchor=W)
-
- self.showvar = StringVar(master)
- self.showvar.set("first")
-
- self.showfirstradio = Radiobutton(self.showframe,
- text="Highlight first match",
- variable=self.showvar,
- value="first",
- command=self.recompile)
- self.showfirstradio.pack(side=LEFT)
-
- self.showallradio = Radiobutton(self.showframe,
- text="Highlight all matches",
- variable=self.showvar,
- value="all",
- command=self.recompile)
- self.showallradio.pack(side=LEFT)
-
- self.stringdisplay = Text(self.master, width=60, height=4)
- self.stringdisplay.pack(fill=BOTH, expand=1)
- self.stringdisplay.tag_configure("hit", background="yellow")
-
- self.grouplabel = Label(self.master, text="Groups:", anchor=W)
- self.grouplabel.pack(fill=X)
-
- self.grouplist = Listbox(self.master)
- self.grouplist.pack(expand=1, fill=BOTH)
-
- self.regexdisplay.bind('<Key>', self.recompile)
- self.stringdisplay.bind('<Key>', self.reevaluate)
-
- self.compiled = None
- self.recompile()
-
- btags = self.regexdisplay.bindtags()
- self.regexdisplay.bindtags(btags[1:] + btags[:1])
-
- btags = self.stringdisplay.bindtags()
- self.stringdisplay.bindtags(btags[1:] + btags[:1])
-
- def addoptions(self):
- self.frames = []
- self.boxes = []
- self.vars = []
- for name in ('IGNORECASE',
- 'MULTILINE',
- 'DOTALL',
- 'VERBOSE'):
- if len(self.boxes) % 3 == 0:
- frame = Frame(self.master)
- frame.pack(fill=X)
- self.frames.append(frame)
- val = getattr(re, name).value
- var = IntVar()
- box = Checkbutton(frame,
- variable=var, text=name,
- offvalue=0, onvalue=val,
- command=self.recompile)
- box.pack(side=LEFT)
- self.boxes.append(box)
- self.vars.append(var)
-
- def getflags(self):
- flags = 0
- for var in self.vars:
- flags = flags | var.get()
- return flags
-
- def recompile(self, event=None):
- try:
- self.compiled = re.compile(self.regexdisplay.get(),
- self.getflags())
- bg = self.promptdisplay['background']
- self.statusdisplay.config(text="", background=bg)
- except re.error as msg:
- self.compiled = None
- self.statusdisplay.config(
- text="re.error: %s" % str(msg),
- background="red")
- self.reevaluate()
-
- def reevaluate(self, event=None):
- try:
- self.stringdisplay.tag_remove("hit", "1.0", END)
- except TclError:
- pass
- try:
- self.stringdisplay.tag_remove("hit0", "1.0", END)
- except TclError:
- pass
- self.grouplist.delete(0, END)
- if not self.compiled:
- return
- self.stringdisplay.tag_configure("hit", background="yellow")
- self.stringdisplay.tag_configure("hit0", background="orange")
- text = self.stringdisplay.get("1.0", END)
- last = 0
- nmatches = 0
- while last <= len(text):
- m = self.compiled.search(text, last)
- if m is None:
- break
- first, last = m.span()
- if last == first:
- last = first+1
- tag = "hit0"
- else:
- tag = "hit"
- pfirst = "1.0 + %d chars" % first
- plast = "1.0 + %d chars" % last
- self.stringdisplay.tag_add(tag, pfirst, plast)
- if nmatches == 0:
- self.stringdisplay.yview_pickplace(pfirst)
- groups = list(m.groups())
- groups.insert(0, m.group())
- for i in range(len(groups)):
- g = "%2d: %r" % (i, groups[i])
- self.grouplist.insert(END, g)
- nmatches = nmatches + 1
- if self.showvar.get() == "first":
- break
-
- if nmatches == 0:
- self.statusdisplay.config(text="(no match)",
- background="yellow")
- else:
- self.statusdisplay.config(text="")
-
-
-# Main function, run when invoked as a stand-alone Python program.
-
-def main():
- root = Tk()
- demo = ReDemo(root)
- root.protocol('WM_DELETE_WINDOW', root.quit)
- root.mainloop()
-
-if __name__ == '__main__':
- main()
diff --git a/Tools/demo/rpython.py b/Tools/demo/rpython.py
deleted file mode 100755
index 11f72cb..0000000
--- a/Tools/demo/rpython.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-Remote python client.
-Execute Python commands remotely and send output back.
-"""
-
-import sys
-from socket import socket, AF_INET, SOCK_STREAM, SHUT_WR
-
-PORT = 4127
-BUFSIZE = 1024
-
-def main():
- if len(sys.argv) < 3:
- print("usage: rpython host command")
- sys.exit(2)
- host = sys.argv[1]
- port = PORT
- i = host.find(':')
- if i >= 0:
- port = int(host[i+1:])
- host = host[:i]
- command = ' '.join(sys.argv[2:])
- with socket(AF_INET, SOCK_STREAM) as s:
- s.connect((host, port))
- s.send(command.encode())
- s.shutdown(SHUT_WR)
- reply = b''
- while True:
- data = s.recv(BUFSIZE)
- if not data:
- break
- reply += data
- print(reply.decode(), end=' ')
-
-main()
diff --git a/Tools/demo/rpythond.py b/Tools/demo/rpythond.py
deleted file mode 100755
index 4e47fb9..0000000
--- a/Tools/demo/rpythond.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-Remote python server.
-Execute Python commands remotely and send output back.
-
-WARNING: This version has a gaping security hole -- it accepts requests
-from any host on the internet!
-"""
-
-import sys
-from socket import socket, AF_INET, SOCK_STREAM
-import io
-import traceback
-
-PORT = 4127
-BUFSIZE = 1024
-
-def main():
- if len(sys.argv) > 1:
- port = int(sys.argv[1])
- else:
- port = PORT
- s = socket(AF_INET, SOCK_STREAM)
- s.bind(('', port))
- s.listen(1)
- while True:
- conn, (remotehost, remoteport) = s.accept()
- with conn:
- print('connection from', remotehost, remoteport)
- request = b''
- while True:
- data = conn.recv(BUFSIZE)
- if not data:
- break
- request += data
- reply = execute(request.decode())
- conn.send(reply.encode())
-
-def execute(request):
- stdout = sys.stdout
- stderr = sys.stderr
- sys.stdout = sys.stderr = fakefile = io.StringIO()
- try:
- try:
- exec(request, {}, {})
- except:
- print()
- traceback.print_exc(100)
- finally:
- sys.stderr = stderr
- sys.stdout = stdout
- return fakefile.getvalue()
-
-try:
- main()
-except KeyboardInterrupt:
- pass
diff --git a/Tools/demo/sortvisu.py b/Tools/demo/sortvisu.py
deleted file mode 100755
index 056a0e0..0000000
--- a/Tools/demo/sortvisu.py
+++ /dev/null
@@ -1,635 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-Sorting algorithms visualizer using Tkinter.
-
-This module is comprised of three ``components'':
-
-- an array visualizer with methods that implement basic sorting
-operations (compare, swap) as well as methods for ``annotating'' the
-sorting algorithm (e.g. to show the pivot element);
-
-- a number of sorting algorithms (currently quicksort, insertion sort,
-selection sort and bubble sort, as well as a randomization function),
-all using the array visualizer for its basic operations and with calls
-to its annotation methods;
-
-- and a ``driver'' class which can be used as a Grail applet or as a
-stand-alone application.
-"""
-
-from tkinter import *
-import random
-
-XGRID = 10
-YGRID = 10
-WIDTH = 6
-
-
-class Array:
-
- class Cancelled(BaseException):
- pass
-
- def __init__(self, master, data=None):
- self.master = master
- self.frame = Frame(self.master)
- self.frame.pack(fill=X)
- self.label = Label(self.frame)
- self.label.pack()
- self.canvas = Canvas(self.frame)
- self.canvas.pack()
- self.report = Label(self.frame)
- self.report.pack()
- 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:
- self.setdata(data)
-
- def setdata(self, data):
- olditems = self.items
- self.items = []
- for item in olditems:
- item.delete()
- self.size = len(data)
- self.maxvalue = max(data)
- self.canvas.config(width=(self.size+1)*XGRID,
- height=(self.maxvalue+1)*YGRID)
- for i in range(self.size):
- self.items.append(ArrayItem(self, i, data[i]))
- self.reset("Sort demo, size %d" % self.size)
-
- speed = "normal"
-
- def setspeed(self, speed):
- self.speed = speed
-
- def destroy(self):
- self.frame.destroy()
-
- in_mainloop = 0
- stop_mainloop = 0
-
- def cancel(self):
- self.stop_mainloop = 1
- if self.in_mainloop:
- self.master.quit()
-
- def step(self):
- if self.in_mainloop:
- self.master.quit()
-
- def wait(self, msecs):
- if self.speed == "fastest":
- msecs = 0
- elif self.speed == "fast":
- msecs = msecs//10
- elif self.speed == "single-step":
- msecs = 1000000000
- if not self.stop_mainloop:
- self.master.update()
- id = self.master.after(msecs, self.master.quit)
- self.in_mainloop = 1
- self.master.mainloop()
- self.master.after_cancel(id)
- self.in_mainloop = 0
- if self.stop_mainloop:
- self.stop_mainloop = 0
- self.message("Cancelled")
- raise Array.Cancelled
-
- def getsize(self):
- return self.size
-
- def show_partition(self, first, last):
- for i in range(self.size):
- item = self.items[i]
- if first <= i < last:
- self.canvas.itemconfig(item, fill='red')
- else:
- 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]
- self.canvas.itemconfig(item, fill='red')
- self.hide_left_right_pivot()
-
- def show_left(self, left):
- if not 0 <= left < self.size:
- self.hide_left()
- return
- x1, y1, x2, y2 = self.items[left].position()
-## top, bot = HIRO
- self.canvas.coords(self.left, (x1 - 2, 0, x1 - 2, 9999))
- self.master.update()
-
- def show_right(self, right):
- if not 0 <= right < self.size:
- self.hide_right()
- return
- x1, y1, x2, y2 = self.items[right].position()
- self.canvas.coords(self.right, (x2 + 2, 0, x2 + 2, 9999))
- self.master.update()
-
- def hide_left_right_pivot(self):
- self.hide_left()
- self.hide_right()
- self.hide_pivot()
-
- def hide_left(self):
- self.canvas.coords(self.left, (0, 0, 0, 0))
-
- def hide_right(self):
- self.canvas.coords(self.right, (0, 0, 0, 0))
-
- def show_pivot(self, pivot):
- x1, y1, x2, y2 = self.items[pivot].position()
- self.canvas.coords(self.pivot, (0, y1 - 2, 9999, y1 - 2))
-
- def hide_pivot(self):
- self.canvas.coords(self.pivot, (0, 0, 0, 0))
-
- def swap(self, i, j):
- if i == j: return
- self.countswap()
- item = self.items[i]
- other = self.items[j]
- self.items[i], self.items[j] = other, item
- item.swapwith(other)
-
- def compare(self, i, j):
- self.countcompare()
- item = self.items[i]
- other = self.items[j]
- return item.compareto(other)
-
- def reset(self, msg):
- self.ncompares = 0
- self.nswaps = 0
- self.message(msg)
- self.updatereport()
- self.hide_partition()
-
- def message(self, msg):
- self.label.config(text=msg)
-
- def countswap(self):
- self.nswaps = self.nswaps + 1
- self.updatereport()
-
- def countcompare(self):
- self.ncompares = self.ncompares + 1
- self.updatereport()
-
- def updatereport(self):
- text = "%d cmps, %d swaps" % (self.ncompares, self.nswaps)
- self.report.config(text=text)
-
-
-class ArrayItem:
-
- def __init__(self, array, index, value):
- self.array = array
- self.index = index
- self.value = value
- self.canvas = array.canvas
- x1, y1, x2, y2 = self.position()
- self.item_id = array.canvas.create_rectangle(x1, y1, x2, y2,
- fill='red', outline='black', width=1)
- self.canvas.tag_bind(self.item_id, '<Button-1>', self.mouse_down)
- self.canvas.tag_bind(self.item_id, '<Button1-Motion>', self.mouse_move)
- self.canvas.tag_bind(self.item_id, '<ButtonRelease-1>', self.mouse_up)
-
- def delete(self):
- item_id = self.item_id
- self.array = None
- 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.canvas.tag_raise(self.item_id)
-
- def mouse_move(self, event):
- self.canvas.move(self.item_id,
- event.x - self.lastx, event.y - self.lasty)
- self.lastx = event.x
- self.lasty = event.y
-
- def mouse_up(self, event):
- i = self.nearestindex(event.x)
- if i >= self.array.getsize():
- i = self.array.getsize() - 1
- if i < 0:
- i = 0
- other = self.array.items[i]
- here = self.index
- self.array.items[here], self.array.items[i] = other, self
- self.index = i
- x1, y1, x2, y2 = self.position()
- self.canvas.coords(self.item_id, (x1, y1, x2, y2))
- other.setindex(here)
-
- def setindex(self, index):
- nsteps = steps(self.index, index)
- if not nsteps: return
- if self.array.speed == "fastest":
- nsteps = 0
- oldpts = self.position()
- self.index = index
- newpts = self.position()
- trajectory = interpolate(oldpts, newpts, nsteps)
- self.canvas.tag_raise(self.item_id)
- for pts in trajectory:
- self.canvas.coords(self.item_id, pts)
- self.array.wait(50)
-
- def swapwith(self, other):
- nsteps = steps(self.index, other.index)
- if not nsteps: return
- if self.array.speed == "fastest":
- nsteps = 0
- myoldpts = self.position()
- otheroldpts = other.position()
- self.index, other.index = other.index, self.index
- mynewpts = self.position()
- othernewpts = other.position()
- 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.canvas.coords(self.item_id, mynewpts)
- self.canvas.coords(other.item_id, othernewpts)
- self.array.master.update()
- 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.canvas.tag_raise(self.item_id)
- self.canvas.tag_raise(other.item_id)
- else:
- 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.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.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.canvas.itemcget(self.item_id, 'fill')
- otherfill = self.canvas.itemcget(other.item_id, 'fill')
- if self.value < other.value:
- myflash = 'white'
- otherflash = 'black'
- outcome = -1
- elif self.value > other.value:
- myflash = 'black'
- otherflash = 'white'
- outcome = 1
- else:
- myflash = otherflash = 'grey'
- outcome = 0
- try:
- self.canvas.itemconfig(self.item_id, fill=myflash)
- self.canvas.itemconfig(other.item_id, fill=otherflash)
- self.array.wait(500)
- finally:
- self.canvas.itemconfig(self.item_id, fill=myfill)
- self.canvas.itemconfig(other.item_id, fill=otherfill)
- return outcome
-
- def position(self):
- x1 = (self.index+1)*XGRID - WIDTH//2
- x2 = x1+WIDTH
- y2 = (self.array.maxvalue+1)*YGRID
- y1 = y2 - (self.value)*YGRID
- return x1, y1, x2, y2
-
- def nearestindex(self, x):
- return int(round(float(x)/XGRID)) - 1
-
-
-# Subroutines that don't need an object
-
-def steps(here, there):
- nsteps = abs(here - there)
- if nsteps <= 3:
- nsteps = nsteps * 3
- elif nsteps <= 5:
- nsteps = nsteps * 2
- elif nsteps > 10:
- nsteps = 10
- return nsteps
-
-def interpolate(oldpts, newpts, n):
- if len(oldpts) != len(newpts):
- raise ValueError("can't interpolate arrays of different length")
- pts = [0]*len(oldpts)
- res = [tuple(oldpts)]
- for i in range(1, n):
- for k in range(len(pts)):
- pts[k] = oldpts[k] + (newpts[k] - oldpts[k])*i//n
- res.append(tuple(pts))
- res.append(tuple(newpts))
- return res
-
-
-# Various (un)sorting algorithms
-
-def uniform(array):
- size = array.getsize()
- array.setdata([(size+1)//2] * size)
- array.reset("Uniform data, size %d" % size)
-
-def distinct(array):
- size = array.getsize()
- array.setdata(range(1, size+1))
- array.reset("Distinct data, size %d" % size)
-
-def randomize(array):
- array.reset("Randomizing")
- n = array.getsize()
- for i in range(n):
- j = random.randint(0, n-1)
- array.swap(i, j)
- array.message("Randomized")
-
-def insertionsort(array):
- size = array.getsize()
- array.reset("Insertion sort")
- for i in range(1, size):
- j = i-1
- while j >= 0:
- if array.compare(j, j+1) <= 0:
- break
- array.swap(j, j+1)
- j = j-1
- array.message("Sorted")
-
-def selectionsort(array):
- size = array.getsize()
- array.reset("Selection sort")
- try:
- for i in range(size):
- array.show_partition(i, size)
- for j in range(i+1, size):
- if array.compare(i, j) > 0:
- array.swap(i, j)
- array.message("Sorted")
- finally:
- array.hide_partition()
-
-def bubblesort(array):
- size = array.getsize()
- array.reset("Bubble sort")
- for i in range(size):
- for j in range(1, size):
- if array.compare(j-1, j) > 0:
- array.swap(j-1, j)
- array.message("Sorted")
-
-def quicksort(array):
- size = array.getsize()
- array.reset("Quicksort")
- try:
- stack = [(0, size)]
- while stack:
- first, last = stack[-1]
- del stack[-1]
- array.show_partition(first, last)
- if last-first < 5:
- array.message("Insertion sort")
- for i in range(first+1, last):
- j = i-1
- while j >= first:
- if array.compare(j, j+1) <= 0:
- break
- array.swap(j, j+1)
- j = j-1
- continue
- array.message("Choosing pivot")
- 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:
- array.swap(k, j)
- if array.compare(j, i) < 0:
- array.swap(j, i)
- pivot = j
- array.show_pivot(pivot)
- array.message("Pivot at left of partition")
- array.wait(1000)
- left = first
- right = last
- while True:
- array.message("Sweep right pointer")
- right = right-1
- array.show_right(right)
- while right > first and array.compare(right, pivot) >= 0:
- right = right-1
- array.show_right(right)
- array.message("Sweep left pointer")
- left = left+1
- array.show_left(left)
- while left < last and array.compare(left, pivot) <= 0:
- left = left+1
- array.show_left(left)
- if left > right:
- array.message("End of partition")
- break
- array.message("Swap items")
- array.swap(left, right)
- array.message("Swap pivot back")
- array.swap(pivot, right)
- n1 = right-first
- n2 = last-left
- if n1 > 1: stack.append((first, right))
- if n2 > 1: stack.append((left, last))
- array.message("Sorted")
- finally:
- array.hide_partition()
-
-def demosort(array):
- while True:
- for alg in [quicksort, insertionsort, selectionsort, bubblesort]:
- randomize(array)
- alg(array)
-
-
-# Sort demo class -- usable as a Grail applet
-
-class SortDemo:
-
- def __init__(self, master, size=15):
- self.master = master
- self.size = size
- self.busy = 0
- self.array = Array(self.master)
-
- self.botframe = Frame(master)
- self.botframe.pack(side=BOTTOM)
- self.botleftframe = Frame(self.botframe)
- self.botleftframe.pack(side=LEFT, fill=Y)
- self.botrightframe = Frame(self.botframe)
- self.botrightframe.pack(side=RIGHT, fill=Y)
-
- self.b_qsort = Button(self.botleftframe,
- text="Quicksort", command=self.c_qsort)
- self.b_qsort.pack(fill=X)
- self.b_isort = Button(self.botleftframe,
- text="Insertion sort", command=self.c_isort)
- self.b_isort.pack(fill=X)
- self.b_ssort = Button(self.botleftframe,
- text="Selection sort", command=self.c_ssort)
- self.b_ssort.pack(fill=X)
- self.b_bsort = Button(self.botleftframe,
- text="Bubble sort", command=self.c_bsort)
- self.b_bsort.pack(fill=X)
-
- # Terrible hack to overcome limitation of OptionMenu...
- class MyIntVar(IntVar):
- def __init__(self, master, demo):
- self.demo = demo
- IntVar.__init__(self, master)
- def set(self, value):
- IntVar.set(self, value)
- if str(value) != '0':
- self.demo.resize(value)
-
- self.v_size = MyIntVar(self.master, self)
- self.v_size.set(size)
- sizes = [1, 2, 3, 4] + list(range(5, 55, 5))
- if self.size not in sizes:
- sizes.append(self.size)
- sizes.sort()
- self.m_size = OptionMenu(self.botleftframe, self.v_size, *sizes)
- self.m_size.pack(fill=X)
-
- self.v_speed = StringVar(self.master)
- self.v_speed.set("normal")
- self.m_speed = OptionMenu(self.botleftframe, self.v_speed,
- "single-step", "normal", "fast", "fastest")
- self.m_speed.pack(fill=X)
-
- self.b_step = Button(self.botleftframe,
- text="Step", command=self.c_step)
- self.b_step.pack(fill=X)
-
- self.b_randomize = Button(self.botrightframe,
- text="Randomize", command=self.c_randomize)
- self.b_randomize.pack(fill=X)
- self.b_uniform = Button(self.botrightframe,
- text="Uniform", command=self.c_uniform)
- self.b_uniform.pack(fill=X)
- self.b_distinct = Button(self.botrightframe,
- text="Distinct", command=self.c_distinct)
- self.b_distinct.pack(fill=X)
- self.b_demo = Button(self.botrightframe,
- text="Demo", command=self.c_demo)
- self.b_demo.pack(fill=X)
- self.b_cancel = Button(self.botrightframe,
- text="Cancel", command=self.c_cancel)
- self.b_cancel.pack(fill=X)
- self.b_cancel.config(state=DISABLED)
- self.b_quit = Button(self.botrightframe,
- text="Quit", command=self.c_quit)
- self.b_quit.pack(fill=X)
-
- def resize(self, newsize):
- if self.busy:
- self.master.bell()
- return
- self.size = newsize
- self.array.setdata(range(1, self.size+1))
-
- def c_qsort(self):
- self.run(quicksort)
-
- def c_isort(self):
- self.run(insertionsort)
-
- def c_ssort(self):
- self.run(selectionsort)
-
- def c_bsort(self):
- self.run(bubblesort)
-
- def c_demo(self):
- self.run(demosort)
-
- def c_randomize(self):
- self.run(randomize)
-
- def c_uniform(self):
- self.run(uniform)
-
- def c_distinct(self):
- self.run(distinct)
-
- def run(self, func):
- if self.busy:
- self.master.bell()
- return
- self.busy = 1
- self.array.setspeed(self.v_speed.get())
- self.b_cancel.config(state=NORMAL)
- try:
- func(self.array)
- except Array.Cancelled:
- pass
- self.b_cancel.config(state=DISABLED)
- self.busy = 0
-
- def c_cancel(self):
- if not self.busy:
- self.master.bell()
- return
- self.array.cancel()
-
- def c_step(self):
- if not self.busy:
- self.master.bell()
- return
- self.v_speed.set("single-step")
- self.array.setspeed("single-step")
- self.array.step()
-
- def c_quit(self):
- if self.busy:
- self.array.cancel()
- self.master.after_idle(self.master.quit)
-
-
-# Main program -- for stand-alone operation outside Grail
-
-def main():
- root = Tk()
- demo = SortDemo(root)
- root.protocol('WM_DELETE_WINDOW', demo.c_quit)
- root.mainloop()
-
-if __name__ == '__main__':
- main()
diff --git a/Tools/demo/spreadsheet.py b/Tools/demo/spreadsheet.py
deleted file mode 100755
index bf88820..0000000
--- a/Tools/demo/spreadsheet.py
+++ /dev/null
@@ -1,829 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-SS1 -- a spreadsheet-like application.
-"""
-
-import os
-import re
-import sys
-from xml.parsers import expat
-from xml.sax.saxutils import escape
-
-LEFT, CENTER, RIGHT = "LEFT", "CENTER", "RIGHT"
-
-def ljust(x, n):
- return x.ljust(n)
-def center(x, n):
- return x.center(n)
-def rjust(x, n):
- return x.rjust(n)
-align2action = {LEFT: ljust, CENTER: center, RIGHT: rjust}
-
-align2xml = {LEFT: "left", CENTER: "center", RIGHT: "right"}
-xml2align = {"left": LEFT, "center": CENTER, "right": RIGHT}
-
-align2anchor = {LEFT: "w", CENTER: "center", RIGHT: "e"}
-
-def sum(seq):
- total = 0
- for x in seq:
- if x is not None:
- total += x
- return total
-
-class Sheet:
-
- def __init__(self):
- self.cells = {} # {(x, y): cell, ...}
- self.ns = dict(
- cell = self.cellvalue,
- cells = self.multicellvalue,
- sum = sum,
- )
-
- def cellvalue(self, x, y):
- cell = self.getcell(x, y)
- if hasattr(cell, 'recalc'):
- return cell.recalc(self.ns)
- else:
- return cell
-
- def multicellvalue(self, x1, y1, x2, y2):
- if x1 > x2:
- x1, x2 = x2, x1
- if y1 > y2:
- y1, y2 = y2, y1
- seq = []
- for y in range(y1, y2+1):
- for x in range(x1, x2+1):
- seq.append(self.cellvalue(x, y))
- return seq
-
- def getcell(self, x, y):
- return self.cells.get((x, y))
-
- def setcell(self, x, y, cell):
- assert x > 0 and y > 0
- assert isinstance(cell, BaseCell)
- self.cells[x, y] = cell
-
- def clearcell(self, x, y):
- try:
- del self.cells[x, y]
- except KeyError:
- pass
-
- def clearcells(self, x1, y1, x2, y2):
- for xy in self.selectcells(x1, y1, x2, y2):
- del self.cells[xy]
-
- def clearrows(self, y1, y2):
- self.clearcells(0, y1, sys.maxsize, y2)
-
- def clearcolumns(self, x1, x2):
- self.clearcells(x1, 0, x2, sys.maxsize)
-
- def selectcells(self, x1, y1, x2, y2):
- if x1 > x2:
- x1, x2 = x2, x1
- if y1 > y2:
- y1, y2 = y2, y1
- return [(x, y) for x, y in self.cells
- if x1 <= x <= x2 and y1 <= y <= y2]
-
- def movecells(self, x1, y1, x2, y2, dx, dy):
- if dx == 0 and dy == 0:
- return
- if x1 > x2:
- x1, x2 = x2, x1
- if y1 > y2:
- y1, y2 = y2, y1
- assert x1+dx > 0 and y1+dy > 0
- new = {}
- for x, y in self.cells:
- cell = self.cells[x, y]
- if hasattr(cell, 'renumber'):
- cell = cell.renumber(x1, y1, x2, y2, dx, dy)
- if x1 <= x <= x2 and y1 <= y <= y2:
- x += dx
- y += dy
- new[x, y] = cell
- self.cells = new
-
- def insertrows(self, y, n):
- assert n > 0
- self.movecells(0, y, sys.maxsize, sys.maxsize, 0, n)
-
- def deleterows(self, y1, y2):
- if y1 > y2:
- y1, y2 = y2, y1
- self.clearrows(y1, y2)
- self.movecells(0, y2+1, sys.maxsize, sys.maxsize, 0, y1-y2-1)
-
- def insertcolumns(self, x, n):
- assert n > 0
- self.movecells(x, 0, sys.maxsize, sys.maxsize, n, 0)
-
- def deletecolumns(self, x1, x2):
- if x1 > x2:
- x1, x2 = x2, x1
- self.clearcells(x1, x2)
- self.movecells(x2+1, 0, sys.maxsize, sys.maxsize, x1-x2-1, 0)
-
- def getsize(self):
- maxx = maxy = 0
- for x, y in self.cells:
- maxx = max(maxx, x)
- maxy = max(maxy, y)
- return maxx, maxy
-
- def reset(self):
- for cell in self.cells.values():
- if hasattr(cell, 'reset'):
- cell.reset()
-
- def recalc(self):
- self.reset()
- for cell in self.cells.values():
- if hasattr(cell, 'recalc'):
- cell.recalc(self.ns)
-
- def display(self):
- maxx, maxy = self.getsize()
- width, height = maxx+1, maxy+1
- colwidth = [1] * width
- full = {}
- # Add column heading labels in row 0
- for x in range(1, width):
- full[x, 0] = text, alignment = colnum2name(x), RIGHT
- colwidth[x] = max(colwidth[x], len(text))
- # Add row labels in column 0
- for y in range(1, height):
- full[0, y] = text, alignment = str(y), RIGHT
- colwidth[0] = max(colwidth[0], len(text))
- # Add sheet cells in columns with x>0 and y>0
- for (x, y), cell in self.cells.items():
- if x <= 0 or y <= 0:
- continue
- if hasattr(cell, 'recalc'):
- cell.recalc(self.ns)
- if hasattr(cell, 'format'):
- text, alignment = cell.format()
- assert isinstance(text, str)
- assert alignment in (LEFT, CENTER, RIGHT)
- else:
- text = str(cell)
- if isinstance(cell, str):
- alignment = LEFT
- else:
- alignment = RIGHT
- full[x, y] = (text, alignment)
- colwidth[x] = max(colwidth[x], len(text))
- # Calculate the horizontal separator line (dashes and dots)
- sep = ""
- for x in range(width):
- if sep:
- sep += "+"
- sep += "-"*colwidth[x]
- # Now print The full grid
- for y in range(height):
- line = ""
- for x in range(width):
- text, alignment = full.get((x, y)) or ("", LEFT)
- text = align2action[alignment](text, colwidth[x])
- if line:
- line += '|'
- line += text
- print(line)
- if y == 0:
- print(sep)
-
- def xml(self):
- out = ['<spreadsheet>']
- for (x, y), cell in self.cells.items():
- if hasattr(cell, 'xml'):
- cellxml = cell.xml()
- else:
- cellxml = '<value>%s</value>' % escape(cell)
- out.append('<cell row="%s" col="%s">\n %s\n</cell>' %
- (y, x, cellxml))
- out.append('</spreadsheet>')
- return '\n'.join(out)
-
- def save(self, filename):
- text = self.xml()
- with open(filename, "w", encoding='utf-8') as f:
- f.write(text)
- if text and not text.endswith('\n'):
- f.write('\n')
-
- def load(self, filename):
- with open(filename, 'rb') as f:
- SheetParser(self).parsefile(f)
-
-class SheetParser:
-
- def __init__(self, sheet):
- self.sheet = sheet
-
- def parsefile(self, f):
- parser = expat.ParserCreate()
- parser.StartElementHandler = self.startelement
- parser.EndElementHandler = self.endelement
- parser.CharacterDataHandler = self.data
- parser.ParseFile(f)
-
- def startelement(self, tag, attrs):
- method = getattr(self, 'start_'+tag, None)
- if method:
- method(attrs)
- self.texts = []
-
- def data(self, text):
- self.texts.append(text)
-
- def endelement(self, tag):
- method = getattr(self, 'end_'+tag, None)
- if method:
- method("".join(self.texts))
-
- def start_cell(self, attrs):
- self.y = int(attrs.get("row"))
- self.x = int(attrs.get("col"))
-
- def start_value(self, attrs):
- self.fmt = attrs.get('format')
- self.alignment = xml2align.get(attrs.get('align'))
-
- start_formula = start_value
-
- def end_int(self, text):
- try:
- self.value = int(text)
- except (TypeError, ValueError):
- self.value = None
-
- end_long = end_int
-
- def end_double(self, text):
- try:
- self.value = float(text)
- except (TypeError, ValueError):
- self.value = None
-
- def end_complex(self, text):
- try:
- self.value = complex(text)
- except (TypeError, ValueError):
- self.value = None
-
- def end_string(self, text):
- self.value = text
-
- def end_value(self, text):
- if isinstance(self.value, BaseCell):
- self.cell = self.value
- elif isinstance(self.value, str):
- self.cell = StringCell(self.value,
- self.fmt or "%s",
- self.alignment or LEFT)
- else:
- self.cell = NumericCell(self.value,
- self.fmt or "%s",
- self.alignment or RIGHT)
-
- def end_formula(self, text):
- self.cell = FormulaCell(text,
- self.fmt or "%s",
- self.alignment or RIGHT)
-
- def end_cell(self, text):
- self.sheet.setcell(self.x, self.y, self.cell)
-
-class BaseCell:
- __init__ = None # Must provide
- """Abstract base class for sheet cells.
-
- Subclasses may but needn't provide the following APIs:
-
- cell.reset() -- prepare for recalculation
- cell.recalc(ns) -> value -- recalculate formula
- cell.format() -> (value, alignment) -- return formatted value
- cell.xml() -> string -- return XML
- """
-
-class NumericCell(BaseCell):
-
- def __init__(self, value, fmt="%s", alignment=RIGHT):
- assert isinstance(value, (int, float, complex))
- assert alignment in (LEFT, CENTER, RIGHT)
- self.value = value
- self.fmt = fmt
- self.alignment = alignment
-
- def recalc(self, ns):
- return self.value
-
- def format(self):
- try:
- text = self.fmt % self.value
- except:
- text = str(self.value)
- return text, self.alignment
-
- def xml(self):
- method = getattr(self, '_xml_' + type(self.value).__name__)
- return '<value align="%s" format="%s">%s</value>' % (
- align2xml[self.alignment],
- self.fmt,
- method())
-
- def _xml_int(self):
- if -2**31 <= self.value < 2**31:
- return '<int>%s</int>' % self.value
- else:
- return '<long>%s</long>' % self.value
-
- def _xml_float(self):
- return '<double>%r</double>' % self.value
-
- def _xml_complex(self):
- return '<complex>%r</complex>' % self.value
-
-class StringCell(BaseCell):
-
- def __init__(self, text, fmt="%s", alignment=LEFT):
- assert isinstance(text, str)
- assert alignment in (LEFT, CENTER, RIGHT)
- self.text = text
- self.fmt = fmt
- self.alignment = alignment
-
- def recalc(self, ns):
- return self.text
-
- def format(self):
- return self.text, self.alignment
-
- def xml(self):
- s = '<value align="%s" format="%s"><string>%s</string></value>'
- return s % (
- align2xml[self.alignment],
- self.fmt,
- escape(self.text))
-
-class FormulaCell(BaseCell):
-
- def __init__(self, formula, fmt="%s", alignment=RIGHT):
- assert alignment in (LEFT, CENTER, RIGHT)
- self.formula = formula
- self.translated = translate(self.formula)
- self.fmt = fmt
- self.alignment = alignment
- self.reset()
-
- def reset(self):
- self.value = None
-
- def recalc(self, ns):
- if self.value is None:
- try:
- self.value = eval(self.translated, ns)
- except:
- exc = sys.exc_info()[0]
- if hasattr(exc, "__name__"):
- self.value = exc.__name__
- else:
- self.value = str(exc)
- return self.value
-
- def format(self):
- try:
- text = self.fmt % self.value
- except:
- text = str(self.value)
- return text, self.alignment
-
- def xml(self):
- return '<formula align="%s" format="%s">%s</formula>' % (
- align2xml[self.alignment],
- self.fmt,
- escape(self.formula))
-
- def renumber(self, x1, y1, x2, y2, dx, dy):
- out = []
- for part in re.split(r'(\w+)', self.formula):
- m = re.match('^([A-Z]+)([1-9][0-9]*)$', part)
- if m is not None:
- sx, sy = m.groups()
- x = colname2num(sx)
- y = int(sy)
- if x1 <= x <= x2 and y1 <= y <= y2:
- part = cellname(x+dx, y+dy)
- out.append(part)
- return FormulaCell("".join(out), self.fmt, self.alignment)
-
-def translate(formula):
- """Translate a formula containing fancy cell names to valid Python code.
-
- Examples:
- B4 -> cell(2, 4)
- B4:Z100 -> cells(2, 4, 26, 100)
- """
- out = []
- for part in re.split(r"(\w+(?::\w+)?)", formula):
- m = re.match(r"^([A-Z]+)([1-9][0-9]*)(?::([A-Z]+)([1-9][0-9]*))?$", part)
- if m is None:
- out.append(part)
- else:
- x1, y1, x2, y2 = m.groups()
- x1 = colname2num(x1)
- if x2 is None:
- s = "cell(%s, %s)" % (x1, y1)
- else:
- x2 = colname2num(x2)
- s = "cells(%s, %s, %s, %s)" % (x1, y1, x2, y2)
- out.append(s)
- return "".join(out)
-
-def cellname(x, y):
- "Translate a cell coordinate to a fancy cell name (e.g. (1, 1)->'A1')."
- assert x > 0 # Column 0 has an empty name, so can't use that
- return colnum2name(x) + str(y)
-
-def colname2num(s):
- "Translate a column name to number (e.g. 'A'->1, 'Z'->26, 'AA'->27)."
- s = s.upper()
- n = 0
- for c in s:
- assert 'A' <= c <= 'Z'
- n = n*26 + ord(c) - ord('A') + 1
- return n
-
-def colnum2name(n):
- "Translate a column number to name (e.g. 1->'A', etc.)."
- assert n > 0
- s = ""
- while n:
- n, m = divmod(n-1, 26)
- s = chr(m+ord('A')) + s
- return s
-
-import tkinter as Tk
-
-class SheetGUI:
-
- """Beginnings of a GUI for a spreadsheet.
-
- TO DO:
- - clear multiple cells
- - Insert, clear, remove rows or columns
- - Show new contents while typing
- - Scroll bars
- - Grow grid when window is grown
- - Proper menus
- - Undo, redo
- - Cut, copy and paste
- - Formatting and alignment
- """
-
- def __init__(self, filename="sheet1.xml", rows=10, columns=5):
- """Constructor.
-
- Load the sheet from the filename argument.
- Set up the Tk widget tree.
- """
- # Create and load the sheet
- self.filename = filename
- self.sheet = Sheet()
- if os.path.isfile(filename):
- self.sheet.load(filename)
- # Calculate the needed grid size
- maxx, maxy = self.sheet.getsize()
- rows = max(rows, maxy)
- columns = max(columns, maxx)
- # Create the widgets
- self.root = Tk.Tk()
- self.root.wm_title("Spreadsheet: %s" % self.filename)
- self.beacon = Tk.Label(self.root, text="A1",
- font=('helvetica', 16, 'bold'))
- self.entry = Tk.Entry(self.root)
- self.savebutton = Tk.Button(self.root, text="Save",
- command=self.save)
- self.cellgrid = Tk.Frame(self.root)
- # Configure the widget lay-out
- self.cellgrid.pack(side="bottom", expand=1, fill="both")
- self.beacon.pack(side="left")
- self.savebutton.pack(side="right")
- self.entry.pack(side="left", expand=1, fill="x")
- # Bind some events
- self.entry.bind("<Return>", self.return_event)
- self.entry.bind("<Shift-Return>", self.shift_return_event)
- self.entry.bind("<Tab>", self.tab_event)
- self.entry.bind("<Shift-Tab>", self.shift_tab_event)
- self.entry.bind("<Delete>", self.delete_event)
- self.entry.bind("<Escape>", self.escape_event)
- # Now create the cell grid
- self.makegrid(rows, columns)
- # Select the top-left cell
- self.currentxy = None
- self.cornerxy = None
- self.setcurrent(1, 1)
- # Copy the sheet cells to the GUI cells
- self.sync()
-
- def delete_event(self, event):
- if self.cornerxy != self.currentxy and self.cornerxy is not None:
- self.sheet.clearcells(*(self.currentxy + self.cornerxy))
- else:
- self.sheet.clearcell(*self.currentxy)
- self.sync()
- self.entry.delete(0, 'end')
- return "break"
-
- def escape_event(self, event):
- x, y = self.currentxy
- self.load_entry(x, y)
-
- def load_entry(self, x, y):
- cell = self.sheet.getcell(x, y)
- if cell is None:
- text = ""
- elif isinstance(cell, FormulaCell):
- text = '=' + cell.formula
- else:
- text, alignment = cell.format()
- self.entry.delete(0, 'end')
- self.entry.insert(0, text)
- self.entry.selection_range(0, 'end')
-
- def makegrid(self, rows, columns):
- """Helper to create the grid of GUI cells.
-
- The edge (x==0 or y==0) is filled with labels; the rest is real cells.
- """
- self.rows = rows
- self.columns = columns
- self.gridcells = {}
- # Create the top left corner cell (which selects all)
- cell = Tk.Label(self.cellgrid, relief='raised')
- cell.grid_configure(column=0, row=0, sticky='NSWE')
- cell.bind("<ButtonPress-1>", self.selectall)
- # Create the top row of labels, and configure the grid columns
- for x in range(1, columns+1):
- self.cellgrid.grid_columnconfigure(x, minsize=64)
- cell = Tk.Label(self.cellgrid, text=colnum2name(x), relief='raised')
- cell.grid_configure(column=x, row=0, sticky='WE')
- self.gridcells[x, 0] = cell
- cell.__x = x
- cell.__y = 0
- cell.bind("<ButtonPress-1>", self.selectcolumn)
- cell.bind("<B1-Motion>", self.extendcolumn)
- cell.bind("<ButtonRelease-1>", self.extendcolumn)
- cell.bind("<Shift-Button-1>", self.extendcolumn)
- # Create the leftmost column of labels
- for y in range(1, rows+1):
- cell = Tk.Label(self.cellgrid, text=str(y), relief='raised')
- cell.grid_configure(column=0, row=y, sticky='WE')
- self.gridcells[0, y] = cell
- cell.__x = 0
- cell.__y = y
- cell.bind("<ButtonPress-1>", self.selectrow)
- cell.bind("<B1-Motion>", self.extendrow)
- cell.bind("<ButtonRelease-1>", self.extendrow)
- cell.bind("<Shift-Button-1>", self.extendrow)
- # Create the real cells
- for x in range(1, columns+1):
- for y in range(1, rows+1):
- cell = Tk.Label(self.cellgrid, relief='sunken',
- bg='white', fg='black')
- cell.grid_configure(column=x, row=y, sticky='NSWE')
- self.gridcells[x, y] = cell
- cell.__x = x
- cell.__y = y
- # Bind mouse events
- cell.bind("<ButtonPress-1>", self.press)
- cell.bind("<B1-Motion>", self.motion)
- cell.bind("<ButtonRelease-1>", self.release)
- cell.bind("<Shift-Button-1>", self.release)
-
- def selectall(self, event):
- self.setcurrent(1, 1)
- self.setcorner(sys.maxsize, sys.maxsize)
-
- def selectcolumn(self, event):
- x, y = self.whichxy(event)
- self.setcurrent(x, 1)
- self.setcorner(x, sys.maxsize)
-
- def extendcolumn(self, event):
- x, y = self.whichxy(event)
- if x > 0:
- self.setcurrent(self.currentxy[0], 1)
- self.setcorner(x, sys.maxsize)
-
- def selectrow(self, event):
- x, y = self.whichxy(event)
- self.setcurrent(1, y)
- self.setcorner(sys.maxsize, y)
-
- def extendrow(self, event):
- x, y = self.whichxy(event)
- if y > 0:
- self.setcurrent(1, self.currentxy[1])
- self.setcorner(sys.maxsize, y)
-
- def press(self, event):
- x, y = self.whichxy(event)
- if x > 0 and y > 0:
- self.setcurrent(x, y)
-
- def motion(self, event):
- x, y = self.whichxy(event)
- if x > 0 and y > 0:
- self.setcorner(x, y)
-
- release = motion
-
- def whichxy(self, event):
- w = self.cellgrid.winfo_containing(event.x_root, event.y_root)
- if w is not None and isinstance(w, Tk.Label):
- try:
- return w.__x, w.__y
- except AttributeError:
- pass
- return 0, 0
-
- def save(self):
- self.sheet.save(self.filename)
-
- def setcurrent(self, x, y):
- "Make (x, y) the current cell."
- if self.currentxy is not None:
- self.change_cell()
- self.clearfocus()
- self.beacon['text'] = cellname(x, y)
- self.load_entry(x, y)
- self.entry.focus_set()
- self.currentxy = x, y
- self.cornerxy = None
- gridcell = self.gridcells.get(self.currentxy)
- if gridcell is not None:
- gridcell['bg'] = 'yellow'
-
- def setcorner(self, x, y):
- if self.currentxy is None or self.currentxy == (x, y):
- self.setcurrent(x, y)
- return
- self.clearfocus()
- self.cornerxy = x, y
- x1, y1 = self.currentxy
- x2, y2 = self.cornerxy or self.currentxy
- if x1 > x2:
- x1, x2 = x2, x1
- if y1 > y2:
- y1, y2 = y2, y1
- for (x, y), cell in self.gridcells.items():
- if x1 <= x <= x2 and y1 <= y <= y2:
- cell['bg'] = 'lightBlue'
- gridcell = self.gridcells.get(self.currentxy)
- if gridcell is not None:
- gridcell['bg'] = 'yellow'
- self.setbeacon(x1, y1, x2, y2)
-
- def setbeacon(self, x1, y1, x2, y2):
- if x1 == y1 == 1 and x2 == y2 == sys.maxsize:
- name = ":"
- elif (x1, x2) == (1, sys.maxsize):
- if y1 == y2:
- name = "%d" % y1
- else:
- name = "%d:%d" % (y1, y2)
- elif (y1, y2) == (1, sys.maxsize):
- if x1 == x2:
- name = "%s" % colnum2name(x1)
- else:
- name = "%s:%s" % (colnum2name(x1), colnum2name(x2))
- else:
- name1 = cellname(*self.currentxy)
- name2 = cellname(*self.cornerxy)
- name = "%s:%s" % (name1, name2)
- self.beacon['text'] = name
-
-
- def clearfocus(self):
- if self.currentxy is not None:
- x1, y1 = self.currentxy
- x2, y2 = self.cornerxy or self.currentxy
- if x1 > x2:
- x1, x2 = x2, x1
- if y1 > y2:
- y1, y2 = y2, y1
- for (x, y), cell in self.gridcells.items():
- if x1 <= x <= x2 and y1 <= y <= y2:
- cell['bg'] = 'white'
-
- def return_event(self, event):
- "Callback for the Return key."
- self.change_cell()
- x, y = self.currentxy
- self.setcurrent(x, y+1)
- return "break"
-
- def shift_return_event(self, event):
- "Callback for the Return key with Shift modifier."
- self.change_cell()
- x, y = self.currentxy
- self.setcurrent(x, max(1, y-1))
- return "break"
-
- def tab_event(self, event):
- "Callback for the Tab key."
- self.change_cell()
- x, y = self.currentxy
- self.setcurrent(x+1, y)
- return "break"
-
- def shift_tab_event(self, event):
- "Callback for the Tab key with Shift modifier."
- self.change_cell()
- x, y = self.currentxy
- self.setcurrent(max(1, x-1), y)
- return "break"
-
- def change_cell(self):
- "Set the current cell from the entry widget."
- x, y = self.currentxy
- text = self.entry.get()
- cell = None
- if text.startswith('='):
- cell = FormulaCell(text[1:])
- else:
- for cls in int, float, complex:
- try:
- value = cls(text)
- except (TypeError, ValueError):
- continue
- else:
- cell = NumericCell(value)
- break
- if cell is None and text:
- cell = StringCell(text)
- if cell is None:
- self.sheet.clearcell(x, y)
- else:
- self.sheet.setcell(x, y, cell)
- self.sync()
-
- def sync(self):
- "Fill the GUI cells from the sheet cells."
- self.sheet.recalc()
- for (x, y), gridcell in self.gridcells.items():
- if x == 0 or y == 0:
- continue
- cell = self.sheet.getcell(x, y)
- if cell is None:
- gridcell['text'] = ""
- else:
- if hasattr(cell, 'format'):
- text, alignment = cell.format()
- else:
- text, alignment = str(cell), LEFT
- gridcell['text'] = text
- gridcell['anchor'] = align2anchor[alignment]
-
-
-def test_basic():
- "Basic non-gui self-test."
- a = Sheet()
- for x in range(1, 11):
- for y in range(1, 11):
- if x == 1:
- cell = NumericCell(y)
- elif y == 1:
- cell = NumericCell(x)
- else:
- c1 = cellname(x, 1)
- c2 = cellname(1, y)
- formula = "%s*%s" % (c1, c2)
- cell = FormulaCell(formula)
- a.setcell(x, y, cell)
-## if os.path.isfile("sheet1.xml"):
-## print "Loading from sheet1.xml"
-## a.load("sheet1.xml")
- a.display()
- a.save("sheet1.xml")
-
-def test_gui():
- "GUI test."
- if sys.argv[1:]:
- filename = sys.argv[1]
- else:
- filename = "sheet1.xml"
- g = SheetGUI(filename)
- g.root.mainloop()
-
-if __name__ == '__main__':
- #test_basic()
- test_gui()
diff --git a/Tools/demo/vector.py b/Tools/demo/vector.py
deleted file mode 100755
index 6df1f50..0000000
--- a/Tools/demo/vector.py
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-A demonstration of classes and their special methods in Python.
-"""
-
-class Vec:
- """A simple vector class.
-
- Instances of the Vec class can be constructed from numbers
-
- >>> a = Vec(1, 2, 3)
- >>> b = Vec(3, 2, 1)
-
- added
- >>> a + b
- Vec(4, 4, 4)
-
- subtracted
- >>> a - b
- Vec(-2, 0, 2)
-
- and multiplied by a scalar on the left
- >>> 3.0 * a
- Vec(3.0, 6.0, 9.0)
-
- or on the right
- >>> a * 3.0
- Vec(3.0, 6.0, 9.0)
-
- and dot product
- >>> a.dot(b)
- 10
-
- and printed in vector notation
- >>> print(a)
- <1 2 3>
-
- """
-
- def __init__(self, *v):
- self.v = list(v)
-
- @classmethod
- def fromlist(cls, v):
- if not isinstance(v, list):
- raise TypeError
- inst = cls()
- inst.v = v
- return inst
-
- def __repr__(self):
- args = ', '.join([repr(x) for x in self.v])
- return f'{type(self).__name__}({args})'
-
- def __str__(self):
- components = ' '.join([str(x) for x in self.v])
- return f'<{components}>'
-
- def __len__(self):
- return len(self.v)
-
- def __getitem__(self, i):
- return self.v[i]
-
- def __add__(self, other):
- "Element-wise addition"
- v = [x + y for x, y in zip(self.v, other.v)]
- return Vec.fromlist(v)
-
- def __sub__(self, other):
- "Element-wise subtraction"
- v = [x - y for x, y in zip(self.v, other.v)]
- return Vec.fromlist(v)
-
- def __mul__(self, scalar):
- "Multiply by scalar"
- v = [x * scalar for x in self.v]
- return Vec.fromlist(v)
-
- __rmul__ = __mul__
-
- def dot(self, other):
- "Vector dot product"
- if not isinstance(other, Vec):
- raise TypeError
- return sum(x_i * y_i for (x_i, y_i) in zip(self, other))
-
-
-def test():
- import doctest
- doctest.testmod()
-
-test()