diff options
author | David Ascher <david.ascher@gmail.com> | 2004-02-18 05:59:53 (GMT) |
---|---|---|
committer | David Ascher <david.ascher@gmail.com> | 2004-02-18 05:59:53 (GMT) |
commit | e2b4b3202588e0ea87bbc6967c79339979f8d0f4 (patch) | |
tree | 30016d15595e4475241ab48595aeb24ffcf0fbd9 /Lib | |
parent | f06116dcab8f6066f78c522c056ffb9c2403706c (diff) | |
download | cpython-e2b4b3202588e0ea87bbc6967c79339979f8d0f4.zip cpython-e2b4b3202588e0ea87bbc6967c79339979f8d0f4.tar.gz cpython-e2b4b3202588e0ea87bbc6967c79339979f8d0f4.tar.bz2 |
Implementation of patch 869468
Allow the user to create Tkinter.Tcl objects which are
just like Tkinter.Tk objects except that they do not
initialize Tk. This is useful in circumstances where the
script is being run on machines that do not have an X
server running -- in those cases, Tk initialization fails,
even if no window is ever created.
Includes documentation change and tests.
Tested on Linux, Solaris and Windows.
Reviewed by Martin von Loewis.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/lib-tk/Tkinter.py | 35 | ||||
-rw-r--r-- | Lib/test/test_tcl.py | 159 |
2 files changed, 189 insertions, 5 deletions
diff --git a/Lib/lib-tk/Tkinter.py b/Lib/lib-tk/Tkinter.py index 67e942e..5ad065d 100644 --- a/Lib/lib-tk/Tkinter.py +++ b/Lib/lib-tk/Tkinter.py @@ -1546,23 +1546,36 @@ class Tk(Misc, Wm): """Toplevel widget of Tk which represents mostly the main window of an appliation. It has an associated Tcl interpreter.""" _w = '.' - def __init__(self, screenName=None, baseName=None, className='Tk'): + def __init__(self, screenName=None, baseName=None, className='Tk', useTk=1): """Return a new Toplevel widget on screen SCREENNAME. A new Tcl interpreter will be created. BASENAME will be used for the identification of the profile file (see readprofile). It is constructed from sys.argv[0] without extensions if None is given. CLASSNAME is the name of the widget class.""" - global _default_root self.master = None self.children = {} + self._tkloaded = 0 + # to avoid recursions in the getattr code in case of failure, we + # ensure that self.tk is always _something_. + self.tk = None if baseName is None: import sys, os baseName = os.path.basename(sys.argv[0]) baseName, ext = os.path.splitext(baseName) if ext not in ('.py', '.pyc', '.pyo'): baseName = baseName + ext - self.tk = _tkinter.create(screenName, baseName, className) - self.tk.wantobjects(wantobjects) + interactive = 0 + self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk) + if useTk: + self._loadtk() + self.readprofile(baseName, className) + def loadtk(self): + if not self._tkloaded: + self.tk.loadtk() + self._loadtk() + def _loadtk(self): + self._tkloaded = 1 + global _default_root if _MacOS and hasattr(_MacOS, 'SchedParams'): # Disable event scanning except for Command-Period _MacOS.SchedParams(1, 0) @@ -1587,7 +1600,6 @@ class Tk(Misc, Wm): % str(TkVersion) self.tk.createcommand('tkerror', _tkerror) self.tk.createcommand('exit', _exit) - self.readprofile(baseName, className) if _support_default_root and not _default_root: _default_root = self self.protocol("WM_DELETE_WINDOW", self.destroy) @@ -1629,6 +1641,15 @@ class Tk(Misc, Wm): sys.last_value = val sys.last_traceback = tb traceback.print_exception(exc, val, tb) + def __getattr__(self, attr): + "Delegate attribute access to the interpreter object" + return getattr(self.tk, attr) + def __hasattr__(self, attr): + "Delegate attribute access to the interpreter object" + return hasattr(self.tk, attr) + def __delattr__(self, attr): + "Delegate attribute access to the interpreter object" + return delattr(self.tk, attr) # Ideally, the classes Pack, Place and Grid disappear, the # pack/place/grid methods are defined on the Widget class, and @@ -1644,6 +1665,10 @@ class Tk(Misc, Wm): # toplevel and interior widgets). Again, for compatibility, these are # copied into the Pack, Place or Grid class. + +def Tcl(screenName=None, baseName=None, className='Tk', useTk=0): + return Tk(screenName, baseName, className, useTk) + class Pack: """Geometry manager Pack. diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py new file mode 100644 index 0000000..3e0a781 --- /dev/null +++ b/Lib/test/test_tcl.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python + +import unittest +import os +from Tkinter import Tcl +from _tkinter import TclError + +class TclTest(unittest.TestCase): + + def setUp(self): + self.interp = Tcl() + + def testEval(self): + tcl = self.interp + tcl.eval('set a 1') + self.assertEqual(tcl.eval('set a'),'1') + + def testEvalException(self): + tcl = self.interp + self.assertRaises(TclError,tcl.eval,'set a') + + def testEvalException2(self): + tcl = self.interp + self.assertRaises(TclError,tcl.eval,'this is wrong') + + def testCall(self): + tcl = self.interp + tcl.call('set','a','1') + self.assertEqual(tcl.call('set','a'),'1') + + def testCallException(self): + tcl = self.interp + self.assertRaises(TclError,tcl.call,'set','a') + + def testCallException2(self): + tcl = self.interp + self.assertRaises(TclError,tcl.call,'this','is','wrong') + + def testSetVar(self): + tcl = self.interp + tcl.setvar('a','1') + self.assertEqual(tcl.eval('set a'),'1') + + def testSetVarArray(self): + tcl = self.interp + tcl.setvar('a(1)','1') + self.assertEqual(tcl.eval('set a(1)'),'1') + + def testGetVar(self): + tcl = self.interp + tcl.eval('set a 1') + self.assertEqual(tcl.getvar('a'),'1') + + def testGetVarArray(self): + tcl = self.interp + tcl.eval('set a(1) 1') + self.assertEqual(tcl.getvar('a(1)'),'1') + + def testGetVarException(self): + tcl = self.interp + self.assertRaises(TclError,tcl.getvar,'a') + + def testGetVarArrayException(self): + tcl = self.interp + self.assertRaises(TclError,tcl.getvar,'a(1)') + + def testUnsetVar(self): + tcl = self.interp + tcl.setvar('a',1) + self.assertEqual(tcl.eval('info exists a'),'1') + tcl.unsetvar('a') + self.assertEqual(tcl.eval('info exists a'),'0') + + def testUnsetVarArray(self): + tcl = self.interp + tcl.setvar('a(1)',1) + tcl.setvar('a(2)',2) + self.assertEqual(tcl.eval('info exists a(1)'),'1') + self.assertEqual(tcl.eval('info exists a(2)'),'1') + tcl.unsetvar('a(1)') + self.assertEqual(tcl.eval('info exists a(1)'),'0') + self.assertEqual(tcl.eval('info exists a(2)'),'1') + + def testUnsetVarException(self): + tcl = self.interp + self.assertRaises(TclError,tcl.unsetvar,'a') + + def testEvalFile(self): + tcl = self.interp + filename = "testEvalFile.tcl" + fd = open(filename,'w') + script = """set a 1 + set b 2 + set c [ expr $a + $b ] + """ + fd.write(script) + fd.close() + tcl.evalfile(filename) + self.assertEqual(tcl.eval('set a'),'1') + self.assertEqual(tcl.eval('set b'),'2') + self.assertEqual(tcl.eval('set c'),'3') + + def testEvalFileException(self): + tcl = self.interp + filename = "doesnotexists" + try: + os.remove(filename) + except Exception,e: + pass + self.assertRaises(TclError,tcl.evalfile,filename) + + def testPackageRequire(self): + tcl = self.interp + tcl.eval('package require Tclx') + tcl.eval('keylset a b.c 1') + self.assertEqual(tcl.eval('keylget a b.c'),'1') + + def testPackageRequireException(self): + tcl = self.interp + self.assertRaises(TclError,tcl.eval,'package require DNE') + + def testLoadTk(self): + import os + if 'DISPLAY' not in os.environ: + # skipping test of clean upgradeability + return + tcl = Tcl() + self.assertRaises(TclError,tcl.winfo_geometry) + tcl.loadtk() + self.assertEqual('1x1+0+0', tcl.winfo_geometry()) + + def testLoadTkFailure(self): + import os + old_display = None + import sys + if sys.platform.startswith('win'): + return # no failure possible on windows? + if 'DISPLAY' in os.environ: + old_display = os.environ['DISPLAY'] + del os.environ['DISPLAY'] + # on some platforms, deleting environment variables + # doesn't actually carry through to the process level + # because they don't support unsetenv + # If that's the case, abort. + display = os.popen('echo $DISPLAY').read().strip() + if display: + return + try: + tcl = Tcl() + self.assertRaises(TclError, tcl.winfo_geometry) + self.assertRaises(TclError, tcl.loadtk) + finally: + if old_display is not None: + os.environ['DISPLAY'] = old_display + +if __name__ == "__main__": + unittest.main() + + |