]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Interactively create a distribution from a sourcetree.
authorJack Jansen <jack.jansen@cwi.nl>
Thu, 31 Aug 1995 13:50:16 +0000 (13:50 +0000)
committerJack Jansen <jack.jansen@cwi.nl>
Thu, 31 Aug 1995 13:50:16 +0000 (13:50 +0000)
Not yet fully tested.

Mac/scripts/MkDistr.py [new file with mode: 0644]
Mac/scripts/MkDistr.rsrc.hqx [new file with mode: 0644]
Mac/scripts/MkDistr_ui.py [new file with mode: 0644]

diff --git a/Mac/scripts/MkDistr.py b/Mac/scripts/MkDistr.py
new file mode 100644 (file)
index 0000000..deda71b
--- /dev/null
@@ -0,0 +1,280 @@
+#
+# Interactively decide what to distribute
+#
+# The distribution type is signalled by a letter. The currently
+# defined letters are:
+# p            PPC normal distribution
+# P            PPC development distribution
+# m            68K normal distribution
+# M            68K development distribution
+#
+# The exclude file signals files to always exclude,
+# The pattern file records are of the form
+# ('pm', '*.c')
+# This excludes all files ending in .c for normal distributions.
+#
+# The include file signals files and directories to include.
+# Records are of the form
+# ('pPmM', 'Lib')
+# This includes the Lib dir in all distributions
+# ('pPmM', 'Tools:bgen:AE:AppleEvents.py', 'Lib:MacToolbox:AppleEvents.py')
+# This includes the specified file, putting it in the given place.
+#
+from MkDistr_ui import *
+import fnmatch
+import regex
+import os
+import sys
+import macfs
+import macostools
+
+SyntaxError='Include/exclude file syntax error'
+
+class Matcher:
+       """Include/exclude database, common code"""
+       
+       def __init__(self, type, filename):
+               self.type = type
+               self.filename = filename
+               self.rawdata = []
+               self.parse(filename)
+               self.rawdata.sort()
+               self.rebuild()
+               self.modified = 0
+
+       def parse(self, dbfile):
+               try:
+                       fp = open(dbfile)
+               except IOError:
+                       return
+               data = fp.readlines()
+               fp.close()
+               for d in data:
+                       d = d[:-1]
+                       if not d or d[0] == '#': continue
+                       pat = self.parseline(d)
+                       self.rawdata.append(pat)
+                               
+       def parseline(self, line):
+               try:
+                       data = eval(line)
+               except:
+                       raise SyntaxError, line
+               if type(data) <> type(()) or len(data) not in (2,3):
+                       raise SyntaxError, line
+               if len(data) == 2:
+                       data = data + ('',)
+               return data
+               
+       def save(self):
+               fp = open(self.filename, 'w')
+               for d in self.rawdata:
+                       fp.write(`d`+'\n')
+               self.modified = 0
+                       
+       def add(self, value):
+               if len(value) == 2:
+                       value = value + ('',)
+               self.rawdata.append(value)
+               self.rebuild1(value)
+               self.modified = 1
+               
+       def delete(self, value):
+               key = value
+               for i in range(len(self.rawdata)):
+                       if self.rawdata[i][1] == key:
+                               del self.rawdata[i]
+                               self.unrebuild1(i, key)
+                               self.modified = 1
+                               return
+               print 'Not found!', key
+                               
+       def getall(self):
+               return map(lambda x: x[1], self.rawdata)
+       
+       def get(self, value):
+               for t, src, dst in self.rawdata:
+                       if src == value:
+                               return t, src, dst
+               print 'Not found!', value
+                               
+       def is_modified(self):
+               return self.modified
+                                                       
+class IncMatcher(Matcher):
+       """Include filename database and matching engine"""
+
+       def rebuild(self):
+               self.idict = {}
+               self.edict = {}
+               for v in self.rawdata:
+                       self.rebuild1(v)
+                       
+       def rebuild1(self, (tp, src, dst)):
+               if self.type in tp:
+                       if dst == '':
+                               dst = src
+                       self.idict[src] = dst
+               else:
+                       self.edict[src] = ''
+                       
+       def unrebuild1(self, num, src):
+               if self.idict.has_key(src):
+                       del self.idict[src]
+               else:
+                       del self.edict[src]
+       
+       def match(self, patharg):
+               removed = []
+               # First check the include directory
+               path = patharg
+               while 1:
+                       if self.idict.has_key(path):
+                               # We know of this path (or initial piece of path)
+                               dstpath = self.idict[path]
+                               # We do want it distributed. Tack on the tail.
+                               while removed:
+                                       dstpath = os.path.join(dstpath, removed[0])
+                                       removed = removed[1:]
+                               # Finally, if the resultant string ends in a separator
+                               # tack on our input filename
+                               if dstpath[-1] == os.sep:
+                                       dir, file = os.path.split(path)
+                                       dstpath = os.path.join(dstpath, path)
+                               return dstpath
+                       path, lastcomp = os.path.split(path)
+                       if not path:
+                               break
+                       removed[0:0] = [lastcomp]
+               # Next check the exclude directory
+               path = patharg
+               while 1:
+                       if self.edict.has_key(path):
+                               return ''
+                       path, lastcomp = os.path.split(path)
+                       if not path:
+                               break
+                       removed[0:0] = [lastcomp]
+               return None
+                       
+       def checksourcetree(self):
+               rv = []
+               for name in self.idict.keys():
+                       if not os.path.exists(name):
+                               rv.append(name)
+               return rv
+                               
+class ExcMatcher(Matcher):
+       """Exclude pattern database and matching engine"""
+
+       def rebuild(self):
+               self.relist = []
+               for v in self.rawdata:
+                       self.rebuild1(v)
+               
+       def rebuild1(self, (tp, src, dst)):
+               if self.type in tp:
+                       pat = fnmatch.translate(src)
+                       self.relist.append(regex.compile(pat))
+               else:
+                       self.relist.append(None)
+                       
+       def unrebuild1(self, num, src):
+               del self.relist[num]
+       
+       def match(self, path):
+               comps = os.path.split(path)
+               file = comps[-1]
+               for pat in self.relist:
+                       if pat and pat.match(file) == len(file):
+                               return 1
+               return 0                
+                
+               
+class Main:
+       """The main program glueing it all together"""
+       
+       def __init__(self):
+               InitUI()
+               fss, ok = macfs.GetDirectory('Source directory:')
+               if not ok:
+                       sys.exit(0)
+               os.chdir(fss.as_pathname())
+               self.typedist = GetType()
+               print 'TYPE', self.typedist
+               self.inc = IncMatcher(self.typedist, '(MkDistr.include)')
+               self.exc = ExcMatcher(self.typedist, '(MkDistr.exclude)')
+               self.ui = MkDistrUI(self)
+               self.ui.mainloop()
+               
+       def check(self):
+               return self.checkdir(':', 1)
+               
+       def checkdir(self, path, istop):
+               files = os.listdir(path)
+               rv = []
+               todo = []
+               for f in files:
+                       if self.exc.match(f):
+                               continue
+                       fullname = os.path.join(path, f)
+                       if self.inc.match(fullname) == None:
+                               if os.path.isdir(fullname):
+                                       todo.append(fullname)
+                               else:
+                                       rv.append(fullname)
+               for d in todo:
+                       if len(rv) > 100:
+                               if istop:
+                                       rv.append('... and more ...')
+                               return rv
+                       rv = rv + self.checkdir(d, 0)
+               return rv
+               
+       def run(self, destprefix):
+               missing = self.inc.checksourcetree()
+               if missing:
+                       print '==== Missing source files ===='
+                       for i in missing:
+                               print i
+                       print '==== Fix and retry ===='
+                       return
+               if not self.rundir(':', destprefix, 0):
+                       return
+               self.rundir(':', destprefix, 1)
+
+       def rundir(self, path, destprefix, doit):
+               files = os.listdir(path)
+               todo = []
+               rv = 1
+               for f in files:
+                       if self.exc.match(f):
+                               continue
+                       fullname = os.path.join(path, f)
+                       if os.path.isdir(fullname):
+                               todo.append(fullname)
+                       else:
+                               dest = self.inc.match(fullname)
+                               if dest == None:
+                                       print 'Not yet resolved:', fullname
+                                       rv = 0
+                               if dest:
+                                       if doit:
+                                               print 'COPY ', fullname
+                                               print '  -> ', os.path.join(destprefix, dest)
+                                               macostools.copy(fullname, os.path.join(destprefix, dest), 1)
+               for d in todo:
+                       if not self.rundir(d, destprefix, doit):
+                               rv = 0
+               return rv
+               
+       def save(self):
+               self.inc.save()
+               self.exc.save()
+               
+       def is_modified(self):
+               return self.inc.is_modified() or self.exc.is_modified()
+
+if __name__ == '__main__':
+       Main()
+       
diff --git a/Mac/scripts/MkDistr.rsrc.hqx b/Mac/scripts/MkDistr.rsrc.hqx
new file mode 100644 (file)
index 0000000..b8c4478
--- /dev/null
@@ -0,0 +1,31 @@
+(This file may be decompressed with BinHex 4.0)
+
+:$%eV4'PcG()ZFR0bB`"bFh*M8P0&4!%!N!F&SINN!*!%!3!!!!5[!!!$V`!!!2)8
+T8SJ&+9+%"5P5rJ6'6!)%!!!#"!!!!J3!!!)%!!!#!a0Dd4TFh4b,R*cFQ0b!J!!
+!(*cFQ058d9%!3$rN!3!!(*cFQ058d9%!3$rN!3!N"+XA"N$!*!'"D(rq"rrrJ!I
+rrm!(rrrJ"rrrm!IrrrJ(rrrm"rrrrJIrrri(rrrq"rrrrJIrrri(rrrq"rrrrJI
+rrri(rrrq"rrrrJIrrri(rrrq"rrrrJIrrri(rrrq"rrrrJIrrri(rrrq"rrrrJI
+rrri(rrrq"rrrrJIrrri(rrrq"rrrrJIrrri!!!!&3"F!$i!rJ'K!!8"!!%!N!8#
+!*!&&3"F!$i!rJ'K!!8"!!%!N!8#!3#3"-`!#!#3"B)")J#@!9`%!Np,!*!&JJ!+
+!*B!4!3'3f&ZBf9X!*!&C!$F!(B"@`8'8fpeFQ0P!*!&8!$F!')"@`8,8&"$)'4P
+GQ9XEh!!N!C3!'i!BJ$B"3Sf1%XJ3QPZBA*j!*!&C!"Z!(B!f!8+8&"$)'*TEQ&b
+H3#3"43!EJ!M!9B3#89NDA3J9'9iG&X!N!88!!S!*!"KL!K3BA4dCA*Z1J#3"9!!
+#J"J!'+)#d9iBfaeC'8JD@ik!*!%p!!+!*!&JJ%L!*B"A!3#6dX!N!@#!!S!PJ"%
+"!C$B@jMC@`!N!9N!0`!GJ&E"3C6Eh9bBf8!N!93!0`!BJ&E"3Y38%-JC'9fC@a[
+F!#3"P!!EJ"L!0J&#MBi5b"#D@jKFRN!N!9N!'i!GJ$B"3T38%-JBQPZBA*j!*!&
+&!"Z!#-"9K!*4@4TG#"8CAKd@`#3"6)!EJ""!9F3!*!'&!!+!#3!BBJ(8fpeFQ0P
+1Jm!N!8b!!S!3J"KL!a%CA0dD@jKG'P[EMS!N!93!!S!B!"LL!Y*EQ0XG@4P)'PZ
+1Q`!!!!9!#J!+!%k!F3!!!%!!3#3"3)#!*!%&3!S!#J"1J(%!!!"!!%!N!8#!`#3
+"%i!!`#3"3S!#J$G!Bi!N!I`!33""!'2"!C%C@aPG'8!N!A`!'i""!$j"!G&C'Pd
+,LiZ!*!'m!!+!33!BJ3'3@4N,LiZ!!!!&3"`!'i!k`&E!!!"!!%!N!8#"!#3"+)!
+"!#3"4i!&!!`!13'#dCeE'`JFfpeFQ0PG!#3"6)!&!"%!13'$e"33b"NCACPE'p`
+E@9ZG1F!N!9'!"3!@!$N"Jmf1%XJBQPZBA*j,@pZE(RR!*!&@J!8!'`!j!B28&"$
+)'*TEQ&bH5e[EQajj`#3"3S!#J!D!1D)(P4jF'8JEfBJC'PcG(*TBR9dD@pZ)(4[
+)'*eD@aN1J!!!'i!"!#3"3S!#J$G!Bi!N!I`!6B""3'-"!T%DA0dFQPLGA4P!*!&
+m!$5!33",J3+3fKPBfXJG(*PC3#3"I!!#J%%!')%#NPZBfaeC'8Z,Li!N!A`!'i"
+"!$'"!G&H'0XG@4P!!!!!3!!!!5[!!!$V`!!!2)!cC58%83!!!!F!+B!!84-6dF!
+"!!54%P86!!%!%i#!*!)cC0`!J%!$`!!!"N!cC0i!J)!(J!!!IS!cC0X!J-!)`!!
+!K-!cC0S!J3!1J!!!Ri!cC0N!J$rr`!!!3)!N!3#!Irr!!!!-J#3"!)#rrm!!!-p
+!-f52!)$rrm!!!)X!*!%!J6rr`!!!TF!N!315@jME(9NC5"ND@&XEfF14AKME(9N
+C5"ND@&XEfF%6@&TEKC*EQ0XG@4P,f9iBfaeC'8JGfPZC'ph%84TFh4bD@*eG'P[
+EL"dHA"PJqX:
diff --git a/Mac/scripts/MkDistr_ui.py b/Mac/scripts/MkDistr_ui.py
new file mode 100644 (file)
index 0000000..f9192f5
--- /dev/null
@@ -0,0 +1,346 @@
+#
+# MkDistr - User Interface.
+#
+# Jack Jansen, CWI, August 1995
+#
+# XXXX To be done (requires mods of FrameWork and toolbox interfaces too):
+# - Give dialogs titles (need dlg->win conversion)
+# - Place dialogs better (???)
+# - <return> as <ok>
+# - big box around ok button
+# - window-close crashes on reopen (why?)
+# - Box around lists (???)
+# - Change cursor while busy (need cursor support in Qd)
+#
+import Res
+import Dlg
+import Ctl
+import List
+import Win
+import Qd
+from FrameWork import *
+import EasyDialogs
+import macfs
+
+# Resource IDs
+ID_MAIN = 514
+MAIN_LIST=1
+MAIN_MKDISTR=2
+MAIN_CHECK=3
+MAIN_INCLUDE=4
+MAIN_EXCLUDE=5
+
+ID_INCEXC=515
+INCEXC_DELETE=2
+INCEXC_CHANGE=3
+INCEXC_ADD=4
+
+ID_INCLUDE=512
+ID_EXCLUDE=513
+DLG_OK=1
+DLG_CANCEL=2
+DLG_FULL=3
+DLG_PPCDEV=4
+DLG_68K=5
+DLG_PPC=6
+DLG_BUTTONS=[DLG_FULL, DLG_PPCDEV, DLG_68K, DLG_PPC]
+DLG_LETTERS=['S', 'P', 'm', 'p']
+DLG_SRCPATH=7
+DLG_DSTPATH=8
+
+ID_DTYPE=516
+
+class EditDialogWindow(DialogWindow):
+       """Include/exclude editor (modeless dialog window)"""
+       
+       def open(self, id, (type, src, dst), callback, cancelrv):
+               self.id = id
+               if id == ID_INCLUDE:
+                       title = "Include file dialog"
+               else:
+                       title = "Exclude pattern dialog"
+               #self.wid.as_Window().SetWTitle(title)
+               self.callback = callback
+               self.cancelrv = cancelrv
+               DialogWindow.open(self, id)
+               tp, h, rect = self.wid.GetDialogItem(DLG_SRCPATH)
+               Dlg.SetDialogItemText(h, src)
+               if id == ID_INCLUDE:
+                       tp, h, rect = self.wid.GetDialogItem(DLG_DSTPATH)
+                       Dlg.SetDialogItemText(h, dst)
+               for b in range(len(DLG_BUTTONS)):
+                       if type == None or DLG_LETTERS[b] in type:
+                               self.setbutton(DLG_BUTTONS[b], 1)
+
+       def setbutton(self, num, value):
+               tp, h, rect = self.wid.GetDialogItem(num)
+               h.as_Control().SetControlValue(value)
+               
+       def getbutton(self, num):
+               tp, h, rect = self.wid.GetDialogItem(num)
+               return h.as_Control().GetControlValue()
+       
+       def do_itemhit(self, item, event):
+               if item in (DLG_OK, DLG_CANCEL):
+                       self.done(item)
+               elif item in DLG_BUTTONS:
+                       v = self.getbutton(item)
+                       self.setbutton(item, (not v))
+               # else it is not interesting
+               
+       def done(self, item):
+               if item == DLG_OK:
+                       distlist = ''
+                       for i in range(len(DLG_BUTTONS)):
+                               if self.getbutton(DLG_BUTTONS[i]):
+                                       distlist = distlist + DLG_LETTERS[i]
+                       tp, h, rect = self.wid.GetDialogItem(DLG_SRCPATH)
+                       src = Dlg.GetDialogItemText(h)
+                       if self.id == ID_INCLUDE:
+                               tp, h, rect = self.wid.GetDialogItem(DLG_DSTPATH)
+                               dst = Dlg.GetDialogItemText(h)
+                               rv = (distlist, src, dst)
+                       else:
+                               rv = (distlist, src)
+               else:
+                       rv = self.cancelrv
+               self.close()
+               self.callback((item==DLG_OK), rv)
+               
+class ListWindow(DialogWindow):
+       """A dialog window containing a list as its main item"""
+       
+       def open(self, id, contents):
+               self.id = id
+               DialogWindow.open(self, id)
+               tp, h, rect = self.wid.GetDialogItem(MAIN_LIST)
+               rect2 = rect[0], rect[1], rect[2]-16, rect[3]-16        # Scroll bar space
+               self.list = List.LNew(rect2, (0, 0, 1, len(contents)), (0,0), 0, self.wid,
+                               0, 1, 1, 1)
+               self.setlist(contents)
+
+       def setlist(self, contents):
+               self.list.LDelRow(0, 0)
+               self.list.LSetDrawingMode(0)
+               if contents:
+                       self.list.LAddRow(len(contents), 0)
+                       for i in range(len(contents)):
+                               self.list.LSetCell(contents[i], (0, i))
+               self.list.LSetDrawingMode(1)
+               self.list.LUpdate()
+               
+       def additem(self, item):
+               where = self.list.LAddRow(1, 0)
+               self.list.LSetCell(item, (0, where))
+               
+       def delgetitem(self, item):
+               data = self.list.LGetCell(1000, (0, item))
+               self.list.LDelRow(1, item)
+               return data
+               
+       def do_listhit(self, event):
+               (what, message, when, where, modifiers) = event
+               Qd.SetPort(self.wid)
+               where = Qd.GlobalToLocal(where)
+               if self.list.LClick(where, modifiers):
+                       self.do_dclick(self.delgetselection())
+               
+       def delgetselection(self):
+               items = []
+               point = (0,0)
+               while 1:
+                       ok, point = self.list.LGetSelect(1, point)
+                       if not ok:
+                               break
+                       items.append(point[1])
+                       point = point[0], point[1]+1
+               values = []
+               items.reverse()
+               for i in items:
+                       values.append(self.delgetitem(i))
+               return values
+               
+       def do_rawupdate(self, window, event):
+               self.list.LUpdate()
+               
+       def do_close(self):
+               self.close()
+               
+       def close(self):
+               del self.list
+               DialogWindow.close(self)
+               
+       def mycb_add(self, ok, item):
+               if item:
+                       self.additem(item[1])
+                       self.cb_add(item)
+               
+class MainListWindow(ListWindow):
+       """The main window"""
+
+       def open(self, id, cb_check, cb_run, cb_add):
+               ListWindow.open(self, id, [])
+               title = "MkDistr: Unresolved files"
+               #self.wid.as_Window().SetWTitle(title)
+               self.cb_run = cb_run
+               self.cb_check = cb_check
+               self.cb_add = cb_add
+
+       def do_itemhit(self, item, event):
+               if item == MAIN_LIST:
+                       self.do_listhit(event)
+               if item == MAIN_MKDISTR:
+                       fss, ok = macfs.StandardPutFile('Destination folder:')
+                       if not ok:
+                               return
+                       self.cb_run(fss.as_pathname())
+               if item == MAIN_CHECK:
+                       list = self.cb_check()
+                       self.setlist(list)
+               if item == MAIN_INCLUDE:
+                       self.do_dclick(self.delgetselection())
+               if item == MAIN_EXCLUDE:
+                       for i in self.delgetselection():
+                               self.cb_add(('', i, ''))
+                       
+       def do_dclick(self, list):
+               if not list:
+                       list = ['']
+               for l in list:
+                       w = EditDialogWindow(self.parent)
+                       w.open(ID_INCLUDE, (None, l, ''), self.mycb_add, None)
+
+       def mycb_add(self, ok, item):
+               if item:
+                       self.cb_add(item)
+
+class IncListWindow(ListWindow):
+       """An include/exclude window"""
+       def open(self, id, editid, contents, cb_add, cb_del, cb_get):
+               ListWindow.open(self, id, contents)
+               if editid == ID_INCLUDE:
+                       title = "MkDistr: files to include"
+               else:
+                       title = "MkDistr: patterns to exclude"
+               #self.wid.as_Window().SetWTitle(title)
+               self.editid = editid
+               self.cb_add = cb_add
+               self.cb_del = cb_del
+               self.cb_get = cb_get
+
+       def do_itemhit(self, item, event):
+               if item == MAIN_LIST:
+                       self.do_listhit(event)
+               if item == INCEXC_DELETE:
+                       old = self.delgetselection()
+                       for i in old:
+                               self.cb_del(i)
+               if item == INCEXC_CHANGE:
+                       self.do_dclick(self.delgetselection())
+               if item == INCEXC_ADD:
+                       w = EditDialogWindow(self.parent)
+                       w.open(self.editid, (None, '', ''), self.mycb_add, None)
+                       
+       def do_dclick(self, list):
+               if not list:
+                       list = ['']
+               for l in list:
+                       old = self.cb_get(l)
+                       self.cb_del(l)
+                       w = EditDialogWindow(self.parent)
+                       w.open(self.editid, old, self.mycb_add, old)
+
+class MkDistrUI(Application):
+       def __init__(self, main):
+               self.main = main
+               Application.__init__(self)
+               self.mwin = MainListWindow(self)
+               self.mwin.open(ID_MAIN, self.main.check, self.main.run, self.main.inc.add)
+               self.iwin = None
+               self.ewin = None        
+               
+       def makeusermenus(self):
+               self.filemenu = m = Menu(self.menubar, "File")
+               self.includeitem = MenuItem(m, "Show Include window", "", self.showinc)
+               self.excludeitem = MenuItem(m, "Show Exclude window", "", self.showexc)
+               self.saveitem = MenuItem(m, "Save databases", "S", self.save)
+               self.quititem = MenuItem(m, "Quit", "Q", self.quit)
+               
+       def quit(self, *args):
+               if self.main.is_modified():
+                       rv = EasyDialogs.AskYesNoCancel('Database modified. Save?', -1)
+                       if rv == -1:
+                               return
+                       if rv == 1:
+                               self.main.save()
+               raise self
+               
+       def save(self, *args):
+               self.main.save()
+               
+       def showinc(self, *args):
+               if self.iwin:
+                       if self._windows.has_key(self.iwin):
+                               self.iwin.close()
+                       del self.iwin
+               self.iwin = IncListWindow(self)
+               self.iwin.open(ID_INCEXC, ID_INCLUDE, self.main.inc.getall(), self.main.inc.add,
+                       self.main.inc.delete, self.main.inc.get)
+               
+       def showexc(self, *args):
+               if self.ewin:
+                       if self._windows.has_key(self.ewin):
+                               self.ewin.close()
+                       del self.ewin
+               self.ewin = IncListWindow(self)
+               self.ewin.open(ID_INCEXC, ID_EXCLUDE, self.main.exc.getall(), self.main.exc.add,
+                       self.main.exc.delete, self.main.exc.get)
+
+       def do_about(self, id, item, window, event):
+               EasyDialogs.Message("Test the MkDistr user interface.")
+               
+def GetType():
+       """Ask user for distribution type"""
+       d = Dlg.GetNewDialog(ID_DTYPE, -1)
+       while 1:
+               rv = ModalDialog(None)
+               if rv >= 1 and rv <= 4:
+                       return DLG_LETTERS[rv-1]
+                       
+def InitUI():
+       """Initialize stuff needed by UI (a resource file)"""
+       Res.OpenResFile('MkDistr.rsrc')
+
+class _testerhelp:
+       def __init__(self, which):
+               self.which = which
+               
+       def get(self):
+               return [self.which+'-one', self.which+'-two']
+               
+       def add(self, value):
+               if value:
+                       print 'ADD', self.which, value
+                       
+       def delete(self, value):
+               print 'DEL', self.which, value
+               
+class _test:
+       def __init__(self):
+               import sys
+               Res.OpenResFile('MkDistr.rsrc')
+               self.inc = _testerhelp('include')
+               self.exc = _testerhelp('exclude')
+               self.ui = MkDistrUI(self)
+               self.ui.mainloop()
+               sys.exit(1)
+               
+       def check(self):
+               print 'CHECK'
+               return ['rv1', 'rv2']
+               
+       def run(self):
+               print 'RUN'
+               
+if __name__ == '__main__':
+       _test()