diff options
author | Guido van Rossum <guido@python.org> | 2003-04-29 11:27:16 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2003-04-29 11:27:16 (GMT) |
commit | a3c253e83b248df1562c3ac2a5be3cf3504432f8 (patch) | |
tree | 9aff2fe100549b3af220796679673e616b9aa8d6 /Tools/idle | |
parent | 767d9fedc797fcddb16cdba8ce0268b503ee13d1 (diff) | |
download | cpython-a3c253e83b248df1562c3ac2a5be3cf3504432f8.zip cpython-a3c253e83b248df1562c3ac2a5be3cf3504432f8.tar.gz cpython-a3c253e83b248df1562c3ac2a5be3cf3504432f8.tar.bz2 |
Removing new files accidentally checked in on the trunk rather than on the
idlefork-merge-branch.
Diffstat (limited to 'Tools/idle')
26 files changed, 0 insertions, 4632 deletions
diff --git a/Tools/idle/CREDITS.txt b/Tools/idle/CREDITS.txt deleted file mode 100644 index fd7af95..0000000 --- a/Tools/idle/CREDITS.txt +++ /dev/null @@ -1,36 +0,0 @@ -IDLEfork Credits -================== - -Guido van Rossum, as well as being the creator of the Python language, is -the original creator of IDLE. He also developed the RPC code and Remote -Debugger extension used in IDLEfork. - -The IDLEfork project was initiated and brought up to version 0.7.1 primarily -by David Scherer, with help from Peter Schneider-Kamp and Nicholas Riley. -Bruce Sherwood has contributed considerable time testing and suggesting -improvements. - -Besides Guido, the main developers who have been active on IDLEfork version -0.8.1 and later are Stephen M. Gava, who implemented the Configuration GUI, the -new configuration system, and the new About menu, and Kurt B. Kaiser, who -completed the integration of the RPC and remote debugger, and made a number of -usability enhancements. - -Other contributors include Raymond Hettinger, Tony Lownds (Mac integration), -Neal Norwitz (code check and clean-up), and Chui Tey (RPC integration, debugger -integration and persistent breakpoints). - -Hernan Foffani, Christos Georgiou, Jason Orendorff, Josh Robb, and Bruce -Sherwood have submitted useful patches. Thanks, guys! - -There are others who should be included here, especially those who contributed -to IDLE versions prior to 0.8, principally Mark Hammond, Jeremy Hylton, -Tim Peters, and Moshe Zadka. For additional details refer to NEWS.txt and -Changelog. - -Please contact the IDLEfork maintainer to have yourself included here if you -are one of those we missed! - -Contact details at http://idlefork.sourceforge.net - - diff --git a/Tools/idle/HISTORY.txt b/Tools/idle/HISTORY.txt deleted file mode 100644 index 9312f32..0000000 --- a/Tools/idle/HISTORY.txt +++ /dev/null @@ -1,180 +0,0 @@ -IDLE History -============ - -This file contains the release messages for previous IDLE releases. -As you read on you go back to the dark ages of IDLE's history. - - -IDLE 0.5 - February 2000 - Release Notes ----------------------------------------- - -This is an early release of IDLE, my own attempt at a Tkinter-based -IDE for Python. - -(For a more detailed change log, see the file ChangeLog.) - -FEATURES - -IDLE has the following features: - -- coded in 100% pure Python, using the Tkinter GUI toolkit (i.e. Tcl/Tk) - -- cross-platform: works on Windows and Unix (on the Mac, there are -currently problems with Tcl/Tk) - -- multi-window text editor with multiple undo, Python colorizing -and many other features, e.g. smart indent and call tips - -- Python shell window (a.k.a. interactive interpreter) - -- debugger (not complete, but you can set breakpoints, view and step) - -USAGE - -The main program is in the file "idle.py"; on Unix, you should be able -to run it by typing "./idle.py" to your shell. On Windows, you can -run it by double-clicking it; you can use idle.pyw to avoid popping up -a DOS console. If you want to pass command line arguments on Windows, -use the batch file idle.bat. - -Command line arguments: files passed on the command line are executed, -not opened for editing, unless you give the -e command line option. -Try "./idle.py -h" to see other command line options. - -IDLE requires Python 1.5.2, so it is currently only usable with a -Python 1.5.2 distribution. (An older version of IDLE is distributed -with Python 1.5.2; you can drop this version on top of it.) - -COPYRIGHT - -IDLE is covered by the standard Python copyright notice -(http://www.python.org/doc/Copyright.html). - - -New in IDLE 0.5 (2/15/2000) ---------------------------- - -Tons of stuff, much of it contributed by Tim Peters and Mark Hammond: - -- Status bar, displaying current line/column (Moshe Zadka). - -- Better stack viewer, using tree widget. (XXX Only used by Stack -Viewer menu, not by the debugger.) - -- Format paragraph now recognizes Python block comments and reformats -them correctly (MH) - -- New version of pyclbr.py parses top-level functions and understands -much more of Python's syntax; this is reflected in the class and path -browsers (TP) - -- Much better auto-indent; knows how to indent the insides of -multi-line statements (TP) - -- Call tip window pops up when you type the name of a known function -followed by an open parenthesis. Hit ESC or click elsewhere in the -window to close the tip window (MH) - -- Comment out region now inserts ## to make it stand out more (TP) - -- New path and class browsers based on a tree widget that looks -familiar to Windows users - -- Reworked script running commands to be more intuitive: I/O now -always goes to the *Python Shell* window, and raw_input() works -correctly. You use F5 to import/reload a module: this adds the module -name to the __main__ namespace. You use Control-F5 to run a script: -this runs the script *in* the __main__ namespace. The latter also -sets sys.argv[] to the script name - - -New in IDLE 0.4 (4/7/99) ------------------------- - -Most important change: a new menu entry "File -> Path browser", shows -a 4-column hierarchical browser which lets you browse sys.path, -directories, modules, and classes. Yes, it's a superset of the Class -browser menu entry. There's also a new internal module, -MultiScrolledLists.py, which provides the framework for this dialog. - - -New in IDLE 0.3 (2/17/99) -------------------------- - -Most important changes: - -- Enabled support for running a module, with or without the debugger. -Output goes to a new window. Pressing F5 in a module is effectively a -reload of that module; Control-F5 loads it under the debugger. - -- Re-enable tearing off the Windows menu, and make a torn-off Windows -menu update itself whenever a window is opened or closed. - -- Menu items can now be have a checkbox (when the menu label starts -with "!"); use this for the Debugger and "Auto-open stack viewer" -(was: JIT stack viewer) menu items. - -- Added a Quit button to the Debugger API. - -- The current directory is explicitly inserted into sys.path. - -- Fix the debugger (when using Python 1.5.2b2) to use canonical -filenames for breakpoints, so these actually work. (There's still a -lot of work to be done to the management of breakpoints in the -debugger though.) - -- Closing a window that is still colorizing now actually works. - -- Allow dragging of the separator between the two list boxes in the -class browser. - -- Bind ESC to "close window" of the debugger, stack viewer and class -browser. It removes the selection highlighting in regular text -windows. (These are standard Windows conventions.) - - -New in IDLE 0.2 (1/8/99) ------------------------- - -Lots of changes; here are the highlights: - -General: - -- You can now write and configure your own IDLE extension modules; see -extend.txt. - - -File menu: - -The command to open the Python shell window is now in the File menu. - - -Edit menu: - -New Find dialog with more options; replace dialog; find in files dialog. - -Commands to tabify or untabify a region. - -Command to format a paragraph. - - -Debug menu: - -JIT (Just-In-Time) stack viewer toggle -- if set, the stack viewer -automaticall pops up when you get a traceback. - -Windows menu: - -Zoom height -- make the window full height. - - -Help menu: - -The help text now show up in a regular window so you can search and -even edit it if you like. - - - -IDLE 0.1 was distributed with the Python 1.5.2b1 release on 12/22/98. - -====================================================================== diff --git a/Tools/idle/INSTALL.txt b/Tools/idle/INSTALL.txt deleted file mode 100644 index ed7ac69..0000000 --- a/Tools/idle/INSTALL.txt +++ /dev/null @@ -1,51 +0,0 @@ -IDLEfork Installation Notes -=========================== - -IDLEfork requires Python Version 2.2 or later. - -There are several distribution files (where xx is the subversion): - -IDLEfork-0.9xx.win32.exe - This is a Windows installer which will install IDLEfork in - ..../site-packages/idleforklib/ and place the idefork startup script - at ..../scripts/idlefork. Rename this to idlefork.pyw and - point your launcher icons at it. Installation is as idlefork - to avoid conflict with the original Python IDLE. - -IDLEfork-0.9xx-1.noarch.rpm - This is an rpm which is designed to install as idleforklib in an - existing /usr/lib/python2.2 tree. It installs as idlefork to avoid - conflict with Python IDLE. - - Python rpms are available at http://www.python.org/2.2.2/rpms.html and - http://www.python.org/2.2.1/rpms.html. - -IDLEfork-0.9xx.tar.gz - This is a distutils sdist (source) tarfile which can be used to make - installations on platforms not supported by the above files. - ** It remains configured to install as idlelib, not idleforklib. ** - - Unpack in ..../Tools/, cd to the IDLEfork directory created, and - "python setup.py install" to install in ....site-packages/idlelib. - This will overwrite the Python IDLE installation. - - If you don't want to overwrite Python IDLE, it is also possible to - simply call "python idle.py" to run from the IDLEfork source directory - without making an installation. In this case, IDLE will not be on - your PATH unless you are in the source directory. Also, it is then - advisable to remove any Python IDLE installation by removing - ..../site-packages/idlelib so the two identically named packages don't - conflict. - - On Redhat Linux systems prior to 8.0, /usr/bin/python may be pointing - at python1.5. If so, change the first line in the /usr/bin/idle - script to read: - !# /usr/bin/python2.2 - -See README.txt for more details on this version of IDLEfork. - - - - - - diff --git a/Tools/idle/LICENSE.txt b/Tools/idle/LICENSE.txt deleted file mode 100644 index f7a8395..0000000 --- a/Tools/idle/LICENSE.txt +++ /dev/null @@ -1,50 +0,0 @@ -To apply this license to IDLE or IDLEfork, read 'IDLE' or 'IDLEfork' -for every occurence of 'Python 2.1.1' in the text below. - -PSF LICENSE AGREEMENT ---------------------- - -1. This LICENSE AGREEMENT is between the Python Software Foundation -("PSF"), and the Individual or Organization ("Licensee") accessing and -otherwise using Python 2.1.1 software in source or binary form and its -associated documentation. - -2. Subject to the terms and conditions of this License Agreement, PSF -hereby grants Licensee a nonexclusive, royalty-free, world-wide -license to reproduce, analyze, test, perform and/or display publicly, -prepare derivative works, distribute, and otherwise use Python 2.1.1 -alone or in any derivative version, provided, however, that PSF's -License Agreement and PSF's notice of copyright, i.e., "Copyright (c) -2001 Python Software Foundation; All Rights Reserved" are retained in -Python 2.1.1 alone or in any derivative version prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python 2.1.1 or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python 2.1.1. - -4. PSF is making Python 2.1.1 available to Licensee on an "AS IS" -basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.1.1 WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -2.1.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.1.1, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any -relationship of agency, partnership, or joint venture between PSF and -Licensee. This License Agreement does not grant permission to use PSF -trademarks or trade name in a trademark sense to endorse or promote -products or services of Licensee, or any third party. - -8. By copying, installing or otherwise using Python 2.1.1, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. diff --git a/Tools/idle/Makefile b/Tools/idle/Makefile deleted file mode 100644 index f118ebf..0000000 --- a/Tools/idle/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# Makefile to build the interrupt module, which is a C extension - -PYTHON=python2.3 - -all: interrupt.so - -interrupt.so: interruptmodule.c - $(PYTHON) setup.py build_ext -i diff --git a/Tools/idle/RemoteDebugger.py b/Tools/idle/RemoteDebugger.py deleted file mode 100644 index 41f910f..0000000 --- a/Tools/idle/RemoteDebugger.py +++ /dev/null @@ -1,381 +0,0 @@ -"""Support for remote Python debugging. - -Some ASCII art to describe the structure: - - IN PYTHON SUBPROCESS # IN IDLE PROCESS - # - # oid='gui_adapter' - +----------+ # +------------+ +-----+ - | GUIProxy |--remote#call-->| GUIAdapter |--calls-->| GUI | -+-----+--calls-->+----------+ # +------------+ +-----+ -| Idb | # / -+-----+<-calls--+------------+ # +----------+<--calls-/ - | IdbAdapter |<--remote#call--| IdbProxy | - +------------+ # +----------+ - oid='idb_adapter' # - -The purpose of the Proxy and Adapter classes is to translate certain -arguments and return values that cannot be transported through the RPC -barrier, in particular frame and traceback objects. - -""" - -import sys -import types -import rpc -import Debugger - -debugging = 0 - -idb_adap_oid = "idb_adapter" -gui_adap_oid = "gui_adapter" - -#======================================= -# -# In the PYTHON subprocess: - -frametable = {} -dicttable = {} -codetable = {} -tracebacktable = {} - -def wrap_frame(frame): - fid = id(frame) - frametable[fid] = frame - return fid - -def wrap_info(info): - "replace info[2], a traceback instance, by its ID" - if info is None: - return None - else: - traceback = info[2] - assert isinstance(traceback, types.TracebackType) - traceback_id = id(traceback) - tracebacktable[traceback_id] = traceback - modified_info = (info[0], info[1], traceback_id) - return modified_info - -class GUIProxy: - - def __init__(self, conn, gui_adap_oid): - self.conn = conn - self.oid = gui_adap_oid - - def interaction(self, message, frame, info=None): - # calls rpc.SocketIO.remotecall() via run.MyHandler instance - # pass frame and traceback object IDs instead of the objects themselves - self.conn.remotecall(self.oid, "interaction", - (message, wrap_frame(frame), wrap_info(info)), - {}) - -class IdbAdapter: - - def __init__(self, idb): - self.idb = idb - - #----------called by an IdbProxy---------- - - def set_step(self): - self.idb.set_step() - - def set_quit(self): - self.idb.set_quit() - - def set_continue(self): - self.idb.set_continue() - - def set_next(self, fid): - frame = frametable[fid] - self.idb.set_next(frame) - - def set_return(self, fid): - frame = frametable[fid] - self.idb.set_return(frame) - - def get_stack(self, fid, tbid): - ##print >>sys.__stderr__, "get_stack(%s, %s)" % (`fid`, `tbid`) - frame = frametable[fid] - if tbid is None: - tb = None - else: - tb = tracebacktable[tbid] - stack, i = self.idb.get_stack(frame, tb) - ##print >>sys.__stderr__, "get_stack() ->", stack - stack = [(wrap_frame(frame), k) for frame, k in stack] - ##print >>sys.__stderr__, "get_stack() ->", stack - return stack, i - - def run(self, cmd): - import __main__ - self.idb.run(cmd, __main__.__dict__) - - def set_break(self, filename, lineno): - msg = self.idb.set_break(filename, lineno) - return msg - - def clear_break(self, filename, lineno): - msg = self.idb.clear_break(filename, lineno) - return msg - - def clear_all_file_breaks(self, filename): - msg = self.idb.clear_all_file_breaks(filename) - return msg - - #----------called by a FrameProxy---------- - - def frame_attr(self, fid, name): - frame = frametable[fid] - return getattr(frame, name) - - def frame_globals(self, fid): - frame = frametable[fid] - dict = frame.f_globals - did = id(dict) - dicttable[did] = dict - return did - - def frame_locals(self, fid): - frame = frametable[fid] - dict = frame.f_locals - did = id(dict) - dicttable[did] = dict - return did - - def frame_code(self, fid): - frame = frametable[fid] - code = frame.f_code - cid = id(code) - codetable[cid] = code - return cid - - #----------called by a CodeProxy---------- - - def code_name(self, cid): - code = codetable[cid] - return code.co_name - - def code_filename(self, cid): - code = codetable[cid] - return code.co_filename - - #----------called by a DictProxy---------- - - def dict_keys(self, did): - dict = dicttable[did] - return dict.keys() - - def dict_item(self, did, key): - dict = dicttable[did] - value = dict[key] - value = repr(value) - return value - -#----------end class IdbAdapter---------- - - -def start_debugger(rpchandler, gui_adap_oid): - """Start the debugger and its RPC link in the Python subprocess - - Start the subprocess side of the split debugger and set up that side of the - RPC link by instantiating the GUIProxy, Idb debugger, and IdbAdapter - objects and linking them together. Register the IdbAdapter with the - RPCServer to handle RPC requests from the split debugger GUI via the - IdbProxy. - - """ - gui_proxy = GUIProxy(rpchandler, gui_adap_oid) - idb = Debugger.Idb(gui_proxy) - idb_adap = IdbAdapter(idb) - rpchandler.register(idb_adap_oid, idb_adap) - return idb_adap_oid - - -#======================================= -# -# In the IDLE process: - - -class FrameProxy: - - def __init__(self, conn, fid): - self._conn = conn - self._fid = fid - self._oid = "idb_adapter" - self._dictcache = {} - - def __getattr__(self, name): - if name[:1] == "_": - raise AttributeError, name - if name == "f_code": - return self._get_f_code() - if name == "f_globals": - return self._get_f_globals() - if name == "f_locals": - return self._get_f_locals() - return self._conn.remotecall(self._oid, "frame_attr", - (self._fid, name), {}) - - def _get_f_code(self): - cid = self._conn.remotecall(self._oid, "frame_code", (self._fid,), {}) - return CodeProxy(self._conn, self._oid, cid) - - def _get_f_globals(self): - did = self._conn.remotecall(self._oid, "frame_globals", - (self._fid,), {}) - return self._get_dict_proxy(did) - - def _get_f_locals(self): - did = self._conn.remotecall(self._oid, "frame_locals", - (self._fid,), {}) - return self._get_dict_proxy(did) - - def _get_dict_proxy(self, did): - if self._dictcache.has_key(did): - return self._dictcache[did] - dp = DictProxy(self._conn, self._oid, did) - self._dictcache[did] = dp - return dp - - -class CodeProxy: - - def __init__(self, conn, oid, cid): - self._conn = conn - self._oid = oid - self._cid = cid - - def __getattr__(self, name): - if name == "co_name": - return self._conn.remotecall(self._oid, "code_name", - (self._cid,), {}) - if name == "co_filename": - return self._conn.remotecall(self._oid, "code_filename", - (self._cid,), {}) - - -class DictProxy: - - def __init__(self, conn, oid, did): - self._conn = conn - self._oid = oid - self._did = did - - def keys(self): - return self._conn.remotecall(self._oid, "dict_keys", (self._did,), {}) - - def __getitem__(self, key): - return self._conn.remotecall(self._oid, "dict_item", - (self._did, key), {}) - - def __getattr__(self, name): - ##print >>sys.__stderr__, "failed DictProxy.__getattr__:", name - raise AttributeError, name - - -class GUIAdapter: - - def __init__(self, conn, gui): - self.conn = conn - self.gui = gui - - def interaction(self, message, fid, modified_info): - ##print "interaction: (%s, %s, %s)" % (message, fid, modified_info) - frame = FrameProxy(self.conn, fid) - self.gui.interaction(message, frame, modified_info) - - -class IdbProxy: - - def __init__(self, conn, shell, oid): - self.oid = oid - self.conn = conn - self.shell = shell - - def call(self, methodname, *args, **kwargs): - ##print "**IdbProxy.call %s %s %s" % (methodname, args, kwargs) - value = self.conn.remotecall(self.oid, methodname, args, kwargs) - ##print "**IdbProxy.call %s returns %s" % (methodname, `value`) - return value - - def run(self, cmd, locals): - # Ignores locals on purpose! - seq = self.conn.asynccall(self.oid, "run", (cmd,), {}) - self.shell.interp.active_seq = seq - - def get_stack(self, frame, tbid): - # passing frame and traceback IDs, not the objects themselves - stack, i = self.call("get_stack", frame._fid, tbid) - stack = [(FrameProxy(self.conn, fid), k) for fid, k in stack] - return stack, i - - def set_continue(self): - self.call("set_continue") - - def set_step(self): - self.call("set_step") - - def set_next(self, frame): - self.call("set_next", frame._fid) - - def set_return(self, frame): - self.call("set_return", frame._fid) - - def set_quit(self): - self.call("set_quit") - - def set_break(self, filename, lineno): - msg = self.call("set_break", filename, lineno) - return msg - - def clear_break(self, filename, lineno): - msg = self.call("clear_break", filename, lineno) - return msg - - def clear_all_file_breaks(self, filename): - msg = self.call("clear_all_file_breaks", filename) - return msg - -def start_remote_debugger(rpcclt, pyshell): - """Start the subprocess debugger, initialize the debugger GUI and RPC link - - Request the RPCServer start the Python subprocess debugger and link. Set - up the Idle side of the split debugger by instantiating the IdbProxy, - debugger GUI, and debugger GUIAdapter objects and linking them together. - - Register the GUIAdapter with the RPCClient to handle debugger GUI - interaction requests coming from the subprocess debugger via the GUIProxy. - - The IdbAdapter will pass execution and environment requests coming from the - Idle debugger GUI to the subprocess debugger via the IdbProxy. - - """ - global idb_adap_oid - - idb_adap_oid = rpcclt.remotecall("exec", "start_the_debugger",\ - (gui_adap_oid,), {}) - idb_proxy = IdbProxy(rpcclt, pyshell, idb_adap_oid) - gui = Debugger.Debugger(pyshell, idb_proxy) - gui_adap = GUIAdapter(rpcclt, gui) - rpcclt.register(gui_adap_oid, gui_adap) - return gui - -def close_remote_debugger(rpcclt): - """Shut down subprocess debugger and Idle side of debugger RPC link - - Request that the RPCServer shut down the subprocess debugger and link. - Unregister the GUIAdapter, which will cause a GC on the Idle process - debugger and RPC link objects. (The second reference to the debugger GUI - is deleted in PyShell.close_remote_debugger().) - - """ - close_subprocess_debugger(rpcclt) - rpcclt.unregister(gui_adap_oid) - -def close_subprocess_debugger(rpcclt): - rpcclt.remotecall("exec", "stop_the_debugger", (idb_adap_oid,), {}) - -def restart_subprocess_debugger(rpcclt): - idb_adap_oid_ret = rpcclt.remotecall("exec", "start_the_debugger",\ - (gui_adap_oid,), {}) - assert idb_adap_oid_ret == idb_adap_oid, 'Idb restarted with different oid' diff --git a/Tools/idle/RemoteObjectBrowser.py b/Tools/idle/RemoteObjectBrowser.py deleted file mode 100644 index 6ba3391..0000000 --- a/Tools/idle/RemoteObjectBrowser.py +++ /dev/null @@ -1,36 +0,0 @@ -import rpc - -def remote_object_tree_item(item): - wrapper = WrappedObjectTreeItem(item) - oid = id(wrapper) - rpc.objecttable[oid] = wrapper - return oid - -class WrappedObjectTreeItem: - # Lives in PYTHON subprocess - - def __init__(self, item): - self.__item = item - - def __getattr__(self, name): - value = getattr(self.__item, name) - return value - - def _GetSubList(self): - list = self.__item._GetSubList() - return map(remote_object_tree_item, list) - -class StubObjectTreeItem: - # Lives in IDLE process - - def __init__(self, sockio, oid): - self.sockio = sockio - self.oid = oid - - def __getattr__(self, name): - value = rpc.MethodProxy(self.sockio, self.oid, name) - return value - - def _GetSubList(self): - list = self.sockio.remotecall(self.oid, "_GetSubList", (), {}) - return [StubObjectTreeItem(self.sockio, oid) for oid in list] diff --git a/Tools/idle/aboutDialog.py b/Tools/idle/aboutDialog.py deleted file mode 100644 index 2fc4a42..0000000 --- a/Tools/idle/aboutDialog.py +++ /dev/null @@ -1,126 +0,0 @@ -""" -about box for idle -""" - -from Tkinter import * -import string, os -import textView -import idlever - -class AboutDialog(Toplevel): - """ - modal about dialog for idle - """ - def __init__(self,parent,title): - Toplevel.__init__(self, parent) - self.configure(borderwidth=5) - self.geometry("+%d+%d" % (parent.winfo_rootx()+30, - parent.winfo_rooty()+30)) - self.bg="#707070" - self.fg="#ffffff" - - self.CreateWidgets() - self.resizable(height=FALSE,width=FALSE) - self.title(title) - self.transient(parent) - self.grab_set() - self.protocol("WM_DELETE_WINDOW", self.Ok) - self.parent = parent - self.buttonOk.focus_set() - #key bindings for this dialog - self.bind('<Alt-c>',self.CreditsButtonBinding) #credits button - self.bind('<Alt-l>',self.LicenseButtonBinding) #license button - self.bind('<Return>',self.Ok) #dismiss dialog - self.bind('<Escape>',self.Ok) #dismiss dialog - self.wait_window() - - def CreateWidgets(self): - frameMain = Frame(self,borderwidth=2,relief=SUNKEN) - frameButtons = Frame(self) - frameButtons.pack(side=BOTTOM,fill=X) - frameMain.pack(side=TOP,expand=TRUE,fill=BOTH) - self.buttonOk = Button(frameButtons,text='Ok', - command=self.Ok)#,default=ACTIVE - self.buttonOk.pack(padx=5,pady=5) - #self.picture = Image('photo',data=self.pictureData) - frameBg = Frame(frameMain,bg=self.bg) - frameBg.pack(expand=TRUE,fill=BOTH) - labelTitle = Label(frameBg,text='IDLEfork',fg=self.fg,bg=self.bg, - font=('courier', 24, 'bold')) - labelTitle.grid(row=0,column=0,sticky=W,padx=10,pady=10) - #labelPicture = Label(frameBg,text='[picture]') - #image=self.picture,bg=self.bg) - #labelPicture.grid(row=0,column=1,sticky=W,rowspan=2,padx=0,pady=3) - labelVersion = Label(frameBg,text='version '+idlever.IDLE_VERSION, - fg=self.fg,bg=self.bg) - labelVersion.grid(row=1,column=0,sticky=W,padx=10,pady=5) - labelDesc = Label(frameBg, - text="A development version of Python's lightweight\n"+ - 'Integrated DeveLopment Environment, IDLE.', - justify=LEFT,fg=self.fg,bg=self.bg) - labelDesc.grid(row=2,column=0,sticky=W,columnspan=3,padx=10,pady=5) - labelCopyright = Label(frameBg, - text="Copyright (c) 2001 Python Software Foundation;\nAll Rights Reserved", - justify=LEFT,fg=self.fg,bg=self.bg) - labelCopyright.grid(row=3,column=0,sticky=W,columnspan=3,padx=10,pady=5) - labelLicense = Label(frameBg, - text='Released under the Python 2.1.1 PSF Licence', - justify=LEFT,fg=self.fg,bg=self.bg) - labelLicense.grid(row=4,column=0,sticky=W,columnspan=3,padx=10,pady=5) - Frame(frameBg,height=5,bg=self.bg).grid(row=5,column=0) - labelEmail = Label(frameBg,text='email: idle-dev@python.org', - justify=LEFT,fg=self.fg,bg=self.bg) - labelEmail.grid(row=6,column=0,columnspan=2,sticky=W,padx=10,pady=0) - labelWWW = Label(frameBg,text='www: http://idlefork.sourceforge.net', - justify=LEFT,fg=self.fg,bg=self.bg) - labelWWW.grid(row=7,column=0,columnspan=2,sticky=W,padx=10,pady=0) - Frame(frameBg,borderwidth=1,relief=SUNKEN, - height=2,bg=self.bg).grid(row=8,column=0,sticky=EW, - columnspan=3, padx=5, pady=5) - labelPythonVer = Label(frameBg,text='Python version: '+ - sys.version.split()[0],fg=self.fg,bg=self.bg) - labelPythonVer.grid(row=9,column=0,sticky=W,padx=10,pady=0) - #handle weird tk version num in windoze python >= 1.6 (?!?) - tkVer = `TkVersion`.split('.') - tkVer[len(tkVer)-1] = str('%.3g' % (float('.'+tkVer[len(tkVer)-1])))[2:] - if tkVer[len(tkVer)-1] == '': - tkVer[len(tkVer)-1] = '0' - tkVer = string.join(tkVer,'.') - labelTkVer = Label(frameBg,text='Tk version: '+ - tkVer,fg=self.fg,bg=self.bg) - labelTkVer.grid(row=9,column=1,sticky=W,padx=2,pady=0) - - self.buttonLicense = Button(frameBg,text='View License',underline=5, - width=14,highlightbackground=self.bg,command=self.ShowLicense)#takefocus=FALSE - self.buttonLicense.grid(row=10,column=0,sticky=W,padx=10,pady=10) - self.buttonCredits = Button(frameBg,text='View Credits',underline=5, - width=14,highlightbackground=self.bg,command=self.ShowCredits)#takefocus=FALSE - self.buttonCredits.grid(row=10,column=1,columnspan=2,sticky=E,padx=10,pady=10) - - def CreditsButtonBinding(self,event): - self.buttonCredits.invoke() - - def LicenseButtonBinding(self,event): - self.buttonLicense.invoke() - - def ShowLicense(self): - self.ViewFile('About - License','LICENSE.txt') - - def ShowCredits(self): - self.ViewFile('About - Credits','CREDITS.txt') - - def ViewFile(self,viewTitle,viewFile): - fn=os.path.join(os.path.abspath(os.path.dirname(__file__)),viewFile) - textView.TextViewer(self,viewTitle,fn) - - def Ok(self, event=None): - self.destroy() - -if __name__ == '__main__': - #test the dialog - root=Tk() - def run(): - import aboutDialog - aboutDialog.AboutDialog(root,'About') - Button(root,text='Dialog',command=run).pack() - root.mainloop() diff --git a/Tools/idle/boolcheck.py b/Tools/idle/boolcheck.py deleted file mode 100644 index f682232..0000000 --- a/Tools/idle/boolcheck.py +++ /dev/null @@ -1,9 +0,0 @@ -"boolcheck - import this module to ensure True, False, bool() builtins exist." -try: - True -except NameError: - import __builtin__ - __builtin__.True = 1 - __builtin__.False = 0 - from operator import truth - __builtin__.bool = truth diff --git a/Tools/idle/config-extensions.def b/Tools/idle/config-extensions.def deleted file mode 100644 index d4905e8..0000000 --- a/Tools/idle/config-extensions.def +++ /dev/null @@ -1,54 +0,0 @@ -# IDLE reads several config files to determine user preferences. This -# file is the default config file for idle extensions settings. -# -# Each extension must have at least one section, named after the extension -# module. This section must contain an 'enable' item (=1 to enable the -# extension, =0 to disable it) and also contains any other general -# configuration items for the extension. Each extension may also define up to -# two optional sections named ExtensionName_bindings and -# ExtensionName_cfgBindings. If present, ExtensionName_bindings defines virtual -# event bindings for the extension that are not sensibly re-configurable. If -# present, ExtensionName_cfgBindings defines virtual event bindings for the -# extension that may be sensibly re-configured. - -# See config-keys.def for notes on specifying keys. - -[FormatParagraph] -enable=1 -[FormatParagraph_cfgBindings] -format-paragraph=<Alt-Key-q> - -[AutoExpand] -enable=1 -[AutoExpand_cfgBindings] -expand-word=<Alt-Key-slash> - -[ZoomHeight] -enable=1 -[ZoomHeight_cfgBindings] -zoom-height=<Alt-Key-2> - -[ScriptBinding] -enable=1 -[ScriptBinding_cfgBindings] -run-module=<Key-F5> -check-module=<Alt-Key-x> - -[CallTips] -enable=1 -[CallTips_bindings] -paren-open=<Key-parenleft> -paren-close=<Key-parenright> -check-calltip-cancel=<KeyRelease> -calltip-cancel=<ButtonPress> <Key-Escape> - -[ParenMatch] -enable=0 -style= expression -flash-delay= 500 -bell= 1 -hilite-foreground= black -hilite-background= #43cd80 -[ParenMatch_bindings] -flash-open-paren=<KeyRelease-parenright> <KeyRelease-bracketright> <KeyRelease-braceright> -check-restore=<KeyPress> diff --git a/Tools/idle/config-highlight.def b/Tools/idle/config-highlight.def deleted file mode 100644 index 2b7deab..0000000 --- a/Tools/idle/config-highlight.def +++ /dev/null @@ -1,60 +0,0 @@ -# IDLE reads several config files to determine user preferences. This -# file is the default config file for idle highlight theme settings. - -[IDLE Classic] -normal-foreground= #000000 -normal-background= #ffffff -keyword-foreground= #ff7700 -keyword-background= #ffffff -comment-foreground= #dd0000 -comment-background= #ffffff -string-foreground= #00aa00 -string-background= #ffffff -definition-foreground= #0000ff -definition-background= #ffffff -hilite-foreground= #000000 -hilite-background= gray -break-foreground= black -break-background= #ffff55 -hit-foreground= #ffffff -hit-background= #000000 -error-foreground= #000000 -error-background= #ff7777 -#cursor (only foreground can be set) -cursor-foreground= black -#shell window -stdout-foreground= blue -stdout-background= #ffffff -stderr-foreground= red -stderr-background= #ffffff -console-foreground= #770000 -console-background= #ffffff - -[IDLE New] -normal-foreground= #000000 -normal-background= #ffffff -keyword-foreground= #ff7700 -keyword-background= #ffffff -comment-foreground= #dd0000 -comment-background= #ffffff -string-foreground= #00aa00 -string-background= #ffffff -definition-foreground= #0000ff -definition-background= #ffffff -hilite-foreground= #000000 -hilite-background= gray -break-foreground= black -break-background= #ffff55 -hit-foreground= #ffffff -hit-background= #000000 -error-foreground= #000000 -error-background= #ff7777 -#cursor (only foreground can be set) -cursor-foreground= black -#shell window -stdout-foreground= blue -stdout-background= #ffffff -stderr-foreground= red -stderr-background= #ffffff -console-foreground= #770000 -console-background= #ffffff diff --git a/Tools/idle/config-keys.def b/Tools/idle/config-keys.def deleted file mode 100644 index 4f2be59..0000000 --- a/Tools/idle/config-keys.def +++ /dev/null @@ -1,155 +0,0 @@ -# IDLE reads several config files to determine user preferences. This -# file is the default config file for idle key binding settings. -# Where multiple keys are specified for an action: if they are separated -# by a space (eg. action=<key1> <key2>) then the keys are altenatives, if -# there is no space (eg. action=<key1><key2>) then the keys comprise a -# single 'emacs style' multi-keystoke binding. The tk event specifier 'Key' -# is used in all cases, for consistency in auto key conflict checking in the -# configuration gui. - -[IDLE Classic Windows] -copy=<Control-Key-c> -cut=<Control-Key-x> -paste=<Control-Key-v> -beginning-of-line= <Key-Home> -center-insert=<Control-Key-l> -close-all-windows=<Control-Key-q> -close-window=<Alt-Key-F4> <Meta-Key-F4> -do-nothing=<Control-Key-F12> -end-of-file=<Control-Key-d> -python-docs=<Key-F1> -python-context-help=<Shift-Key-F1> -history-next=<Alt-Key-n> <Meta-Key-n> -history-previous=<Alt-Key-p> <Meta-Key-p> -interrupt-execution=<Control-Key-c> -view-restart=<Key-F6> -restart-shell=<Control-Key-F6> -open-class-browser=<Alt-Key-c> <Meta-Key-c> -open-module=<Alt-Key-m> <Meta-Key-m> -open-new-window=<Control-Key-n> -open-window-from-file=<Control-Key-o> -plain-newline-and-indent=<Control-Key-j> -print-window=<Control-Key-p> -redo=<Control-Shift-Key-z> -remove-selection=<Key-Escape> -save-copy-of-window-as-file=<Alt-Shift-Key-s> -save-window-as-file=<Control-Shift-Key-s> -save-window=<Control-Key-s> -select-all=<Control-Key-a> -toggle-auto-coloring=<Control-Key-slash> -undo=<Control-Key-z> -find=<Control-Key-f> -find-again=<Control-Key-g> <Key-F3> -find-in-files=<Alt-Key-F3> <Meta-Key-F3> -find-selection=<Control-Key-F3> -replace=<Control-Key-h> -goto-line=<Alt-Key-g> <Meta-Key-g> -smart-backspace=<Key-BackSpace> -newline-and-indent=<Key-Return> <Key-KP_Enter> -smart-indent=<Key-Tab> -indent-region=<Control-Key-bracketright> -dedent-region=<Control-Key-bracketleft> -comment-region=<Alt-Key-3> <Meta-Key-3> -uncomment-region=<Alt-Key-4> <Meta-Key-4> -tabify-region=<Alt-Key-5> <Meta-Key-5> -untabify-region=<Alt-Key-6> <Meta-Key-6> -toggle-tabs=<Alt-Key-t> <Meta-Key-t> -change-indentwidth=<Alt-Key-u> <Meta-Key-u> - -[IDLE Classic Unix] -copy=<Alt-Key-w> <Meta-Key-w> -cut=<Control-Key-w> -paste=<Control-Key-y> -beginning-of-line=<Control-Key-a> <Key-Home> -center-insert=<Control-Key-l> -close-all-windows=<Control-Key-x><Control-Key-c> -close-window=<Control-Key-x><Control-Key-0> -do-nothing=<Control-Key-x> -end-of-file=<Control-Key-d> -history-next=<Alt-Key-n> <Meta-Key-n> -history-previous=<Alt-Key-p> <Meta-Key-p> -interrupt-execution=<Control-Key-c> -view-restart=<Key-F6> -restart-shell=<Control-Key-F6> -open-class-browser=<Control-Key-x><Control-Key-b> -open-module=<Control-Key-x><Control-Key-m> -open-new-window=<Control-Key-x><Control-Key-n> -open-window-from-file=<Control-Key-x><Control-Key-f> -plain-newline-and-indent=<Control-Key-j> -print-window=<Control-x><Control-Key-p> -python-docs=<Control-Key-h> -python-context-help=<Control-Shift-Key-h> -redo=<Alt-Key-z> <Meta-Key-z> -remove-selection=<Key-Escape> -save-copy-of-window-as-file=<Control-Key-x><Control-Key-y> -save-window-as-file=<Control-Key-x><Control-Key-w> -save-window=<Control-Key-x><Control-Key-s> -select-all=<Alt-Key-a> <Meta-Key-a> -toggle-auto-coloring=<Control-Key-slash> -undo=<Control-Key-z> -find=<Control-Key-u><Control-Key-u><Control-Key-s> -find-again=<Control-Key-u><Control-Key-s> -find-in-files=<Alt-Key-s> <Meta-Key-s> -find-selection=<Control-Key-s> -replace=<Control-Key-r> -goto-line=<Alt-Key-g> <Meta-Key-g> -smart-backspace=<Key-BackSpace> -newline-and-indent=<Key-Return> <Key-KP_Enter> -smart-indent=<Key-Tab> -indent-region=<Control-Key-bracketright> -dedent-region=<Control-Key-bracketleft> -comment-region=<Alt-Key-3> -uncomment-region=<Alt-Key-4> -tabify-region=<Alt-Key-5> -untabify-region=<Alt-Key-6> -toggle-tabs=<Alt-Key-t> -change-indentwidth=<Alt-Key-u> - -[IDLE Classic Mac] -copy=<Command-Key-c> -cut=<Command-Key-x> -paste=<Command-Key-v> -beginning-of-line= <Key-Home> -center-insert=<Control-Key-l> -close-all-windows=<Command-Key-q> -close-window=<Command-Key-w> -do-nothing=<Control-Key-F12> -end-of-file=<Control-Key-d> -python-docs=<Key-F1> -python-context-help=<Shift-Key-F1> -history-next=<Control-Key-n> -history-previous=<Control-Key-p> -interrupt-execution=<Control-Key-c> -view-restart=<Key-F6> -restart-shell=<Control-Key-F6> -open-class-browser=<Command-Key-b> -open-module=<Command-Key-m> -open-new-window=<Command-Key-n> -open-window-from-file=<Command-Key-o> -plain-newline-and-indent=<Control-Key-j> -print-window=<Command-Key-p> -redo=<Shift-Command-Key-z> -remove-selection=<Key-Escape> -save-window-as-file=<Shift-Command-Key-s> -save-window=<Command-Key-s> -save-copy-of-window-as-file=<Option-Command-Key-s> -select-all=<Command-Key-a> -toggle-auto-coloring=<Control-Key-slash> -undo=<Command-Key-z> -find=<Command-Key-f> -find-again=<Command-Key-g> <Key-F3> -find-in-files=<Command-Key-F3> -find-selection=<Shift-Command-Key-F3> -replace=<Command-Key-r> -goto-line=<Command-Key-j> -smart-backspace=<Key-BackSpace> -newline-and-indent=<Key-Return> <Key-KP_Enter> -smart-indent=<Key-Tab> -indent-region=<Command-Key-bracketright> -dedent-region=<Command-Key-bracketleft> -comment-region=<Control-Key-3> -uncomment-region=<Control-Key-4> -tabify-region=<Control-Key-5> -untabify-region=<Control-Key-6> -toggle-tabs=<Control-Key-t> -change-indentwidth=<Control-Key-u> diff --git a/Tools/idle/config-main.def b/Tools/idle/config-main.def deleted file mode 100644 index 9d520c1..0000000 --- a/Tools/idle/config-main.def +++ /dev/null @@ -1,65 +0,0 @@ -# IDLE reads several config files to determine user preferences. This -# file is the default config file for general idle settings. -# -# When IDLE starts, it will look in -# the following two sets of files, in order: -# -# default configuration -# --------------------- -# config-main.def the default general config file -# config-extensions.def the default extension config file -# config-highlight.def the default highlighting config file -# config-keys.def the default keybinding config file -# -# user configuration -# ------------------- -# ~/.idlerc/idle-main.cfg the user general config file -# ~/.idlerc/idle-extensions.cfg the user extension config file -# ~/.idlerc/idle-highlight.cfg the user highlighting config file -# ~/.idlerc/idle-keys.cfg the user keybinding config file -# -# Any options the user saves through the config dialog will be saved to -# the relevant user config file. Reverting any general setting to the -# default causes that entry to be wiped from the user file and re-read -# from the default file. User highlighting themes or keybinding sets are -# retained unless specifically deleted within the config dialog. Choosing -# one of the default themes or keysets just applies the relevant settings -# from the default file. -# -# Additional help sources are listed in the [HelpFiles] section and must be -# viewable by a web browser (or the Windows Help viewer in the case of .chm -# files). These sources will be listed on the Help menu. The pattern is -# <sequence_number = menu item;/path/to/help/source> -# You can't use a semi-colon in a menu item or path. The path will be platform -# specific because of path separators, drive specs etc. -# -# It is best to use the Configuration GUI to set up additional help sources! -# Example: -#1 = My Extra Help Source;/usr/share/doc/foo/index.html -#2 = Another Help Source;/path/to/another.pdf - -[General] -editor-on-startup= 0 -print-command-posix=lpr %s -print-command-win=start /min notepad /p %s - -[EditorWindow] -width= 80 -height= 30 -font= courier -font-size= 12 -font-bold= 0 - -[Indent] -use-spaces= 1 -num-spaces= 4 - -[Theme] -default= 1 -name= IDLE Classic - -[Keys] -default= 1 -name= IDLE Classic Windows - -[HelpFiles] diff --git a/Tools/idle/configDialog.py b/Tools/idle/configDialog.py deleted file mode 100644 index 814689c..0000000 --- a/Tools/idle/configDialog.py +++ /dev/null @@ -1,1134 +0,0 @@ -"""IDLE Configuration Dialog: support user customization of IDLE by GUI - -Customize font faces, sizes, and colorization attributes. Set indentation -defaults. Customize keybindings. Colorization and keybindings can be -saved as user defined sets. Select startup options including shell/editor -and default window size. Define additional help sources. - -Note that tab width in IDLE is currently fixed at eight due to Tk issues. -Refer to comment in EditorWindow autoindent code for details. - -""" -from Tkinter import * -import tkMessageBox, tkColorChooser, tkFont -import string, copy - -from configHandler import idleConf -from dynOptionMenuWidget import DynOptionMenu -from tabpage import TabPageSet -from keybindingDialog import GetKeysDialog -from configSectionNameDialog import GetCfgSectionNameDialog -from configHelpSourceEdit import GetHelpSourceDialog - -class ConfigDialog(Toplevel): - """ - configuration dialog for idle - """ - def __init__(self,parent,title): - Toplevel.__init__(self, parent) - self.configure(borderwidth=5) - self.geometry("+%d+%d" % (parent.winfo_rootx()+20, - parent.winfo_rooty()+30)) - #Theme Elements. Each theme element key is it's display name. - #The first value of the tuple is the sample area tag name. - #The second value is the display name list sort index. - self.themeElements={'Normal Text':('normal','00'), - 'Python Keywords':('keyword','01'), - 'Python Definitions':('definition','02'), - 'Python Comments':('comment','03'), - 'Python Strings':('string','04'), - 'Selected Text':('hilite','05'), - 'Found Text':('hit','06'), - 'Cursor':('cursor','07'), - 'Error Text':('error','08'), - 'Shell Normal Text':('console','09'), - 'Shell Stdout Text':('stdout','10'), - 'Shell Stderr Text':('stderr','11')} - self.ResetChangedItems() #load initial values in changed items dict - self.CreateWidgets() - self.resizable(height=FALSE,width=FALSE) - self.transient(parent) - self.grab_set() - self.protocol("WM_DELETE_WINDOW", self.Cancel) - self.parent = parent - self.tabPages.focus_set() - #key bindings for this dialog - #self.bind('<Escape>',self.Cancel) #dismiss dialog, no save - #self.bind('<Alt-a>',self.Apply) #apply changes, save - #self.bind('<F1>',self.Help) #context help - self.LoadConfigs() - self.AttachVarCallbacks() #avoid callbacks during LoadConfigs - self.wait_window() - - def CreateWidgets(self): - self.tabPages = TabPageSet(self, - pageNames=['Fonts/Tabs','Highlighting','Keys','General']) - self.tabPages.ChangePage()#activates default (first) page - frameActionButtons = Frame(self) - #action buttons - self.buttonHelp = Button(frameActionButtons,text='Help', - command=self.Help,takefocus=FALSE) - self.buttonOk = Button(frameActionButtons,text='Ok', - command=self.Ok,takefocus=FALSE) - self.buttonApply = Button(frameActionButtons,text='Apply', - command=self.Apply,takefocus=FALSE) - self.buttonCancel = Button(frameActionButtons,text='Cancel', - command=self.Cancel,takefocus=FALSE) - self.CreatePageFontTab() - self.CreatePageHighlight() - self.CreatePageKeys() - self.CreatePageGeneral() - self.buttonHelp.pack(side=RIGHT,padx=5,pady=5) - self.buttonOk.pack(side=LEFT,padx=5,pady=5) - self.buttonApply.pack(side=LEFT,padx=5,pady=5) - self.buttonCancel.pack(side=LEFT,padx=5,pady=5) - frameActionButtons.pack(side=BOTTOM) - self.tabPages.pack(side=TOP,expand=TRUE,fill=BOTH) - - def CreatePageFontTab(self): - #tkVars - self.fontSize=StringVar(self) - self.fontBold=BooleanVar(self) - self.fontName=StringVar(self) - self.spaceNum=IntVar(self) - #self.tabCols=IntVar(self) - self.indentBySpaces=BooleanVar(self) - self.editFont=tkFont.Font(self,('courier',12,'normal')) - ##widget creation - #body frame - frame=self.tabPages.pages['Fonts/Tabs']['page'] - #body section frames - frameFont=Frame(frame,borderwidth=2,relief=GROOVE) - frameIndent=Frame(frame,borderwidth=2,relief=GROOVE) - #frameFont - labelFontTitle=Label(frameFont,text='Set Base Editor Font') - frameFontName=Frame(frameFont) - frameFontParam=Frame(frameFont) - labelFontNameTitle=Label(frameFontName,justify=LEFT, - text='Font :') - self.listFontName=Listbox(frameFontName,height=5,takefocus=FALSE, - exportselection=FALSE) - self.listFontName.bind('<ButtonRelease-1>',self.OnListFontButtonRelease) - scrollFont=Scrollbar(frameFontName) - scrollFont.config(command=self.listFontName.yview) - self.listFontName.config(yscrollcommand=scrollFont.set) - labelFontSizeTitle=Label(frameFontParam,text='Size :') - self.optMenuFontSize=DynOptionMenu(frameFontParam,self.fontSize,None, - command=self.SetFontSample) - checkFontBold=Checkbutton(frameFontParam,variable=self.fontBold, - onvalue=1,offvalue=0,text='Bold',command=self.SetFontSample) - frameFontSample=Frame(frameFont,relief=SOLID,borderwidth=1) - self.labelFontSample=Label(frameFontSample, - text='AaBbCcDdEe\nFfGgHhIiJjK\n1234567890\n#:+=(){}[]', - justify=LEFT,font=self.editFont) - #frameIndent - labelIndentTitle=Label(frameIndent,text='Set Indentation Defaults') - frameIndentType=Frame(frameIndent) - frameIndentSize=Frame(frameIndent) - labelIndentTypeTitle=Label(frameIndentType, - text='Choose indentation type :') - radioUseSpaces=Radiobutton(frameIndentType,variable=self.indentBySpaces, - value=1,text='Tab key inserts spaces') - radioUseTabs=Radiobutton(frameIndentType,variable=self.indentBySpaces, - value=0,text='Tab key inserts tabs') - labelIndentSizeTitle=Label(frameIndentSize, - text='Choose indentation size :') - labelSpaceNumTitle=Label(frameIndentSize,justify=LEFT, - text='indent width') - self.scaleSpaceNum=Scale(frameIndentSize,variable=self.spaceNum, - orient='horizontal',tickinterval=2,from_=2,to=16) - #labeltabColsTitle=Label(frameIndentSize,justify=LEFT, - # text='when tab key inserts tabs,\ncolumns per tab') - #self.scaleTabCols=Scale(frameIndentSize,variable=self.tabCols, - # orient='horizontal',tickinterval=2,from_=2,to=8) - #widget packing - #body - frameFont.pack(side=LEFT,padx=5,pady=10,expand=TRUE,fill=BOTH) - frameIndent.pack(side=LEFT,padx=5,pady=10,fill=Y) - #frameFont - labelFontTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - frameFontName.pack(side=TOP,padx=5,pady=5,fill=X) - frameFontParam.pack(side=TOP,padx=5,pady=5,fill=X) - labelFontNameTitle.pack(side=TOP,anchor=W) - self.listFontName.pack(side=LEFT,expand=TRUE,fill=X) - scrollFont.pack(side=LEFT,fill=Y) - labelFontSizeTitle.pack(side=LEFT,anchor=W) - self.optMenuFontSize.pack(side=LEFT,anchor=W) - checkFontBold.pack(side=LEFT,anchor=W,padx=20) - frameFontSample.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH) - self.labelFontSample.pack(expand=TRUE,fill=BOTH) - #frameIndent - labelIndentTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - frameIndentType.pack(side=TOP,padx=5,fill=X) - frameIndentSize.pack(side=TOP,padx=5,pady=5,fill=BOTH) - labelIndentTypeTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - radioUseSpaces.pack(side=TOP,anchor=W,padx=5) - radioUseTabs.pack(side=TOP,anchor=W,padx=5) - labelIndentSizeTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - labelSpaceNumTitle.pack(side=TOP,anchor=W,padx=5) - self.scaleSpaceNum.pack(side=TOP,padx=5,fill=X) - #labeltabColsTitle.pack(side=TOP,anchor=W,padx=5) - #self.scaleTabCols.pack(side=TOP,padx=5,fill=X) - return frame - - def CreatePageHighlight(self): - self.builtinTheme=StringVar(self) - self.customTheme=StringVar(self) - self.fgHilite=BooleanVar(self) - self.colour=StringVar(self) - self.fontName=StringVar(self) - self.themeIsBuiltin=BooleanVar(self) - self.highlightTarget=StringVar(self) - ##widget creation - #body frame - frame=self.tabPages.pages['Highlighting']['page'] - #body section frames - frameCustom=Frame(frame,borderwidth=2,relief=GROOVE) - frameTheme=Frame(frame,borderwidth=2,relief=GROOVE) - #frameCustom - self.textHighlightSample=Text(frameCustom,relief=SOLID,borderwidth=1, - font=('courier',12,''),cursor='hand2',width=21,height=10, - takefocus=FALSE,highlightthickness=0,wrap=NONE) - text=self.textHighlightSample - text.bind('<Double-Button-1>',lambda e: 'break') - text.bind('<B1-Motion>',lambda e: 'break') - textAndTags=(('#you can click here','comment'),('\n','normal'), - ('#to choose items','comment'),('\n','normal'),('def','keyword'), - (' ','normal'),('func','definition'),('(param):','normal'), - ('\n ','normal'),('"""string"""','string'),('\n var0 = ','normal'), - ("'string'",'string'),('\n var1 = ','normal'),("'selected'",'hilite'), - ('\n var2 = ','normal'),("'found'",'hit'),('\n\n','normal'), - (' error ','error'),(' ','normal'),('cursor |','cursor'), - ('\n ','normal'),('shell','console'),(' ','normal'),('stdout','stdout'), - (' ','normal'),('stderr','stderr'),('\n','normal')) - for txTa in textAndTags: - text.insert(END,txTa[0],txTa[1]) - for element in self.themeElements.keys(): - text.tag_bind(self.themeElements[element][0],'<ButtonPress-1>', - lambda event,elem=element: event.widget.winfo_toplevel() - .highlightTarget.set(elem)) - text.config(state=DISABLED) - self.frameColourSet=Frame(frameCustom,relief=SOLID,borderwidth=1) - frameFgBg=Frame(frameCustom) - labelCustomTitle=Label(frameCustom,text='Set Custom Highlighting') - buttonSetColour=Button(self.frameColourSet,text='Choose Colour for :', - command=self.GetColour,highlightthickness=0) - self.optMenuHighlightTarget=DynOptionMenu(self.frameColourSet, - self.highlightTarget,None,highlightthickness=0)#,command=self.SetHighlightTargetBinding - self.radioFg=Radiobutton(frameFgBg,variable=self.fgHilite, - value=1,text='Foreground',command=self.SetColourSampleBinding) - self.radioBg=Radiobutton(frameFgBg,variable=self.fgHilite, - value=0,text='Background',command=self.SetColourSampleBinding) - self.fgHilite.set(1) - buttonSaveCustomTheme=Button(frameCustom, - text='Save as New Custom Theme',command=self.SaveAsNewTheme) - #frameTheme - labelThemeTitle=Label(frameTheme,text='Select a Highlighting Theme') - labelTypeTitle=Label(frameTheme,text='Select : ') - self.radioThemeBuiltin=Radiobutton(frameTheme,variable=self.themeIsBuiltin, - value=1,command=self.SetThemeType,text='a Built-in Theme') - self.radioThemeCustom=Radiobutton(frameTheme,variable=self.themeIsBuiltin, - value=0,command=self.SetThemeType,text='a Custom Theme') - self.optMenuThemeBuiltin=DynOptionMenu(frameTheme, - self.builtinTheme,None,command=None) - self.optMenuThemeCustom=DynOptionMenu(frameTheme, - self.customTheme,None,command=None) - self.buttonDeleteCustomTheme=Button(frameTheme,text='Delete Custom Theme', - command=self.DeleteCustomTheme) - ##widget packing - #body - frameCustom.pack(side=LEFT,padx=5,pady=10,expand=TRUE,fill=BOTH) - frameTheme.pack(side=LEFT,padx=5,pady=10,fill=Y) - #frameCustom - labelCustomTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - self.frameColourSet.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=X) - frameFgBg.pack(side=TOP,padx=5,pady=0) - self.textHighlightSample.pack(side=TOP,padx=5,pady=5,expand=TRUE, - fill=BOTH) - buttonSetColour.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=4) - self.optMenuHighlightTarget.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=3) - self.radioFg.pack(side=LEFT,anchor=E) - self.radioBg.pack(side=RIGHT,anchor=W) - buttonSaveCustomTheme.pack(side=BOTTOM,fill=X,padx=5,pady=5) - #frameTheme - labelThemeTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - labelTypeTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - self.radioThemeBuiltin.pack(side=TOP,anchor=W,padx=5) - self.radioThemeCustom.pack(side=TOP,anchor=W,padx=5,pady=2) - self.optMenuThemeBuiltin.pack(side=TOP,fill=X,padx=5,pady=5) - self.optMenuThemeCustom.pack(side=TOP,fill=X,anchor=W,padx=5,pady=5) - self.buttonDeleteCustomTheme.pack(side=TOP,fill=X,padx=5,pady=5) - return frame - - def CreatePageKeys(self): - #tkVars - self.bindingTarget=StringVar(self) - self.builtinKeys=StringVar(self) - self.customKeys=StringVar(self) - self.keysAreBuiltin=BooleanVar(self) - self.keyBinding=StringVar(self) - ##widget creation - #body frame - frame=self.tabPages.pages['Keys']['page'] - #body section frames - frameCustom=Frame(frame,borderwidth=2,relief=GROOVE) - frameKeySets=Frame(frame,borderwidth=2,relief=GROOVE) - #frameCustom - frameTarget=Frame(frameCustom) - labelCustomTitle=Label(frameCustom,text='Set Custom Key Bindings') - labelTargetTitle=Label(frameTarget,text='Action - Key(s)') - scrollTargetY=Scrollbar(frameTarget) - scrollTargetX=Scrollbar(frameTarget,orient=HORIZONTAL) - self.listBindings=Listbox(frameTarget,takefocus=FALSE, - exportselection=FALSE) - self.listBindings.bind('<ButtonRelease-1>',self.KeyBindingSelected) - scrollTargetY.config(command=self.listBindings.yview) - scrollTargetX.config(command=self.listBindings.xview) - self.listBindings.config(yscrollcommand=scrollTargetY.set) - self.listBindings.config(xscrollcommand=scrollTargetX.set) - self.buttonNewKeys=Button(frameCustom,text='Get New Keys for Selection', - command=self.GetNewKeys,state=DISABLED) - buttonSaveCustomKeys=Button(frameCustom, - text='Save as New Custom Key Set',command=self.SaveAsNewKeySet) - #frameKeySets - labelKeysTitle=Label(frameKeySets,text='Select a Key Set') - labelTypeTitle=Label(frameKeySets,text='Select : ') - self.radioKeysBuiltin=Radiobutton(frameKeySets,variable=self.keysAreBuiltin, - value=1,command=self.SetKeysType,text='a Built-in Key Set') - self.radioKeysCustom=Radiobutton(frameKeySets,variable=self.keysAreBuiltin, - value=0,command=self.SetKeysType,text='a Custom Key Set') - self.optMenuKeysBuiltin=DynOptionMenu(frameKeySets, - self.builtinKeys,None,command=None) - self.optMenuKeysCustom=DynOptionMenu(frameKeySets, - self.customKeys,None,command=None) - self.buttonDeleteCustomKeys=Button(frameKeySets,text='Delete Custom Key Set', - command=self.DeleteCustomKeys) - ##widget packing - #body - frameCustom.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH) - frameKeySets.pack(side=LEFT,padx=5,pady=5,fill=Y) - #frameCustom - labelCustomTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - buttonSaveCustomKeys.pack(side=BOTTOM,fill=X,padx=5,pady=5) - self.buttonNewKeys.pack(side=BOTTOM,fill=X,padx=5,pady=5) - frameTarget.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH) - #frame target - frameTarget.columnconfigure(0,weight=1) - frameTarget.rowconfigure(1,weight=1) - labelTargetTitle.grid(row=0,column=0,columnspan=2,sticky=W) - self.listBindings.grid(row=1,column=0,sticky=NSEW) - scrollTargetY.grid(row=1,column=1,sticky=NS) - scrollTargetX.grid(row=2,column=0,sticky=EW) - #frameKeySets - labelKeysTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - labelTypeTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - self.radioKeysBuiltin.pack(side=TOP,anchor=W,padx=5) - self.radioKeysCustom.pack(side=TOP,anchor=W,padx=5,pady=2) - self.optMenuKeysBuiltin.pack(side=TOP,fill=X,padx=5,pady=5) - self.optMenuKeysCustom.pack(side=TOP,fill=X,anchor=W,padx=5,pady=5) - self.buttonDeleteCustomKeys.pack(side=TOP,fill=X,padx=5,pady=5) - return frame - - def CreatePageGeneral(self): - #tkVars - self.winWidth=StringVar(self) - self.winHeight=StringVar(self) - self.startupEdit=IntVar(self) - self.userHelpBrowser=BooleanVar(self) - self.helpBrowser=StringVar(self) - #widget creation - #body - frame=self.tabPages.pages['General']['page'] - #body section frames - frameRun=Frame(frame,borderwidth=2,relief=GROOVE) - frameWinSize=Frame(frame,borderwidth=2,relief=GROOVE) - frameHelp=Frame(frame,borderwidth=2,relief=GROOVE) - #frameRun - labelRunTitle=Label(frameRun,text='Startup Preferences') - labelRunChoiceTitle=Label(frameRun,text='On Startup : ') - radioStartupEdit=Radiobutton(frameRun,variable=self.startupEdit, - value=1,command=self.SetKeysType,text="Open Edit Window") - radioStartupShell=Radiobutton(frameRun,variable=self.startupEdit, - value=0,command=self.SetKeysType,text='Open Shell Window') - #frameWinSize - labelWinSizeTitle=Label(frameWinSize,text='Initial Window Size'+ - ' (in characters)') - labelWinWidthTitle=Label(frameWinSize,text='Width') - entryWinWidth=Entry(frameWinSize,textvariable=self.winWidth, - width=3) - labelWinHeightTitle=Label(frameWinSize,text='Height') - entryWinHeight=Entry(frameWinSize,textvariable=self.winHeight, - width=3) - #frameHelp - labelHelpTitle=Label(frameHelp,text='Help Options') - frameHelpList=Frame(frameHelp) - frameHelpListButtons=Frame(frameHelpList) - labelHelpListTitle=Label(frameHelpList,text='Additional Help Sources:') - scrollHelpList=Scrollbar(frameHelpList) - self.listHelp=Listbox(frameHelpList,height=5,takefocus=FALSE, - exportselection=FALSE) - scrollHelpList.config(command=self.listHelp.yview) - self.listHelp.config(yscrollcommand=scrollHelpList.set) - self.listHelp.bind('<ButtonRelease-1>',self.HelpSourceSelected) - self.buttonHelpListEdit=Button(frameHelpListButtons,text='Edit', - state=DISABLED,width=8,command=self.HelpListItemEdit) - self.buttonHelpListAdd=Button(frameHelpListButtons,text='Add', - width=8,command=self.HelpListItemAdd) - self.buttonHelpListRemove=Button(frameHelpListButtons,text='Remove', - state=DISABLED,width=8,command=self.HelpListItemRemove) - # the following is better handled by the BROWSER environment - # variable under unix/linux - #checkHelpBrowser=Checkbutton(frameHelp,variable=self.userHelpBrowser, - # onvalue=1,offvalue=0,text='user specified (html) help browser:', - # command=self.OnCheckUserHelpBrowser) - #self.entryHelpBrowser=Entry(frameHelp,textvariable=self.helpBrowser, - # width=40) - #widget packing - #body - frameRun.pack(side=TOP,padx=5,pady=5,fill=X) - frameWinSize.pack(side=TOP,padx=5,pady=5,fill=X) - frameHelp.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH) - #frameRun - labelRunTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - labelRunChoiceTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - radioStartupEdit.pack(side=LEFT,anchor=W,padx=5,pady=5) - radioStartupShell.pack(side=LEFT,anchor=W,padx=5,pady=5) - #frameWinSize - labelWinSizeTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - entryWinHeight.pack(side=RIGHT,anchor=E,padx=10,pady=5) - labelWinHeightTitle.pack(side=RIGHT,anchor=E,pady=5) - entryWinWidth.pack(side=RIGHT,anchor=E,padx=10,pady=5) - labelWinWidthTitle.pack(side=RIGHT,anchor=E,pady=5) - #frameHelp - labelHelpTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - frameHelpListButtons.pack(side=RIGHT,padx=5,pady=5,fill=Y) - frameHelpList.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH) - labelHelpListTitle.pack(side=TOP,anchor=W) - scrollHelpList.pack(side=RIGHT,anchor=W,fill=Y) - self.listHelp.pack(side=LEFT,anchor=E,expand=TRUE,fill=BOTH) - self.buttonHelpListEdit.pack(side=TOP,anchor=W,pady=5) - self.buttonHelpListAdd.pack(side=TOP,anchor=W) - self.buttonHelpListRemove.pack(side=TOP,anchor=W,pady=5) - #checkHelpBrowser.pack(side=TOP,anchor=W,padx=5) - #self.entryHelpBrowser.pack(side=TOP,anchor=W,padx=5,pady=5) - return frame - - def AttachVarCallbacks(self): - self.fontSize.trace_variable('w',self.VarChanged_fontSize) - self.fontName.trace_variable('w',self.VarChanged_fontName) - self.fontBold.trace_variable('w',self.VarChanged_fontBold) - self.spaceNum.trace_variable('w',self.VarChanged_spaceNum) - #self.tabCols.trace_variable('w',self.VarChanged_tabCols) - self.indentBySpaces.trace_variable('w',self.VarChanged_indentBySpaces) - self.colour.trace_variable('w',self.VarChanged_colour) - self.builtinTheme.trace_variable('w',self.VarChanged_builtinTheme) - self.customTheme.trace_variable('w',self.VarChanged_customTheme) - self.themeIsBuiltin.trace_variable('w',self.VarChanged_themeIsBuiltin) - self.highlightTarget.trace_variable('w',self.VarChanged_highlightTarget) - self.keyBinding.trace_variable('w',self.VarChanged_keyBinding) - self.builtinKeys.trace_variable('w',self.VarChanged_builtinKeys) - self.customKeys.trace_variable('w',self.VarChanged_customKeys) - self.keysAreBuiltin.trace_variable('w',self.VarChanged_keysAreBuiltin) - self.winWidth.trace_variable('w',self.VarChanged_winWidth) - self.winHeight.trace_variable('w',self.VarChanged_winHeight) - self.startupEdit.trace_variable('w',self.VarChanged_startupEdit) - - def VarChanged_fontSize(self,*params): - value=self.fontSize.get() - self.AddChangedItem('main','EditorWindow','font-size',value) - - def VarChanged_fontName(self,*params): - value=self.fontName.get() - self.AddChangedItem('main','EditorWindow','font',value) - - def VarChanged_fontBold(self,*params): - value=self.fontBold.get() - self.AddChangedItem('main','EditorWindow','font-bold',value) - - def VarChanged_indentBySpaces(self,*params): - value=self.indentBySpaces.get() - self.AddChangedItem('main','Indent','use-spaces',value) - - def VarChanged_spaceNum(self,*params): - value=self.spaceNum.get() - self.AddChangedItem('main','Indent','num-spaces',value) - - #def VarChanged_tabCols(self,*params): - # value=self.tabCols.get() - # self.AddChangedItem('main','Indent','tab-cols',value) - - def VarChanged_colour(self,*params): - self.OnNewColourSet() - - def VarChanged_builtinTheme(self,*params): - value=self.builtinTheme.get() - self.AddChangedItem('main','Theme','name',value) - self.PaintThemeSample() - - def VarChanged_customTheme(self,*params): - value=self.customTheme.get() - if value != '- no custom themes -': - self.AddChangedItem('main','Theme','name',value) - self.PaintThemeSample() - - def VarChanged_themeIsBuiltin(self,*params): - value=self.themeIsBuiltin.get() - self.AddChangedItem('main','Theme','default',value) - if value: - self.VarChanged_builtinTheme() - else: - self.VarChanged_customTheme() - - def VarChanged_highlightTarget(self,*params): - self.SetHighlightTarget() - - def VarChanged_keyBinding(self,*params): - value=self.keyBinding.get() - keySet=self.customKeys.get() - event=self.listBindings.get(ANCHOR).split()[0] - if idleConf.IsCoreBinding(event): - #this is a core keybinding - self.AddChangedItem('keys',keySet,event,value) - else: #this is an extension key binding - extName=idleConf.GetExtnNameForEvent(event) - extKeybindSection=extName+'_cfgBindings' - self.AddChangedItem('extensions',extKeybindSection,event,value) - - def VarChanged_builtinKeys(self,*params): - value=self.builtinKeys.get() - self.AddChangedItem('main','Keys','name',value) - self.LoadKeysList(value) - - def VarChanged_customKeys(self,*params): - value=self.customKeys.get() - if value != '- no custom keys -': - self.AddChangedItem('main','Keys','name',value) - self.LoadKeysList(value) - - def VarChanged_keysAreBuiltin(self,*params): - value=self.keysAreBuiltin.get() - self.AddChangedItem('main','Keys','default',value) - if value: - self.VarChanged_builtinKeys() - else: - self.VarChanged_customKeys() - - def VarChanged_winWidth(self,*params): - value=self.winWidth.get() - self.AddChangedItem('main','EditorWindow','width',value) - - def VarChanged_winHeight(self,*params): - value=self.winHeight.get() - self.AddChangedItem('main','EditorWindow','height',value) - - def VarChanged_startupEdit(self,*params): - value=self.startupEdit.get() - self.AddChangedItem('main','General','editor-on-startup',value) - - def ResetChangedItems(self): - #When any config item is changed in this dialog, an entry - #should be made in the relevant section (config type) of this - #dictionary. The key should be the config file section name and the - #value a dictionary, whose key:value pairs are item=value pairs for - #that config file section. - self.changedItems={'main':{},'highlight':{},'keys':{},'extensions':{}} - - def AddChangedItem(self,type,section,item,value): - value=str(value) #make sure we use a string - if not self.changedItems[type].has_key(section): - self.changedItems[type][section]={} - self.changedItems[type][section][item]=value - - def GetDefaultItems(self): - dItems={'main':{},'highlight':{},'keys':{},'extensions':{}} - for configType in dItems.keys(): - sections=idleConf.GetSectionList('default',configType) - for section in sections: - dItems[configType][section]={} - options=idleConf.defaultCfg[configType].GetOptionList(section) - for option in options: - dItems[configType][section][option]=( - idleConf.defaultCfg[configType].Get(section,option)) - return dItems - - def SetThemeType(self): - if self.themeIsBuiltin.get(): - self.optMenuThemeBuiltin.config(state=NORMAL) - self.optMenuThemeCustom.config(state=DISABLED) - self.buttonDeleteCustomTheme.config(state=DISABLED) - else: - self.optMenuThemeBuiltin.config(state=DISABLED) - self.radioThemeCustom.config(state=NORMAL) - self.optMenuThemeCustom.config(state=NORMAL) - self.buttonDeleteCustomTheme.config(state=NORMAL) - - def SetKeysType(self): - if self.keysAreBuiltin.get(): - self.optMenuKeysBuiltin.config(state=NORMAL) - self.optMenuKeysCustom.config(state=DISABLED) - self.buttonDeleteCustomKeys.config(state=DISABLED) - else: - self.optMenuKeysBuiltin.config(state=DISABLED) - self.radioKeysCustom.config(state=NORMAL) - self.optMenuKeysCustom.config(state=NORMAL) - self.buttonDeleteCustomKeys.config(state=NORMAL) - - def GetNewKeys(self): - listIndex=self.listBindings.index(ANCHOR) - binding=self.listBindings.get(listIndex) - bindName=binding.split()[0] #first part, up to first space - if self.keysAreBuiltin.get(): - currentKeySetName=self.builtinKeys.get() - else: - currentKeySetName=self.customKeys.get() - currentBindings=idleConf.GetCurrentKeySet() - if currentKeySetName in self.changedItems['keys'].keys(): #unsaved changes - keySetChanges=self.changedItems['keys'][currentKeySetName] - for event in keySetChanges.keys(): - currentBindings[event]=keySetChanges[event].split() - currentKeySequences=currentBindings.values() - newKeys=GetKeysDialog(self,'Get New Keys',bindName, - currentKeySequences).result - if newKeys: #new keys were specified - if self.keysAreBuiltin.get(): #current key set is a built-in - message=('Your changes will be saved as a new Custom Key Set. '+ - 'Enter a name for your new Custom Key Set below.') - newKeySet=self.GetNewKeysName(message) - if not newKeySet: #user cancelled custom key set creation - self.listBindings.select_set(listIndex) - self.listBindings.select_anchor(listIndex) - return - else: #create new custom key set based on previously active key set - self.CreateNewKeySet(newKeySet) - self.listBindings.delete(listIndex) - self.listBindings.insert(listIndex,bindName+' - '+newKeys) - self.listBindings.select_set(listIndex) - self.listBindings.select_anchor(listIndex) - self.keyBinding.set(newKeys) - else: - self.listBindings.select_set(listIndex) - self.listBindings.select_anchor(listIndex) - - def GetNewKeysName(self,message): - usedNames=(idleConf.GetSectionList('user','keys')+ - idleConf.GetSectionList('default','keys')) - newKeySet=GetCfgSectionNameDialog(self,'New Custom Key Set', - message,usedNames).result - return newKeySet - - def SaveAsNewKeySet(self): - newKeysName=self.GetNewKeysName('New Key Set Name:') - if newKeysName: - self.CreateNewKeySet(newKeysName) - - def KeyBindingSelected(self,event): - self.buttonNewKeys.config(state=NORMAL) - - def CreateNewKeySet(self,newKeySetName): - #creates new custom key set based on the previously active key set, - #and makes the new key set active - if self.keysAreBuiltin.get(): - prevKeySetName=self.builtinKeys.get() - else: - prevKeySetName=self.customKeys.get() - prevKeys=idleConf.GetCoreKeys(prevKeySetName) - newKeys={} - for event in prevKeys.keys(): #add key set to changed items - eventName=event[2:-2] #trim off the angle brackets - binding=string.join(prevKeys[event]) - newKeys[eventName]=binding - #handle any unsaved changes to prev key set - if prevKeySetName in self.changedItems['keys'].keys(): - keySetChanges=self.changedItems['keys'][prevKeySetName] - for event in keySetChanges.keys(): - newKeys[event]=keySetChanges[event] - #save the new theme - self.SaveNewKeySet(newKeySetName,newKeys) - #change gui over to the new key set - customKeyList=idleConf.GetSectionList('user','keys') - customKeyList.sort() - self.optMenuKeysCustom.SetMenu(customKeyList,newKeySetName) - self.keysAreBuiltin.set(0) - self.SetKeysType() - - def LoadKeysList(self,keySetName): - reselect=0 - newKeySet=0 - if self.listBindings.curselection(): - reselect=1 - listIndex=self.listBindings.index(ANCHOR) - keySet=idleConf.GetKeySet(keySetName) - bindNames=keySet.keys() - bindNames.sort() - self.listBindings.delete(0,END) - for bindName in bindNames: - key=string.join(keySet[bindName]) #make key(s) into a string - bindName=bindName[2:-2] #trim off the angle brackets - if keySetName in self.changedItems['keys'].keys(): - #handle any unsaved changes to this key set - if bindName in self.changedItems['keys'][keySetName].keys(): - key=self.changedItems['keys'][keySetName][bindName] - self.listBindings.insert(END, bindName+' - '+key) - if reselect: - self.listBindings.see(listIndex) - self.listBindings.select_set(listIndex) - self.listBindings.select_anchor(listIndex) - - def DeleteCustomKeys(self): - keySetName=self.customKeys.get() - if not tkMessageBox.askyesno('Delete Key Set','Are you sure you wish '+ - 'to delete the key set '+`keySetName`+' ?', - parent=self): - return - #remove key set from config - idleConf.userCfg['keys'].remove_section(keySetName) - if self.changedItems['keys'].has_key(keySetName): - del(self.changedItems['keys'][keySetName]) - #write changes - idleConf.userCfg['keys'].Save() - #reload user key set list - itemList=idleConf.GetSectionList('user','keys') - itemList.sort() - if not itemList: - self.radioKeysCustom.config(state=DISABLED) - self.optMenuKeysCustom.SetMenu(itemList,'- no custom keys -') - else: - self.optMenuKeysCustom.SetMenu(itemList,itemList[0]) - #revert to default key set - self.keysAreBuiltin.set(idleConf.defaultCfg['main'].Get('Keys','default')) - self.builtinKeys.set(idleConf.defaultCfg['main'].Get('Keys','name')) - #user can't back out of these changes, they must be applied now - self.Apply() - self.SetKeysType() - - def DeleteCustomTheme(self): - themeName=self.customTheme.get() - if not tkMessageBox.askyesno('Delete Theme','Are you sure you wish '+ - 'to delete the theme '+`themeName`+' ?', - parent=self): - return - #remove theme from config - idleConf.userCfg['highlight'].remove_section(themeName) - if self.changedItems['highlight'].has_key(themeName): - del(self.changedItems['highlight'][themeName]) - #write changes - idleConf.userCfg['highlight'].Save() - #reload user theme list - itemList=idleConf.GetSectionList('user','highlight') - itemList.sort() - if not itemList: - self.radioThemeCustom.config(state=DISABLED) - self.optMenuThemeCustom.SetMenu(itemList,'- no custom themes -') - else: - self.optMenuThemeCustom.SetMenu(itemList,itemList[0]) - #revert to default theme - self.themeIsBuiltin.set(idleConf.defaultCfg['main'].Get('Theme','default')) - self.builtinTheme.set(idleConf.defaultCfg['main'].Get('Theme','name')) - #user can't back out of these changes, they must be applied now - self.Apply() - self.SetThemeType() - - def GetColour(self): - target=self.highlightTarget.get() - prevColour=self.frameColourSet.cget('bg') - rgbTuplet, colourString = tkColorChooser.askcolor(parent=self, - title='Pick new colour for : '+target,initialcolor=prevColour) - if colourString and (colourString!=prevColour): - #user didn't cancel, and they chose a new colour - if self.themeIsBuiltin.get(): #current theme is a built-in - message=('Your changes will be saved as a new Custom Theme. '+ - 'Enter a name for your new Custom Theme below.') - newTheme=self.GetNewThemeName(message) - if not newTheme: #user cancelled custom theme creation - return - else: #create new custom theme based on previously active theme - self.CreateNewTheme(newTheme) - self.colour.set(colourString) - else: #current theme is user defined - self.colour.set(colourString) - - def OnNewColourSet(self): - newColour=self.colour.get() - self.frameColourSet.config(bg=newColour)#set sample - if self.fgHilite.get(): plane='foreground' - else: plane='background' - sampleElement=self.themeElements[self.highlightTarget.get()][0] - apply(self.textHighlightSample.tag_config, - (sampleElement,),{plane:newColour}) - theme=self.customTheme.get() - themeElement=sampleElement+'-'+plane - self.AddChangedItem('highlight',theme,themeElement,newColour) - - def GetNewThemeName(self,message): - usedNames=(idleConf.GetSectionList('user','highlight')+ - idleConf.GetSectionList('default','highlight')) - newTheme=GetCfgSectionNameDialog(self,'New Custom Theme', - message,usedNames).result - return newTheme - - def SaveAsNewTheme(self): - newThemeName=self.GetNewThemeName('New Theme Name:') - if newThemeName: - self.CreateNewTheme(newThemeName) - - def CreateNewTheme(self,newThemeName): - #creates new custom theme based on the previously active theme, - #and makes the new theme active - if self.themeIsBuiltin.get(): - themeType='default' - themeName=self.builtinTheme.get() - else: - themeType='user' - themeName=self.customTheme.get() - newTheme=idleConf.GetThemeDict(themeType,themeName) - #apply any of the old theme's unsaved changes to the new theme - if themeName in self.changedItems['highlight'].keys(): - themeChanges=self.changedItems['highlight'][themeName] - for element in themeChanges.keys(): - newTheme[element]=themeChanges[element] - #save the new theme - self.SaveNewTheme(newThemeName,newTheme) - #change gui over to the new theme - customThemeList=idleConf.GetSectionList('user','highlight') - customThemeList.sort() - self.optMenuThemeCustom.SetMenu(customThemeList,newThemeName) - self.themeIsBuiltin.set(0) - self.SetThemeType() - - def OnListFontButtonRelease(self,event): - self.fontName.set(self.listFontName.get(ANCHOR)) - self.SetFontSample() - - def SetFontSample(self,event=None): - fontName=self.fontName.get() - if self.fontBold.get(): - fontWeight=tkFont.BOLD - else: - fontWeight=tkFont.NORMAL - self.editFont.config(size=self.fontSize.get(), - weight=fontWeight,family=fontName) - - def SetHighlightTarget(self): - if self.highlightTarget.get()=='Cursor': #bg not possible - self.radioFg.config(state=DISABLED) - self.radioBg.config(state=DISABLED) - self.fgHilite.set(1) - else: #both fg and bg can be set - self.radioFg.config(state=NORMAL) - self.radioBg.config(state=NORMAL) - self.fgHilite.set(1) - self.SetColourSample() - - def SetColourSampleBinding(self,*args): - self.SetColourSample() - - def SetColourSample(self): - #set the colour smaple area - tag=self.themeElements[self.highlightTarget.get()][0] - if self.fgHilite.get(): plane='foreground' - else: plane='background' - colour=self.textHighlightSample.tag_cget(tag,plane) - self.frameColourSet.config(bg=colour) - - def PaintThemeSample(self): - if self.themeIsBuiltin.get(): #a default theme - theme=self.builtinTheme.get() - else: #a user theme - theme=self.customTheme.get() - for elementTitle in self.themeElements.keys(): - element=self.themeElements[elementTitle][0] - colours=idleConf.GetHighlight(theme,element) - if element=='cursor': #cursor sample needs special painting - colours['background']=idleConf.GetHighlight(theme, - 'normal', fgBg='bg') - #handle any unsaved changes to this theme - if theme in self.changedItems['highlight'].keys(): - themeDict=self.changedItems['highlight'][theme] - if themeDict.has_key(element+'-foreground'): - colours['foreground']=themeDict[element+'-foreground'] - if themeDict.has_key(element+'-background'): - colours['background']=themeDict[element+'-background'] - apply(self.textHighlightSample.tag_config,(element,),colours) - self.SetColourSample() - -## def OnCheckUserHelpBrowser(self): -## if self.userHelpBrowser.get(): -## self.entryHelpBrowser.config(state=NORMAL) -## else: -## self.entryHelpBrowser.config(state=DISABLED) - - def HelpSourceSelected(self,event): - self.SetHelpListButtonStates() - - def SetHelpListButtonStates(self): - if self.listHelp.size()<1: #no entries in list - self.buttonHelpListEdit.config(state=DISABLED) - self.buttonHelpListRemove.config(state=DISABLED) - else: #there are some entries - if self.listHelp.curselection(): #there currently is a selection - self.buttonHelpListEdit.config(state=NORMAL) - self.buttonHelpListRemove.config(state=NORMAL) - else: #there currently is not a selection - self.buttonHelpListEdit.config(state=DISABLED) - self.buttonHelpListRemove.config(state=DISABLED) - - def HelpListItemAdd(self): - helpSource=GetHelpSourceDialog(self,'New Help Source').result - if helpSource: - self.userHelpList.append( (helpSource[0],helpSource[1]) ) - self.listHelp.insert(END,helpSource[0]) - self.UpdateUserHelpChangedItems() - self.SetHelpListButtonStates() - - def HelpListItemEdit(self): - itemIndex=self.listHelp.index(ANCHOR) - helpSource=self.userHelpList[itemIndex] - newHelpSource=GetHelpSourceDialog(self,'Edit Help Source', - menuItem=helpSource[0],filePath=helpSource[1]).result - if (not newHelpSource) or (newHelpSource==helpSource): - return #no changes - self.userHelpList[itemIndex]=newHelpSource - self.listHelp.delete(itemIndex) - self.listHelp.insert(itemIndex,newHelpSource[0]) - self.UpdateUserHelpChangedItems() - self.SetHelpListButtonStates() - - def HelpListItemRemove(self): - itemIndex=self.listHelp.index(ANCHOR) - del(self.userHelpList[itemIndex]) - self.listHelp.delete(itemIndex) - self.UpdateUserHelpChangedItems() - self.SetHelpListButtonStates() - - def UpdateUserHelpChangedItems(self): - "Clear and rebuild the HelpFiles section in self.changedItems" - self.changedItems['main']['HelpFiles'] = {} - for num in range(1,len(self.userHelpList)+1): - self.AddChangedItem('main','HelpFiles',str(num), - string.join(self.userHelpList[num-1][:2],';')) - - def LoadFontCfg(self): - ##base editor font selection list - fonts=list(tkFont.families(self)) - fonts.sort() - for font in fonts: - self.listFontName.insert(END,font) - configuredFont=idleConf.GetOption('main','EditorWindow','font', - default='courier') - self.fontName.set(configuredFont) - if configuredFont in fonts: - currentFontIndex=fonts.index(configuredFont) - self.listFontName.see(currentFontIndex) - self.listFontName.select_set(currentFontIndex) - self.listFontName.select_anchor(currentFontIndex) - ##font size dropdown - fontSize=idleConf.GetOption('main','EditorWindow','font-size', - default='12') - self.optMenuFontSize.SetMenu(('7','8','9','10','11','12','13','14', - '16','18','20','22'),fontSize ) - ##fontWeight - self.fontBold.set(idleConf.GetOption('main','EditorWindow', - 'font-bold',default=0,type='bool')) - ##font sample - self.SetFontSample() - - def LoadTabCfg(self): - ##indent type radiobuttons - spaceIndent=idleConf.GetOption('main','Indent','use-spaces', - default=1,type='bool') - self.indentBySpaces.set(spaceIndent) - ##indent sizes - spaceNum=idleConf.GetOption('main','Indent','num-spaces', - default=4,type='int') - #tabCols=idleConf.GetOption('main','Indent','tab-cols', - # default=4,type='int') - self.spaceNum.set(spaceNum) - #self.tabCols.set(tabCols) - - def LoadThemeCfg(self): - ##current theme type radiobutton - self.themeIsBuiltin.set(idleConf.GetOption('main','Theme','default', - type='bool',default=1)) - ##currently set theme - currentOption=idleConf.CurrentTheme() - ##load available theme option menus - if self.themeIsBuiltin.get(): #default theme selected - itemList=idleConf.GetSectionList('default','highlight') - itemList.sort() - self.optMenuThemeBuiltin.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('user','highlight') - itemList.sort() - if not itemList: - self.radioThemeCustom.config(state=DISABLED) - self.customTheme.set('- no custom themes -') - else: - self.optMenuThemeCustom.SetMenu(itemList,itemList[0]) - else: #user theme selected - itemList=idleConf.GetSectionList('user','highlight') - itemList.sort() - self.optMenuThemeCustom.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('default','highlight') - itemList.sort() - self.optMenuThemeBuiltin.SetMenu(itemList,itemList[0]) - self.SetThemeType() - ##load theme element option menu - themeNames=self.themeElements.keys() - themeNames.sort(self.__ThemeNameIndexCompare) - self.optMenuHighlightTarget.SetMenu(themeNames,themeNames[0]) - self.PaintThemeSample() - self.SetHighlightTarget() - - def __ThemeNameIndexCompare(self,a,b): - if self.themeElements[a][1]<self.themeElements[b][1]: return -1 - elif self.themeElements[a][1]==self.themeElements[b][1]: return 0 - else: return 1 - - def LoadKeyCfg(self): - ##current keys type radiobutton - self.keysAreBuiltin.set(idleConf.GetOption('main','Keys','default', - type='bool',default=1)) - ##currently set keys - currentOption=idleConf.CurrentKeys() - ##load available keyset option menus - if self.keysAreBuiltin.get(): #default theme selected - itemList=idleConf.GetSectionList('default','keys') - itemList.sort() - self.optMenuKeysBuiltin.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('user','keys') - itemList.sort() - if not itemList: - self.radioKeysCustom.config(state=DISABLED) - self.customKeys.set('- no custom keys -') - else: - self.optMenuKeysCustom.SetMenu(itemList,itemList[0]) - else: #user key set selected - itemList=idleConf.GetSectionList('user','keys') - itemList.sort() - self.optMenuKeysCustom.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('default','keys') - itemList.sort() - self.optMenuKeysBuiltin.SetMenu(itemList,itemList[0]) - self.SetKeysType() - ##load keyset element list - keySetName=idleConf.CurrentKeys() - self.LoadKeysList(keySetName) - - def LoadGeneralCfg(self): - #startup state - self.startupEdit.set(idleConf.GetOption('main','General', - 'editor-on-startup',default=1,type='bool')) - #initial window size - self.winWidth.set(idleConf.GetOption('main','EditorWindow','width')) - self.winHeight.set(idleConf.GetOption('main','EditorWindow','height')) - # additional help sources - self.userHelpList = idleConf.GetAllExtraHelpSourcesList() - for helpItem in self.userHelpList: - self.listHelp.insert(END,helpItem[0]) - self.SetHelpListButtonStates() - #self.userHelpBrowser.set(idleConf.GetOption('main','General', - # 'user-help-browser',default=0,type='bool')) - #self.helpBrowser.set(idleConf.GetOption('main','General', - # 'user-help-browser-command',default='')) - #self.OnCheckUserHelpBrowser() - - def LoadConfigs(self): - """ - load configuration from default and user config files and populate - the widgets on the config dialog pages. - """ - ### fonts / tabs page - self.LoadFontCfg() - self.LoadTabCfg() - ### highlighting page - self.LoadThemeCfg() - ### keys page - self.LoadKeyCfg() - ### general page - self.LoadGeneralCfg() - - def SaveNewKeySet(self,keySetName,keySet): - """ - save a newly created core key set. - keySetName - string, the name of the new key set - keySet - dictionary containing the new key set - """ - if not idleConf.userCfg['keys'].has_section(keySetName): - idleConf.userCfg['keys'].add_section(keySetName) - for event in keySet.keys(): - value=keySet[event] - idleConf.userCfg['keys'].SetOption(keySetName,event,value) - - def SaveNewTheme(self,themeName,theme): - """ - save a newly created theme. - themeName - string, the name of the new theme - theme - dictionary containing the new theme - """ - if not idleConf.userCfg['highlight'].has_section(themeName): - idleConf.userCfg['highlight'].add_section(themeName) - for element in theme.keys(): - value=theme[element] - idleConf.userCfg['highlight'].SetOption(themeName,element,value) - - def SetUserValue(self,configType,section,item,value): - if idleConf.defaultCfg[configType].has_option(section,item): - if idleConf.defaultCfg[configType].Get(section,item)==value: - #the setting equals a default setting, remove it from user cfg - return idleConf.userCfg[configType].RemoveOption(section,item) - #if we got here set the option - return idleConf.userCfg[configType].SetOption(section,item,value) - - def SaveAllChangedConfigs(self): - "Save configuration changes to the user config file." - idleConf.userCfg['main'].Save() - for configType in self.changedItems.keys(): - cfgTypeHasChanges = False - for section in self.changedItems[configType].keys(): - if section == 'HelpFiles': - #this section gets completely replaced - idleConf.userCfg['main'].remove_section('HelpFiles') - cfgTypeHasChanges = True - for item in self.changedItems[configType][section].keys(): - value = self.changedItems[configType][section][item] - if self.SetUserValue(configType,section,item,value): - cfgTypeHasChanges = True - if cfgTypeHasChanges: - idleConf.userCfg[configType].Save() - self.ResetChangedItems() #clear the changed items dict - - def ActivateConfigChanges(self): - #things that need to be done to make - #applied config changes dynamic: - #update editor/shell font and repaint - #dynamically update indentation setttings - #update theme and repaint - #update keybindings and re-bind - #update user help sources menu - winInstances=self.parent.instanceDict.keys() - for instance in winInstances: - instance.ResetColorizer() - instance.ResetFont() - instance.ResetKeybindings() - instance.reset_help_menu_entries() - - def Cancel(self): - self.destroy() - - def Ok(self): - self.Apply() - self.destroy() - - def Apply(self): - self.SaveAllChangedConfigs() - self.ActivateConfigChanges() - - def Help(self): - pass - -if __name__ == '__main__': - #test the dialog - root=Tk() - Button(root,text='Dialog', - command=lambda:ConfigDialog(root,'Settings')).pack() - root.instanceDict={} - root.mainloop() diff --git a/Tools/idle/configHandler.py b/Tools/idle/configHandler.py deleted file mode 100644 index fd9cbc4..0000000 --- a/Tools/idle/configHandler.py +++ /dev/null @@ -1,655 +0,0 @@ -"""Provides access to stored IDLE configuration information. - -Refer to the comments at the beginning of config-main.def for a description of -the available configuration files and the design implemented to update user -configuration information. In particular, user configuration choices which -duplicate the defaults will be removed from the user's configuration files, -and if a file becomes empty, it will be deleted. - -The contents of the user files may be altered using the Options/Configure IDLE -menu to access the configuration GUI (configDialog.py), or manually. - -Throughout this module there is an emphasis on returning useable defaults -when a problem occurs in returning a requested configuration value back to -idle. This is to allow IDLE to continue to function in spite of errors in -the retrieval of config information. When a default is returned instead of -a requested config value, a message is printed to stderr to aid in -configuration problem notification and resolution. - -""" -import os -import sys -import string -from ConfigParser import ConfigParser, NoOptionError, NoSectionError - -class InvalidConfigType(Exception): pass -class InvalidConfigSet(Exception): pass -class InvalidFgBg(Exception): pass -class InvalidTheme(Exception): pass - -class IdleConfParser(ConfigParser): - """ - A ConfigParser specialised for idle configuration file handling - """ - def __init__(self, cfgFile, cfgDefaults=None): - """ - cfgFile - string, fully specified configuration file name - """ - self.file=cfgFile - ConfigParser.__init__(self,defaults=cfgDefaults) - - def Get(self, section, option, type=None, default=None): - """ - Get an option value for given section/option or return default. - If type is specified, return as type. - """ - if type=='bool': - getVal=self.getboolean - elif type=='int': - getVal=self.getint - else: - getVal=self.get - if self.has_option(section,option): - #return getVal(section, option, raw, vars, default) - return getVal(section, option) - else: - return default - - def GetOptionList(self,section): - """ - Get an option list for given section - """ - if self.has_section(section): - return self.options(section) - else: #return a default value - return [] - - def Load(self): - """ - Load the configuration file from disk - """ - self.read(self.file) - -class IdleUserConfParser(IdleConfParser): - """ - IdleConfigParser specialised for user configuration handling. - """ - - def AddSection(self,section): - """ - if section doesn't exist, add it - """ - if not self.has_section(section): - self.add_section(section) - - def RemoveEmptySections(self): - """ - remove any sections that have no options - """ - for section in self.sections(): - if not self.GetOptionList(section): - self.remove_section(section) - - def IsEmpty(self): - """ - Remove empty sections and then return 1 if parser has no sections - left, else return 0. - """ - self.RemoveEmptySections() - if self.sections(): - return 0 - else: - return 1 - - def RemoveOption(self,section,option): - """ - If section/option exists, remove it. - Returns 1 if option was removed, 0 otherwise. - """ - if self.has_section(section): - return self.remove_option(section,option) - - def SetOption(self,section,option,value): - """ - Sets option to value, adding section if required. - Returns 1 if option was added or changed, otherwise 0. - """ - if self.has_option(section,option): - if self.get(section,option)==value: - return 0 - else: - self.set(section,option,value) - return 1 - else: - if not self.has_section(section): - self.add_section(section) - self.set(section,option,value) - return 1 - - def RemoveFile(self): - """ - Removes the user config file from disk if it exists. - """ - if os.path.exists(self.file): - os.remove(self.file) - - def Save(self): - """Update user configuration file. - - Remove empty sections. If resulting config isn't empty, write the file - to disk. If config is empty, remove the file from disk if it exists. - - """ - if not self.IsEmpty(): - cfgFile=open(self.file,'w') - self.write(cfgFile) - else: - self.RemoveFile() - -class IdleConf: - """ - holds config parsers for all idle config files: - default config files - (idle install dir)/config-main.def - (idle install dir)/config-extensions.def - (idle install dir)/config-highlight.def - (idle install dir)/config-keys.def - user config files - (user home dir)/.idlerc/config-main.cfg - (user home dir)/.idlerc/config-extensions.cfg - (user home dir)/.idlerc/config-highlight.cfg - (user home dir)/.idlerc/config-keys.cfg - """ - def __init__(self): - self.defaultCfg={} - self.userCfg={} - self.cfg={} - self.CreateConfigHandlers() - self.LoadCfgFiles() - #self.LoadCfg() - - def CreateConfigHandlers(self): - """ - set up a dictionary of config parsers for default and user - configurations respectively - """ - #build idle install path - if __name__ != '__main__': # we were imported - idleDir=os.path.dirname(__file__) - else: # we were exec'ed (for testing only) - idleDir=os.path.abspath(sys.path[0]) - userDir=self.GetUserCfgDir() - configTypes=('main','extensions','highlight','keys') - defCfgFiles={} - usrCfgFiles={} - for cfgType in configTypes: #build config file names - defCfgFiles[cfgType]=os.path.join(idleDir,'config-'+cfgType+'.def') - usrCfgFiles[cfgType]=os.path.join(userDir,'config-'+cfgType+'.cfg') - for cfgType in configTypes: #create config parsers - self.defaultCfg[cfgType]=IdleConfParser(defCfgFiles[cfgType]) - self.userCfg[cfgType]=IdleUserConfParser(usrCfgFiles[cfgType]) - - def GetUserCfgDir(self): - """ - Creates (if required) and returns a filesystem directory for storing - user config files. - """ - cfgDir='.idlerc' - userDir=os.path.expanduser('~') - if userDir != '~': #'HOME' exists as a key in os.environ - if not os.path.exists(userDir): - warn=('\n Warning: HOME environment variable points to\n '+ - userDir+'\n but the path does not exist.\n') - sys.stderr.write(warn) - userDir='~' - if userDir=='~': #we still don't have a home directory - #traditionally idle has defaulted to os.getcwd(), is this adeqate? - userDir = os.getcwd() #hack for no real homedir - userDir=os.path.join(userDir,cfgDir) - if not os.path.exists(userDir): - try: #make the config dir if it doesn't exist yet - os.mkdir(userDir) - except IOError: - warn=('\n Warning: unable to create user config directory\n '+ - userDir+'\n') - sys.stderr.write(warn) - return userDir - - def GetOption(self, configType, section, option, default=None, type=None): - """ - Get an option value for given config type and given general - configuration section/option or return a default. If type is specified, - return as type. Firstly the user configuration is checked, with a - fallback to the default configuration, and a final 'catch all' - fallback to a useable passed-in default if the option isn't present in - either the user or the default configuration. - configType must be one of ('main','extensions','highlight','keys') - If a default is returned a warning is printed to stderr. - """ - if self.userCfg[configType].has_option(section,option): - return self.userCfg[configType].Get(section, option, type=type) - elif self.defaultCfg[configType].has_option(section,option): - return self.defaultCfg[configType].Get(section, option, type=type) - else: #returning default, print warning - warning=('\n Warning: configHandler.py - IdleConf.GetOption -\n'+ - ' problem retrieving configration option '+`option`+'\n'+ - ' from section '+`section`+'.\n'+ - ' returning default value: '+`default`+'\n') - sys.stderr.write(warning) - return default - - def GetSectionList(self, configSet, configType): - """ - Get a list of sections from either the user or default config for - the given config type. - configSet must be either 'user' or 'default' - configType must be one of ('main','extensions','highlight','keys') - """ - if not (configType in ('main','extensions','highlight','keys')): - raise InvalidConfigType, 'Invalid configType specified' - if configSet == 'user': - cfgParser=self.userCfg[configType] - elif configSet == 'default': - cfgParser=self.defaultCfg[configType] - else: - raise InvalidConfigSet, 'Invalid configSet specified' - return cfgParser.sections() - - def GetHighlight(self, theme, element, fgBg=None): - """ - return individual highlighting theme elements. - fgBg - string ('fg'or'bg') or None, if None return a dictionary - containing fg and bg colours (appropriate for passing to Tkinter in, - e.g., a tag_config call), otherwise fg or bg colour only as specified. - """ - if self.defaultCfg['highlight'].has_section(theme): - themeDict=self.GetThemeDict('default',theme) - else: - themeDict=self.GetThemeDict('user',theme) - fore=themeDict[element+'-foreground'] - if element=='cursor': #there is no config value for cursor bg - back=themeDict['normal-background'] - else: - back=themeDict[element+'-background'] - highlight={"foreground": fore,"background": back} - if not fgBg: #return dict of both colours - return highlight - else: #return specified colour only - if fgBg == 'fg': - return highlight["foreground"] - if fgBg == 'bg': - return highlight["background"] - else: - raise InvalidFgBg, 'Invalid fgBg specified' - - def GetThemeDict(self,type,themeName): - """ - type - string, 'default' or 'user' theme type - themeName - string, theme name - Returns a dictionary which holds {option:value} for each element - in the specified theme. Values are loaded over a set of ultimate last - fallback defaults to guarantee that all theme elements are present in - a newly created theme. - """ - if type == 'user': - cfgParser=self.userCfg['highlight'] - elif type == 'default': - cfgParser=self.defaultCfg['highlight'] - else: - raise InvalidTheme, 'Invalid theme type specified' - #foreground and background values are provded for each theme element - #(apart from cursor) even though all these values are not yet used - #by idle, to allow for their use in the future. Default values are - #generally black and white. - theme={ 'normal-foreground':'#000000', - 'normal-background':'#ffffff', - 'keyword-foreground':'#000000', - 'keyword-background':'#ffffff', - 'comment-foreground':'#000000', - 'comment-background':'#ffffff', - 'string-foreground':'#000000', - 'string-background':'#ffffff', - 'definition-foreground':'#000000', - 'definition-background':'#ffffff', - 'hilite-foreground':'#000000', - 'hilite-background':'gray', - 'break-foreground':'#ffffff', - 'break-background':'#000000', - 'hit-foreground':'#ffffff', - 'hit-background':'#000000', - 'error-foreground':'#ffffff', - 'error-background':'#000000', - #cursor (only foreground can be set) - 'cursor-foreground':'#000000', - #shell window - 'stdout-foreground':'#000000', - 'stdout-background':'#ffffff', - 'stderr-foreground':'#000000', - 'stderr-background':'#ffffff', - 'console-foreground':'#000000', - 'console-background':'#ffffff' } - for element in theme.keys(): - if not cfgParser.has_option(themeName,element): - #we are going to return a default, print warning - warning=('\n Warning: configHandler.py - IdleConf.GetThemeDict'+ - ' -\n problem retrieving theme element '+`element`+ - '\n from theme '+`themeName`+'.\n'+ - ' returning default value: '+`theme[element]`+'\n') - sys.stderr.write(warning) - colour=cfgParser.Get(themeName,element,default=theme[element]) - theme[element]=colour - return theme - - def CurrentTheme(self): - """ - Returns the name of the currently active theme - """ - return self.GetOption('main','Theme','name',default='') - - def CurrentKeys(self): - """ - Returns the name of the currently active key set - """ - return self.GetOption('main','Keys','name',default='') - - def GetExtensions(self, activeOnly=1): - """ - Gets a list of all idle extensions declared in the config files. - activeOnly - boolean, if true only return active (enabled) extensions - """ - extns=self.RemoveKeyBindNames( - self.GetSectionList('default','extensions')) - userExtns=self.RemoveKeyBindNames( - self.GetSectionList('user','extensions')) - for extn in userExtns: - if extn not in extns: #user has added own extension - extns.append(extn) - if activeOnly: - activeExtns=[] - for extn in extns: - if self.GetOption('extensions',extn,'enable',default=1, - type='bool'): - #the extension is enabled - activeExtns.append(extn) - return activeExtns - else: - return extns - - def RemoveKeyBindNames(self,extnNameList): - #get rid of keybinding section names - names=extnNameList - kbNameIndicies=[] - for name in names: - if name.endswith('_bindings') or name.endswith('_cfgBindings'): - kbNameIndicies.append(names.index(name)) - kbNameIndicies.sort() - kbNameIndicies.reverse() - for index in kbNameIndicies: #delete each keybinding section name - del(names[index]) - return names - - def GetExtnNameForEvent(self,virtualEvent): - """ - Returns the name of the extension that virtualEvent is bound in, or - None if not bound in any extension. - virtualEvent - string, name of the virtual event to test for, without - the enclosing '<< >>' - """ - extName=None - vEvent='<<'+virtualEvent+'>>' - for extn in self.GetExtensions(activeOnly=0): - for event in self.GetExtensionKeys(extn).keys(): - if event == vEvent: - extName=extn - return extName - - def GetExtensionKeys(self,extensionName): - """ - returns a dictionary of the configurable keybindings for a particular - extension,as they exist in the dictionary returned by GetCurrentKeySet; - that is, where previously used bindings are disabled. - """ - keysName=extensionName+'_cfgBindings' - activeKeys=self.GetCurrentKeySet() - extKeys={} - if self.defaultCfg['extensions'].has_section(keysName): - eventNames=self.defaultCfg['extensions'].GetOptionList(keysName) - for eventName in eventNames: - event='<<'+eventName+'>>' - binding=activeKeys[event] - extKeys[event]=binding - return extKeys - - def __GetRawExtensionKeys(self,extensionName): - """ - returns a dictionary of the configurable keybindings for a particular - extension, as defined in the configuration files, or an empty dictionary - if no bindings are found - """ - keysName=extensionName+'_cfgBindings' - extKeys={} - if self.defaultCfg['extensions'].has_section(keysName): - eventNames=self.defaultCfg['extensions'].GetOptionList(keysName) - for eventName in eventNames: - binding=self.GetOption('extensions',keysName, - eventName,default='').split() - event='<<'+eventName+'>>' - extKeys[event]=binding - return extKeys - - def GetExtensionBindings(self,extensionName): - """ - Returns a dictionary of all the event bindings for a particular - extension. The configurable keybindings are returned as they exist in - the dictionary returned by GetCurrentKeySet; that is, where re-used - keybindings are disabled. - """ - bindsName=extensionName+'_bindings' - extBinds=self.GetExtensionKeys(extensionName) - #add the non-configurable bindings - if self.defaultCfg['extensions'].has_section(bindsName): - eventNames=self.defaultCfg['extensions'].GetOptionList(bindsName) - for eventName in eventNames: - binding=self.GetOption('extensions',bindsName, - eventName,default='').split() - event='<<'+eventName+'>>' - extBinds[event]=binding - - return extBinds - - def GetKeyBinding(self, keySetName, eventStr): - """ - returns the keybinding for a specific event. - keySetName - string, name of key binding set - eventStr - string, the virtual event we want the binding for, - represented as a string, eg. '<<event>>' - """ - eventName=eventStr[2:-2] #trim off the angle brackets - binding=self.GetOption('keys',keySetName,eventName,default='').split() - return binding - - def GetCurrentKeySet(self): - return self.GetKeySet(self.CurrentKeys()) - - def GetKeySet(self,keySetName): - """ - Returns a dictionary of: all requested core keybindings, plus the - keybindings for all currently active extensions. If a binding defined - in an extension is already in use, that binding is disabled. - """ - keySet=self.GetCoreKeys(keySetName) - activeExtns=self.GetExtensions(activeOnly=1) - for extn in activeExtns: - extKeys=self.__GetRawExtensionKeys(extn) - if extKeys: #the extension defines keybindings - for event in extKeys.keys(): - if extKeys[event] in keySet.values(): - #the binding is already in use - extKeys[event]='' #disable this binding - keySet[event]=extKeys[event] #add binding - return keySet - - def IsCoreBinding(self,virtualEvent): - """ - returns true if the virtual event is bound in the core idle keybindings. - virtualEvent - string, name of the virtual event to test for, without - the enclosing '<< >>' - """ - return ('<<'+virtualEvent+'>>') in self.GetCoreKeys().keys() - - def GetCoreKeys(self, keySetName=None): - """ - returns the requested set of core keybindings, with fallbacks if - required. - Keybindings loaded from the config file(s) are loaded _over_ these - defaults, so if there is a problem getting any core binding there will - be an 'ultimate last resort fallback' to the CUA-ish bindings - defined here. - """ - keyBindings={ - '<<copy>>': ['<Control-c>', '<Control-C>'], - '<<cut>>': ['<Control-x>', '<Control-X>'], - '<<paste>>': ['<Control-v>', '<Control-V>'], - '<<beginning-of-line>>': ['<Control-a>', '<Home>'], - '<<center-insert>>': ['<Control-l>'], - '<<close-all-windows>>': ['<Control-q>'], - '<<close-window>>': ['<Alt-F4>'], - '<<do-nothing>>': ['<Control-x>'], - '<<end-of-file>>': ['<Control-d>'], - '<<python-docs>>': ['<F1>'], - '<<python-context-help>>': ['<Shift-F1>'], - '<<history-next>>': ['<Alt-n>'], - '<<history-previous>>': ['<Alt-p>'], - '<<interrupt-execution>>': ['<Control-c>'], - '<<view-restart>>': ['<F6>'], - '<<restart-shell>>': ['<Control-F6>'], - '<<open-class-browser>>': ['<Alt-c>'], - '<<open-module>>': ['<Alt-m>'], - '<<open-new-window>>': ['<Control-n>'], - '<<open-window-from-file>>': ['<Control-o>'], - '<<plain-newline-and-indent>>': ['<Control-j>'], - '<<print-window>>': ['<Control-p>'], - '<<redo>>': ['<Control-y>'], - '<<remove-selection>>': ['<Escape>'], - '<<save-copy-of-window-as-file>>': ['<Alt-Shift-s>'], - '<<save-window-as-file>>': ['<Alt-s>'], - '<<save-window>>': ['<Control-s>'], - '<<select-all>>': ['<Alt-a>'], - '<<toggle-auto-coloring>>': ['<Control-slash>'], - '<<undo>>': ['<Control-z>'], - '<<find-again>>': ['<Control-g>', '<F3>'], - '<<find-in-files>>': ['<Alt-F3>'], - '<<find-selection>>': ['<Control-F3>'], - '<<find>>': ['<Control-f>'], - '<<replace>>': ['<Control-h>'], - '<<goto-line>>': ['<Alt-g>'], - '<<smart-backspace>>': ['<Key-BackSpace>'], - '<<newline-and-indent>>': ['<Key-Return> <Key-KP_Enter>'], - '<<smart-indent>>': ['<Key-Tab>'], - '<<indent-region>>': ['<Control-Key-bracketright>'], - '<<dedent-region>>': ['<Control-Key-bracketleft>'], - '<<comment-region>>': ['<Alt-Key-3>'], - '<<uncomment-region>>': ['<Alt-Key-4>'], - '<<tabify-region>>': ['<Alt-Key-5>'], - '<<untabify-region>>': ['<Alt-Key-6>'], - '<<toggle-tabs>>': ['<Alt-Key-t>'], - '<<change-indentwidth>>': ['<Alt-Key-u>'] - } - if keySetName: - for event in keyBindings.keys(): - binding=self.GetKeyBinding(keySetName,event) - if binding: - keyBindings[event]=binding - else: #we are going to return a default, print warning - warning=('\n Warning: configHandler.py - IdleConf.GetCoreKeys'+ - ' -\n problem retrieving key binding for event '+ - `event`+'\n from key set '+`keySetName`+'.\n'+ - ' returning default value: '+`keyBindings[event]`+'\n') - sys.stderr.write(warning) - return keyBindings - - def GetExtraHelpSourceList(self,configSet): - """Fetch list of extra help sources from a given configSet. - - Valid configSets are 'user' or 'default'. Return a list of tuples of - the form (menu_item , path_to_help_file , option), or return the empty - list. 'option' is the sequence number of the help resource. 'option' - values determine the position of the menu items on the Help menu, - therefore the returned list must be sorted by 'option'. - - """ - helpSources=[] - if configSet=='user': - cfgParser=self.userCfg['main'] - elif configSet=='default': - cfgParser=self.defaultCfg['main'] - else: - raise InvalidConfigSet, 'Invalid configSet specified' - options=cfgParser.GetOptionList('HelpFiles') - for option in options: - value=cfgParser.Get('HelpFiles',option,default=';') - if value.find(';')==-1: #malformed config entry with no ';' - menuItem='' #make these empty - helpPath='' #so value won't be added to list - else: #config entry contains ';' as expected - value=string.split(value,';') - menuItem=value[0].strip() - helpPath=value[1].strip() - if menuItem and helpPath: #neither are empty strings - helpSources.append( (menuItem,helpPath,option) ) - helpSources.sort(self.__helpsort) - return helpSources - - def __helpsort(self, h1, h2): - if int(h1[2]) < int(h2[2]): - return -1 - elif int(h1[2]) > int(h2[2]): - return 1 - else: - return 0 - - def GetAllExtraHelpSourcesList(self): - """ - Returns a list of tuples containing the details of all additional help - sources configured, or an empty list if there are none. Tuples are of - the format returned by GetExtraHelpSourceList. - """ - allHelpSources=( self.GetExtraHelpSourceList('default')+ - self.GetExtraHelpSourceList('user') ) - return allHelpSources - - def LoadCfgFiles(self): - """ - load all configuration files. - """ - for key in self.defaultCfg.keys(): - self.defaultCfg[key].Load() - self.userCfg[key].Load() #same keys - - def SaveUserCfgFiles(self): - """ - write all loaded user configuration files back to disk - """ - for key in self.userCfg.keys(): - self.userCfg[key].Save() - -idleConf=IdleConf() - -### module test -if __name__ == '__main__': - def dumpCfg(cfg): - print '\n',cfg,'\n' - for key in cfg.keys(): - sections=cfg[key].sections() - print key - print sections - for section in sections: - options=cfg[key].options(section) - print section - print options - for option in options: - print option, '=', cfg[key].Get(section,option) - dumpCfg(idleConf.defaultCfg) - dumpCfg(idleConf.userCfg) - print idleConf.userCfg['main'].Get('Theme','name') - #print idleConf.userCfg['highlight'].GetDefHighlight('Foo','normal') diff --git a/Tools/idle/configHelpSourceEdit.py b/Tools/idle/configHelpSourceEdit.py deleted file mode 100644 index b781884..0000000 --- a/Tools/idle/configHelpSourceEdit.py +++ /dev/null @@ -1,157 +0,0 @@ -"Dialog to specify or edit the parameters for a user configured help source." - -import os - -from Tkinter import * -import tkMessageBox -import tkFileDialog - -class GetHelpSourceDialog(Toplevel): - def __init__(self, parent, title, menuItem='', filePath=''): - """Get menu entry and url/ local file location for Additional Help - - User selects a name for the Help resource and provides a web url - or a local file as its source. The user can enter a url or browse - for the file. - - """ - Toplevel.__init__(self, parent) - self.configure(borderwidth=5) - self.resizable(height=FALSE, width=FALSE) - self.title(title) - self.transient(parent) - self.grab_set() - self.protocol("WM_DELETE_WINDOW", self.Cancel) - self.parent = parent - self.result = None - self.CreateWidgets() - self.menu.set(menuItem) - self.path.set(filePath) - self.withdraw() #hide while setting geometry - #needs to be done here so that the winfo_reqwidth is valid - self.update_idletasks() - #centre dialog over parent: - self.geometry("+%d+%d" % - ((parent.winfo_rootx() + ((parent.winfo_width()/2) - -(self.winfo_reqwidth()/2)), - parent.winfo_rooty() + ((parent.winfo_height()/2) - -(self.winfo_reqheight()/2))))) - self.deiconify() #geometry set, unhide - self.bind('<Return>', self.Ok) - self.wait_window() - - def CreateWidgets(self): - self.menu = StringVar(self) - self.path = StringVar(self) - self.fontSize = StringVar(self) - self.frameMain = Frame(self, borderwidth=2, relief=GROOVE) - self.frameMain.pack(side=TOP, expand=TRUE, fill=BOTH) - labelMenu = Label(self.frameMain, anchor=W, justify=LEFT, - text='Menu Item:') - self.entryMenu = Entry(self.frameMain, textvariable=self.menu, - width=30) - self.entryMenu.focus_set() - labelPath = Label(self.frameMain, anchor=W, justify=LEFT, - text='Help File Path: Enter URL or browse for file') - self.entryPath = Entry(self.frameMain, textvariable=self.path, - width=40) - self.entryMenu.focus_set() - labelMenu.pack(anchor=W, padx=5, pady=3) - self.entryMenu.pack(anchor=W, padx=5, pady=3) - labelPath.pack(anchor=W, padx=5, pady=3) - self.entryPath.pack(anchor=W, padx=5, pady=3) - browseButton = Button(self.frameMain, text='Browse', width=8, - command=self.browseFile) - browseButton.pack(pady=3) - frameButtons = Frame(self) - frameButtons.pack(side=BOTTOM, fill=X) - self.buttonOk = Button(frameButtons, text='OK', - width=8, default=ACTIVE, command=self.Ok) - self.buttonOk.grid(row=0, column=0, padx=5,pady=5) - self.buttonCancel = Button(frameButtons, text='Cancel', - width=8, command=self.Cancel) - self.buttonCancel.grid(row=0, column=1, padx=5, pady=5) - - def browseFile(self): - filetypes = [ - ("HTML Files", "*.htm *.html", "TEXT"), - ("PDF Files", "*.pdf", "TEXT"), - ("Windows Help Files", "*.chm"), - ("Text Files", "*.txt", "TEXT"), - ("All Files", "*")] - path = self.path.get() - if path: - dir, base = os.path.split(path) - else: - base = None - if sys.platform.count('win') or sys.platform.count('nt'): - dir = os.path.join(os.path.dirname(sys.executable), 'Doc') - if not os.path.isdir(dir): - dir = os.getcwd() - else: - dir = os.getcwd() - opendialog = tkFileDialog.Open(parent=self, filetypes=filetypes) - file = opendialog.show(initialdir=dir, initialfile=base) - if file: - self.path.set(file) - - def MenuOk(self): - "Simple validity check for a sensible menu item name" - menuOk = True - menu = self.menu.get() - menu.strip() - if not menu: - tkMessageBox.showerror(title='Menu Item Error', - message='No menu item specified', - parent=self) - self.entryMenu.focus_set() - menuOk = False - elif len(menu) > 30: - tkMessageBox.showerror(title='Menu Item Error', - message='Menu item too long:' - '\nLimit 30 characters.', - parent=self) - self.entryMenu.focus_set() - menuOk = False - return menuOk - - def PathOk(self): - "Simple validity check for menu file path" - pathOk = True - path = self.path.get() - path.strip() - if not path: #no path specified - tkMessageBox.showerror(title='File Path Error', - message='No help file path specified.', - parent=self) - self.entryPath.focus_set() - pathOk = False - elif path.startswith('www.') or path.startswith('http'): - pathOk = True - elif not os.path.exists(path): - tkMessageBox.showerror(title='File Path Error', - message='Help file path does not exist.', - parent=self) - self.entryPath.focus_set() - pathOk = False - return pathOk - - def Ok(self, event=None): - if self.MenuOk() and self.PathOk(): - self.result = (self.menu.get().strip(), - self.path.get().strip()) - self.destroy() - - def Cancel(self, event=None): - self.result = None - self.destroy() - -if __name__ == '__main__': - #test the dialog - root = Tk() - def run(): - keySeq = '' - dlg = GetHelpSourceDialog(root, 'Get Help Source') - print dlg.result - Button(root,text='Dialog', command=run).pack() - root.mainloop() diff --git a/Tools/idle/configSectionNameDialog.py b/Tools/idle/configSectionNameDialog.py deleted file mode 100644 index 4f1b002..0000000 --- a/Tools/idle/configSectionNameDialog.py +++ /dev/null @@ -1,97 +0,0 @@ -""" -Dialog that allows user to specify a new config file section name. -Used to get new highlight theme and keybinding set names. -""" -from Tkinter import * -import tkMessageBox - -class GetCfgSectionNameDialog(Toplevel): - def __init__(self,parent,title,message,usedNames): - """ - message - string, informational message to display - usedNames - list, list of names already in use for validity check - """ - Toplevel.__init__(self, parent) - self.configure(borderwidth=5) - self.resizable(height=FALSE,width=FALSE) - self.title(title) - self.transient(parent) - self.grab_set() - self.protocol("WM_DELETE_WINDOW", self.Cancel) - self.parent = parent - self.message=message - self.usedNames=usedNames - self.result='' - self.CreateWidgets() - self.withdraw() #hide while setting geometry - self.update_idletasks() - #needs to be done here so that the winfo_reqwidth is valid - self.messageInfo.config(width=self.frameMain.winfo_reqwidth()) - self.geometry("+%d+%d" % - ((parent.winfo_rootx()+((parent.winfo_width()/2) - -(self.winfo_reqwidth()/2)), - parent.winfo_rooty()+((parent.winfo_height()/2) - -(self.winfo_reqheight()/2)) )) ) #centre dialog over parent - self.deiconify() #geometry set, unhide - self.wait_window() - - def CreateWidgets(self): - self.name=StringVar(self) - self.fontSize=StringVar(self) - self.frameMain = Frame(self,borderwidth=2,relief=SUNKEN) - self.frameMain.pack(side=TOP,expand=TRUE,fill=BOTH) - self.messageInfo=Message(self.frameMain,anchor=W,justify=LEFT,padx=5,pady=5, - text=self.message)#,aspect=200) - entryName=Entry(self.frameMain,textvariable=self.name,width=30) - entryName.focus_set() - self.messageInfo.pack(padx=5,pady=5)#,expand=TRUE,fill=BOTH) - entryName.pack(padx=5,pady=5) - frameButtons=Frame(self) - frameButtons.pack(side=BOTTOM,fill=X) - self.buttonOk = Button(frameButtons,text='Ok', - width=8,command=self.Ok) - self.buttonOk.grid(row=0,column=0,padx=5,pady=5) - self.buttonCancel = Button(frameButtons,text='Cancel', - width=8,command=self.Cancel) - self.buttonCancel.grid(row=0,column=1,padx=5,pady=5) - - def NameOk(self): - #simple validity check for a sensible - #ConfigParser file section name - nameOk=1 - name=self.name.get() - name.strip() - if not name: #no name specified - tkMessageBox.showerror(title='Name Error', - message='No name specified.', parent=self) - nameOk=0 - elif len(name)>30: #name too long - tkMessageBox.showerror(title='Name Error', - message='Name too long. It should be no more than '+ - '30 characters.', parent=self) - nameOk=0 - elif name in self.usedNames: - tkMessageBox.showerror(title='Name Error', - message='This name is already in use.', parent=self) - nameOk=0 - return nameOk - - def Ok(self, event=None): - if self.NameOk(): - self.result=self.name.get().strip() - self.destroy() - - def Cancel(self, event=None): - self.result='' - self.destroy() - -if __name__ == '__main__': - #test the dialog - root=Tk() - def run(): - keySeq='' - dlg=GetCfgSectionNameDialog(root,'Get Name', - 'The information here should need to be word wrapped. Test.') - print dlg.result - Button(root,text='Dialog',command=run).pack() - root.mainloop() diff --git a/Tools/idle/dynOptionMenuWidget.py b/Tools/idle/dynOptionMenuWidget.py deleted file mode 100644 index e81f7ba..0000000 --- a/Tools/idle/dynOptionMenuWidget.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -OptionMenu widget modified to allow dynamic menu reconfiguration -and setting of highlightthickness -""" -from Tkinter import OptionMenu -from Tkinter import _setit -import copy - -class DynOptionMenu(OptionMenu): - """ - unlike OptionMenu, our kwargs can include highlightthickness - """ - def __init__(self, master, variable, value, *values, **kwargs): - #get a copy of kwargs before OptionMenu.__init__ munges them - kwargsCopy=copy.copy(kwargs) - if 'highlightthickness' in kwargs.keys(): - del(kwargs['highlightthickness']) - OptionMenu.__init__(self, master, variable, value, *values, **kwargs) - self.config(highlightthickness=kwargsCopy.get('highlightthickness')) - #self.menu=self['menu'] - self.variable=variable - self.command=kwargs.get('command') - - def SetMenu(self,valueList,value=None): - """ - clear and reload the menu with a new set of options. - valueList - list of new options - value - initial value to set the optionmenu's menubutton to - """ - self['menu'].delete(0,'end') - for item in valueList: - self['menu'].add_command(label=item, - command=_setit(self.variable,item,self.command)) - if value: - self.variable.set(value) diff --git a/Tools/idle/interruptmodule.c b/Tools/idle/interruptmodule.c deleted file mode 100644 index 8e18d5a..0000000 --- a/Tools/idle/interruptmodule.c +++ /dev/null @@ -1,49 +0,0 @@ -/*********************************************************************** - * interruptmodule.c - * - * Python extension implementing the interrupt module. - * - **********************************************************************/ - -#include "Python.h" - -#ifndef PyDoc_STR -#define PyDoc_VAR(name) static char name[] -#define PyDoc_STR(str) str -#define PyDoc_STRVAR(name,str) PyDoc_VAR(name) = PyDoc_STR(str) -#endif - -/* module documentation */ - -PyDoc_STRVAR(module_doc, -"Provide a way to interrupt the main thread from a subthread.\n\n\ -In threaded Python code the KeyboardInterrupt is always directed to\n\ -the thread which raised it. This extension provides a method,\n\ -interrupt_main, which a subthread can use to raise a KeyboardInterrupt\n\ -in the main thread."); - -/* module functions */ - -static PyObject * -setinterrupt(PyObject * self, PyObject * args) -{ - PyErr_SetInterrupt(); - Py_INCREF(Py_None); - return Py_None; -} - -/* registration table */ - -static struct PyMethodDef methods[] = { - {"interrupt_main", setinterrupt, METH_VARARGS, - PyDoc_STR("Interrupt the main thread")}, - {NULL, NULL} -}; - -/* module initialization */ - -void -initinterrupt(void) -{ - (void) Py_InitModule3("interrupt", methods, module_doc); -} diff --git a/Tools/idle/keybindingDialog.py b/Tools/idle/keybindingDialog.py deleted file mode 100644 index df024e7..0000000 --- a/Tools/idle/keybindingDialog.py +++ /dev/null @@ -1,262 +0,0 @@ -""" -dialog for building tkinter accelerator key bindings -""" -from Tkinter import * -import tkMessageBox -import string, os - -class GetKeysDialog(Toplevel): - def __init__(self,parent,title,action,currentKeySequences): - """ - action - string, the name of the virtual event these keys will be - mapped to - currentKeys - list, a list of all key sequence lists currently mapped - to virtual events, for overlap checking - """ - Toplevel.__init__(self, parent) - self.configure(borderwidth=5) - self.resizable(height=FALSE,width=FALSE) - self.title(title) - self.transient(parent) - self.grab_set() - self.protocol("WM_DELETE_WINDOW", self.Cancel) - self.parent = parent - self.action=action - self.currentKeySequences=currentKeySequences - self.result='' - self.keyString=StringVar(self) - self.keyString.set('') - self.SetModifiersForPlatform() - self.modifier_vars = [] - for modifier in self.modifiers: - variable = StringVar(self) - variable.set('') - self.modifier_vars.append(variable) - self.CreateWidgets() - self.LoadFinalKeyList() - self.withdraw() #hide while setting geometry - self.update_idletasks() - self.geometry("+%d+%d" % - ((parent.winfo_rootx()+((parent.winfo_width()/2) - -(self.winfo_reqwidth()/2)), - parent.winfo_rooty()+((parent.winfo_height()/2) - -(self.winfo_reqheight()/2)) )) ) #centre dialog over parent - self.deiconify() #geometry set, unhide - self.wait_window() - - def CreateWidgets(self): - frameMain = Frame(self,borderwidth=2,relief=SUNKEN) - frameMain.pack(side=TOP,expand=TRUE,fill=BOTH) - frameButtons=Frame(self) - frameButtons.pack(side=BOTTOM,fill=X) - self.buttonOk = Button(frameButtons,text='Ok', - width=8,command=self.Ok) - self.buttonOk.grid(row=0,column=0,padx=5,pady=5) - self.buttonCancel = Button(frameButtons,text='Cancel', - width=8,command=self.Cancel) - self.buttonCancel.grid(row=0,column=1,padx=5,pady=5) - self.frameKeySeqBasic = Frame(frameMain) - self.frameKeySeqAdvanced = Frame(frameMain) - self.frameControlsBasic = Frame(frameMain) - self.frameHelpAdvanced = Frame(frameMain) - self.frameKeySeqAdvanced.grid(row=0,column=0,sticky=NSEW,padx=5,pady=5) - self.frameKeySeqBasic.grid(row=0,column=0,sticky=NSEW,padx=5,pady=5) - self.frameKeySeqBasic.lift() - self.frameHelpAdvanced.grid(row=1,column=0,sticky=NSEW,padx=5) - self.frameControlsBasic.grid(row=1,column=0,sticky=NSEW,padx=5) - self.frameControlsBasic.lift() - self.buttonLevel = Button(frameMain,command=self.ToggleLevel, - text='Advanced Key Binding Entry >>') - self.buttonLevel.grid(row=2,column=0,stick=EW,padx=5,pady=5) - labelTitleBasic = Label(self.frameKeySeqBasic, - text="New keys for '"+self.action+"' :") - labelTitleBasic.pack(anchor=W) - labelKeysBasic = Label(self.frameKeySeqBasic,justify=LEFT, - textvariable=self.keyString,relief=GROOVE,borderwidth=2) - labelKeysBasic.pack(ipadx=5,ipady=5,fill=X) - self.modifier_checkbuttons = {} - column = 0 - for modifier, variable in zip(self.modifiers, self.modifier_vars): - label = self.modifier_label.get(modifier, modifier) - check=Checkbutton(self.frameControlsBasic, - command=self.BuildKeyString, - text=label,variable=variable,onvalue=modifier,offvalue='') - check.grid(row=0,column=column,padx=2,sticky=W) - self.modifier_checkbuttons[modifier] = check - column += 1 - labelFnAdvice=Label(self.frameControlsBasic,justify=LEFT, - text="Select the desired modifier\n"+ - "keys above, and final key\n"+ - "from the list on the right.") - labelFnAdvice.grid(row=1,column=0,columnspan=4,padx=2,sticky=W) - self.listKeysFinal=Listbox(self.frameControlsBasic,width=15,height=10, - selectmode=SINGLE) - self.listKeysFinal.bind('<ButtonRelease-1>',self.FinalKeySelected) - self.listKeysFinal.grid(row=0,column=4,rowspan=4,sticky=NS) - scrollKeysFinal=Scrollbar(self.frameControlsBasic,orient=VERTICAL, - command=self.listKeysFinal.yview) - self.listKeysFinal.config(yscrollcommand=scrollKeysFinal.set) - scrollKeysFinal.grid(row=0,column=5,rowspan=4,sticky=NS) - self.buttonClear=Button(self.frameControlsBasic, - text='Clear Keys',command=self.ClearKeySeq) - self.buttonClear.grid(row=2,column=0,columnspan=4) - labelTitleAdvanced = Label(self.frameKeySeqAdvanced,justify=LEFT, - text="Enter new binding(s) for '"+self.action+"' :\n"+ - "(will not be checked for validity)") - labelTitleAdvanced.pack(anchor=W) - self.entryKeysAdvanced=Entry(self.frameKeySeqAdvanced, - textvariable=self.keyString) - self.entryKeysAdvanced.pack(fill=X) - labelHelpAdvanced=Label(self.frameHelpAdvanced,justify=LEFT, - text="Key bindings are specified using tkinter key id's as\n"+ - "in these samples: <Control-f>, <Shift-F2>, <F12>,\n" - "<Control-space>, <Meta-less>, <Control-Alt-Shift-x>.\n\n"+ - "'Emacs style' multi-keystroke bindings are specified as\n"+ - "follows: <Control-x><Control-y> or <Meta-f><Meta-g>.\n\n"+ - "Multiple separate bindings for one action should be\n"+ - "separated by a space, eg., <Alt-v> <Meta-v>." ) - labelHelpAdvanced.grid(row=0,column=0,sticky=NSEW) - - def SetModifiersForPlatform(self): - """Determine list of names of key modifiers for this platform. - - The names are used to build Tk bindings -- it doesn't matter if the - keyboard has these keys, it matters if Tk understands them. The - order is also important: key binding equality depends on it, so - config-keys.def must use the same ordering. - """ - import sys - if sys.platform == 'darwin' and sys.executable.count('.app'): - self.modifiers = ['Shift', 'Control', 'Option', 'Command'] - else: - self.modifiers = ['Control', 'Alt', 'Shift'] - self.modifier_label = {'Control': 'Ctrl'} - - def ToggleLevel(self): - if self.buttonLevel.cget('text')[:8]=='Advanced': - self.ClearKeySeq() - self.buttonLevel.config(text='<< Basic Key Binding Entry') - self.frameKeySeqAdvanced.lift() - self.frameHelpAdvanced.lift() - self.entryKeysAdvanced.focus_set() - else: - self.ClearKeySeq() - self.buttonLevel.config(text='Advanced Key Binding Entry >>') - self.frameKeySeqBasic.lift() - self.frameControlsBasic.lift() - - def FinalKeySelected(self,event): - self.BuildKeyString() - - def BuildKeyString(self): - keyList=[] - modifiers=self.GetModifiers() - finalKey=self.listKeysFinal.get(ANCHOR) - if modifiers: modifiers[0]='<'+modifiers[0] - keyList=keyList+modifiers - if finalKey: - if (not modifiers) and (finalKey not - in self.alphanumKeys+self.punctuationKeys): - finalKey='<'+self.TranslateKey(finalKey) - else: - finalKey=self.TranslateKey(finalKey) - keyList.append(finalKey+'>') - keyStr=string.join(keyList,'-') - self.keyString.set(keyStr) - - def GetModifiers(self): - modList = [variable.get() for variable in self.modifier_vars] - return filter(None, modList) - - def ClearKeySeq(self): - self.listKeysFinal.select_clear(0,END) - self.listKeysFinal.yview(MOVETO, '0.0') - for variable in self.modifier_vars: - variable.set('') - self.keyString.set('') - - def LoadFinalKeyList(self): - #these tuples are also available for use in validity checks - self.functionKeys=('F1','F2','F2','F4','F5','F6','F7','F8','F9', - 'F10','F11','F12') - self.alphanumKeys=tuple(string.ascii_lowercase+string.digits) - self.punctuationKeys=tuple('~!@#%^&*()_-+={}[]|;:,.<>/?') - self.whitespaceKeys=('Tab','Space','Return') - self.editKeys=('BackSpace','Delete','Insert') - self.moveKeys=('Home','End','Page Up','Page Down','Left Arrow', - 'Right Arrow','Up Arrow','Down Arrow') - #make a tuple of most of the useful common 'final' keys - keys=(self.alphanumKeys+self.punctuationKeys+self.functionKeys+ - self.whitespaceKeys+self.editKeys+self.moveKeys) - apply(self.listKeysFinal.insert, - (END,)+keys) - - def TranslateKey(self,key): - #translate from key list value to tkinter key-id - translateDict={'~':'asciitilde','!':'exclam','@':'at','#':'numbersign', - '%':'percent','^':'asciicircum','&':'ampersand','*':'asterisk', - '(':'parenleft',')':'parenright','_':'underscore','-':'minus', - '+':'plus','=':'equal','{':'braceleft','}':'braceright', - '[':'bracketleft',']':'bracketright','|':'bar',';':'semicolon', - ':':'colon',',':'comma','.':'period','<':'less','>':'greater', - '/':'slash','?':'question','Page Up':'Prior','Page Down':'Next', - 'Left Arrow':'Left','Right Arrow':'Right','Up Arrow':'Up', - 'Down Arrow': 'Down'} - if key in translateDict.keys(): - key=translateDict[key] - key='Key-'+key - return key - - def Ok(self, event=None): - if self.KeysOk(): - self.result=self.keyString.get() - self.destroy() - - def Cancel(self, event=None): - self.result='' - self.destroy() - - def KeysOk(self): - #simple validity check - keysOk=1 - keys=self.keyString.get() - keys.strip() - finalKey=self.listKeysFinal.get(ANCHOR) - modifiers=self.GetModifiers() - keySequence=keys.split()#make into a key sequence list for overlap check - if not keys: #no keys specified - tkMessageBox.showerror(title='Key Sequence Error', - message='No keys specified.') - keysOk=0 - elif not keys.endswith('>'): #no final key specified - tkMessageBox.showerror(title='Key Sequence Error', - message='No final key specified.') - keysOk=0 - elif (not modifiers) and (finalKey in - self.alphanumKeys+self.punctuationKeys): - #modifier required - tkMessageBox.showerror(title='Key Sequence Error', - message='No modifier key(s) specified.') - keysOk=0 - elif (modifiers==['Shift']) and (finalKey not - in self.functionKeys+('Tab',)): - #shift alone is only a useful modifier with a function key - tkMessageBox.showerror(title='Key Sequence Error', - message='Shift alone is not a useful modifier '+ - 'when used with this final key key.') - keysOk=0 - elif keySequence in self.currentKeySequences: #keys combo already in use - tkMessageBox.showerror(title='Key Sequence Error', - message='This key combination is already in use.') - keysOk=0 - return keysOk - -if __name__ == '__main__': - #test the dialog - root=Tk() - def run(): - keySeq='' - dlg=GetKeysDialog(root,'Get Keys','find-again',[]) - print dlg.result - Button(root,text='Dialog',command=run).pack() - root.mainloop() diff --git a/Tools/idle/macosx_main.py b/Tools/idle/macosx_main.py deleted file mode 100644 index bc91a0b..0000000 --- a/Tools/idle/macosx_main.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env pythonw -# IDLE.app -# -# Installation: -# see the install_IDLE target in python/dist/src/Mac/OSX/Makefile -# -# Usage: -# -# 1. Double clicking IDLE icon will open IDLE. -# 2. Dropping file on IDLE icon will open that file in IDLE. -# 3. Launch from command line with files with this command-line: -# -# /Applications/Python/IDLE.app/Contents/MacOS/python file1 file2 file3 -# -# - -# Add IDLE.app/Contents/Resources/idlelib to path. -# __file__ refers to this file when it is used as a module, sys.argv[0] -# refers to this file when it is used as a script (pythonw macosx_main.py) -import sys - -from os.path import split, join, isdir -try: - __file__ -except NameError: - __file__ = sys.argv[0] -idlelib = join(split(__file__)[0], 'idlelib') -if isdir(idlelib): - sys.path.append(idlelib) - -# see if we are being asked to execute the subprocess code -if '-p' in sys.argv: - # run expects only the port number in sys.argv - sys.argv.remove('-p') - - # this module will become the namespace used by the interactive - # interpreter; remove all variables we have defined. - del sys, __file__, split, join, isdir, idlelib - __import__('run').main() -else: - # Load idlelib/idle.py which starts the application. - import idle diff --git a/Tools/idle/rpc.py b/Tools/idle/rpc.py deleted file mode 100644 index 15946a6..0000000 --- a/Tools/idle/rpc.py +++ /dev/null @@ -1,580 +0,0 @@ -"""RPC Implemention, originally written for the Python Idle IDE - -For security reasons, GvR requested that Idle's Python execution server process -connect to the Idle process, which listens for the connection. Since Idle has -has only one client per server, this was not a limitation. - - +---------------------------------+ +-------------+ - | SocketServer.BaseRequestHandler | | SocketIO | - +---------------------------------+ +-------------+ - ^ | register() | - | | unregister()| - | +-------------+ - | ^ ^ - | | | - | + -------------------+ | - | | | - +-------------------------+ +-----------------+ - | RPCHandler | | RPCClient | - | [attribute of RPCServer]| | | - +-------------------------+ +-----------------+ - -The RPCServer handler class is expected to provide register/unregister methods. -RPCHandler inherits the mix-in class SocketIO, which provides these methods. - -See the Idle run.main() docstring for further information on how this was -accomplished in Idle. - -""" - -import sys -import socket -import select -import SocketServer -import struct -import cPickle as pickle -import threading -import traceback -import copy_reg -import types -import marshal - -def unpickle_code(ms): - co = marshal.loads(ms) - assert isinstance(co, types.CodeType) - return co - -def pickle_code(co): - assert isinstance(co, types.CodeType) - ms = marshal.dumps(co) - return unpickle_code, (ms,) - -# XXX KBK 24Aug02 function pickling capability not used in Idle -# def unpickle_function(ms): -# return ms - -# def pickle_function(fn): -# assert isinstance(fn, type.FunctionType) -# return `fn` - -copy_reg.pickle(types.CodeType, pickle_code, unpickle_code) -# copy_reg.pickle(types.FunctionType, pickle_function, unpickle_function) - -BUFSIZE = 8*1024 - -class RPCServer(SocketServer.TCPServer): - - def __init__(self, addr, handlerclass=None): - if handlerclass is None: - handlerclass = RPCHandler - SocketServer.TCPServer.__init__(self, addr, handlerclass) - - def server_bind(self): - "Override TCPServer method, no bind() phase for connecting entity" - pass - - def server_activate(self): - """Override TCPServer method, connect() instead of listen() - - Due to the reversed connection, self.server_address is actually the - address of the Idle Client to which we are connecting. - - """ - self.socket.connect(self.server_address) - - def get_request(self): - "Override TCPServer method, return already connected socket" - return self.socket, self.server_address - - def handle_error(self, request, client_address): - """Override TCPServer method - - Error message goes to __stderr__. No error message if exiting - normally or socket raised EOF. Other exceptions not handled in - server code will cause os._exit. - - """ - try: - raise - except SystemExit: - raise - except EOFError: - pass - except: - erf = sys.__stderr__ - print>>erf, '\n' + '-'*40 - print>>erf, 'Unhandled server exception!' - print>>erf, 'Thread: %s' % threading.currentThread().getName() - print>>erf, 'Client Address: ', client_address - print>>erf, 'Request: ', repr(request) - traceback.print_exc(file=erf) - print>>erf, '\n*** Unrecoverable, server exiting!' - print>>erf, '-'*40 - import os - os._exit(0) - - -objecttable = {} - -class SocketIO: - - nextseq = 0 - - def __init__(self, sock, objtable=None, debugging=None): - self.mainthread = threading.currentThread() - if debugging is not None: - self.debugging = debugging - self.sock = sock - if objtable is None: - objtable = objecttable - self.objtable = objtable - self.cvar = threading.Condition() - self.responses = {} - self.cvars = {} - self.interrupted = False - - def close(self): - sock = self.sock - self.sock = None - if sock is not None: - sock.close() - - def debug(self, *args): - if not self.debugging: - return - s = self.location + " " + str(threading.currentThread().getName()) - for a in args: - s = s + " " + str(a) - print>>sys.__stderr__, s - - def register(self, oid, object): - self.objtable[oid] = object - - def unregister(self, oid): - try: - del self.objtable[oid] - except KeyError: - pass - - def localcall(self, request): - self.debug("localcall:", request) - try: - how, (oid, methodname, args, kwargs) = request - except TypeError: - return ("ERROR", "Bad request format") - assert how == "call" - if not self.objtable.has_key(oid): - return ("ERROR", "Unknown object id: %s" % `oid`) - obj = self.objtable[oid] - if methodname == "__methods__": - methods = {} - _getmethods(obj, methods) - return ("OK", methods) - if methodname == "__attributes__": - attributes = {} - _getattributes(obj, attributes) - return ("OK", attributes) - if not hasattr(obj, methodname): - return ("ERROR", "Unsupported method name: %s" % `methodname`) - method = getattr(obj, methodname) - try: - ret = method(*args, **kwargs) - if isinstance(ret, RemoteObject): - ret = remoteref(ret) - return ("OK", ret) - except SystemExit: - raise - except socket.error: - pass - except: - self.debug("localcall:EXCEPTION") - traceback.print_exc(file=sys.__stderr__) - return ("EXCEPTION", None) - - def remotecall(self, oid, methodname, args, kwargs): - self.debug("remotecall:asynccall: ", oid, methodname) - # XXX KBK 06Feb03 self.interrupted logic may not be necessary if - # subprocess is threaded. - if self.interrupted: - self.interrupted = False - raise KeyboardInterrupt - seq = self.asynccall(oid, methodname, args, kwargs) - return self.asyncreturn(seq) - - def asynccall(self, oid, methodname, args, kwargs): - request = ("call", (oid, methodname, args, kwargs)) - seq = self.newseq() - self.debug(("asynccall:%d:" % seq), oid, methodname, args, kwargs) - self.putmessage((seq, request)) - return seq - - def asyncreturn(self, seq): - self.debug("asyncreturn:%d:call getresponse(): " % seq) - response = self.getresponse(seq, wait=None) - self.debug(("asyncreturn:%d:response: " % seq), response) - return self.decoderesponse(response) - - def decoderesponse(self, response): - how, what = response - if how == "OK": - return what - if how == "EXCEPTION": - self.debug("decoderesponse: EXCEPTION") - return None - if how == "ERROR": - self.debug("decoderesponse: Internal ERROR:", what) - raise RuntimeError, what - raise SystemError, (how, what) - - def mainloop(self): - """Listen on socket until I/O not ready or EOF - - Main thread pollresponse() will loop looking for seq number None, which - never comes, and exit on EOFError. - - """ - try: - self.getresponse(myseq=None, wait=None) - except EOFError: - pass - - def getresponse(self, myseq, wait): - response = self._getresponse(myseq, wait) - if response is not None: - how, what = response - if how == "OK": - response = how, self._proxify(what) - return response - - def _proxify(self, obj): - if isinstance(obj, RemoteProxy): - return RPCProxy(self, obj.oid) - if isinstance(obj, types.ListType): - return map(self._proxify, obj) - # XXX Check for other types -- not currently needed - return obj - - def _getresponse(self, myseq, wait): - self.debug("_getresponse:myseq:", myseq) - if threading.currentThread() is self.mainthread: - # Main thread: does all reading of requests or responses - # Loop here, blocking each time until socket is ready. - while 1: - response = self.pollresponse(myseq, wait) - if response is not None: - return response - else: - # Auxiliary thread: wait for notification from main thread - self.cvar.acquire() - self.cvars[myseq] = self.cvar - while not self.responses.has_key(myseq): - self.cvar.wait() - response = self.responses[myseq] - del self.responses[myseq] - del self.cvars[myseq] - self.cvar.release() - return response - - def newseq(self): - self.nextseq = seq = self.nextseq + 2 - return seq - - def putmessage(self, message): - self.debug("putmessage:%d:" % message[0]) - try: - s = pickle.dumps(message) - except: - print >>sys.__stderr__, "Cannot pickle:", `message` - raise - s = struct.pack("<i", len(s)) + s - while len(s) > 0: - try: - n = self.sock.send(s) - except AttributeError: - # socket was closed - raise IOError - else: - s = s[n:] - - def ioready(self, wait=0.0): - r, w, x = select.select([self.sock.fileno()], [], [], wait) - return len(r) - - buffer = "" - bufneed = 4 - bufstate = 0 # meaning: 0 => reading count; 1 => reading data - - def pollpacket(self, wait=0.0): - self._stage0() - if len(self.buffer) < self.bufneed: - if not self.ioready(wait): - return None - try: - s = self.sock.recv(BUFSIZE) - except socket.error: - raise EOFError - if len(s) == 0: - raise EOFError - self.buffer += s - self._stage0() - return self._stage1() - - def _stage0(self): - if self.bufstate == 0 and len(self.buffer) >= 4: - s = self.buffer[:4] - self.buffer = self.buffer[4:] - self.bufneed = struct.unpack("<i", s)[0] - self.bufstate = 1 - - def _stage1(self): - if self.bufstate == 1 and len(self.buffer) >= self.bufneed: - packet = self.buffer[:self.bufneed] - self.buffer = self.buffer[self.bufneed:] - self.bufneed = 4 - self.bufstate = 0 - return packet - - def pollmessage(self, wait=0.0): - packet = self.pollpacket(wait) - if packet is None: - return None - try: - message = pickle.loads(packet) - except: - print >>sys.__stderr__, "-----------------------" - print >>sys.__stderr__, "cannot unpickle packet:", `packet` - traceback.print_stack(file=sys.__stderr__) - print >>sys.__stderr__, "-----------------------" - raise - return message - - def pollresponse(self, myseq, wait=0.0): - """Handle messages received on the socket. - - Some messages received may be asynchronous 'call' commands, and - some may be responses intended for other threads. - - Loop until message with myseq sequence number is received. Save others - in self.responses and notify the owning thread, except that 'call' - commands are handed off to localcall() and the response sent back - across the link with the appropriate sequence number. - - """ - while 1: - message = self.pollmessage(wait) - if message is None: # socket not ready - return None - #wait = 0.0 # poll on subsequent passes instead of blocking - seq, resq = message - self.debug("pollresponse:%d:myseq:%s" % (seq, myseq)) - if resq[0] == "call": - self.debug("pollresponse:%d:localcall:call:" % seq) - response = self.localcall(resq) - self.debug("pollresponse:%d:localcall:response:%s" - % (seq, response)) - self.putmessage((seq, response)) - continue - elif seq == myseq: - return resq - else: - self.cvar.acquire() - cv = self.cvars.get(seq) - # response involving unknown sequence number is discarded, - # probably intended for prior incarnation - if cv is not None: - self.responses[seq] = resq - cv.notify() - self.cvar.release() - continue - -#----------------- end class SocketIO -------------------- - -class RemoteObject: - # Token mix-in class - pass - -def remoteref(obj): - oid = id(obj) - objecttable[oid] = obj - return RemoteProxy(oid) - -class RemoteProxy: - - def __init__(self, oid): - self.oid = oid - -class RPCHandler(SocketServer.BaseRequestHandler, SocketIO): - - debugging = False - location = "#S" # Server - - def __init__(self, sock, addr, svr): - svr.current_handler = self ## cgt xxx - SocketIO.__init__(self, sock) - SocketServer.BaseRequestHandler.__init__(self, sock, addr, svr) - - def handle(self): - "handle() method required by SocketServer" - self.mainloop() - - def get_remote_proxy(self, oid): - return RPCProxy(self, oid) - -class RPCClient(SocketIO): - - debugging = False - location = "#C" # Client - - nextseq = 1 # Requests coming from the client are odd numbered - - def __init__(self, address, family=socket.AF_INET, type=socket.SOCK_STREAM): - self.listening_sock = socket.socket(family, type) - self.listening_sock.setsockopt(socket.SOL_SOCKET, - socket.SO_REUSEADDR, 1) - self.listening_sock.bind(address) - self.listening_sock.listen(1) - - def accept(self): - working_sock, address = self.listening_sock.accept() - if self.debugging: - print>>sys.__stderr__, "****** Connection request from ", address - if address[0] == '127.0.0.1': - SocketIO.__init__(self, working_sock) - else: - print>>sys.__stderr__, "** Invalid host: ", address - raise socket.error - - def get_remote_proxy(self, oid): - return RPCProxy(self, oid) - -class RPCProxy: - - __methods = None - __attributes = None - - def __init__(self, sockio, oid): - self.sockio = sockio - self.oid = oid - - def __getattr__(self, name): - if self.__methods is None: - self.__getmethods() - if self.__methods.get(name): - return MethodProxy(self.sockio, self.oid, name) - if self.__attributes is None: - self.__getattributes() - if not self.__attributes.has_key(name): - raise AttributeError, name - __getattr__.DebuggerStepThrough=1 - - def __getattributes(self): - self.__attributes = self.sockio.remotecall(self.oid, - "__attributes__", (), {}) - - def __getmethods(self): - self.__methods = self.sockio.remotecall(self.oid, - "__methods__", (), {}) - -def _getmethods(obj, methods): - # Helper to get a list of methods from an object - # Adds names to dictionary argument 'methods' - for name in dir(obj): - attr = getattr(obj, name) - if callable(attr): - methods[name] = 1 - if type(obj) == types.InstanceType: - _getmethods(obj.__class__, methods) - if type(obj) == types.ClassType: - for super in obj.__bases__: - _getmethods(super, methods) - -def _getattributes(obj, attributes): - for name in dir(obj): - attr = getattr(obj, name) - if not callable(attr): - attributes[name] = 1 - -class MethodProxy: - - def __init__(self, sockio, oid, name): - self.sockio = sockio - self.oid = oid - self.name = name - - def __call__(self, *args, **kwargs): - value = self.sockio.remotecall(self.oid, self.name, args, kwargs) - return value - -# -# Self Test -# - -def testServer(addr): - # XXX 25 Jul 02 KBK needs update to use rpc.py register/unregister methods - class RemotePerson: - def __init__(self,name): - self.name = name - def greet(self, name): - print "(someone called greet)" - print "Hello %s, I am %s." % (name, self.name) - print - def getName(self): - print "(someone called getName)" - print - return self.name - def greet_this_guy(self, name): - print "(someone called greet_this_guy)" - print "About to greet %s ..." % name - remote_guy = self.server.current_handler.get_remote_proxy(name) - remote_guy.greet("Thomas Edison") - print "Done." - print - - person = RemotePerson("Thomas Edison") - svr = RPCServer(addr) - svr.register('thomas', person) - person.server = svr # only required if callbacks are used - - # svr.serve_forever() - svr.handle_request() # process once only - -def testClient(addr): - "demonstrates RPC Client" - # XXX 25 Jul 02 KBK needs update to use rpc.py register/unregister methods - import time - clt=RPCClient(addr) - thomas = clt.get_remote_proxy("thomas") - print "The remote person's name is ..." - print thomas.getName() - # print clt.remotecall("thomas", "getName", (), {}) - print - time.sleep(1) - print "Getting remote thomas to say hi..." - thomas.greet("Alexander Bell") - #clt.remotecall("thomas","greet",("Alexander Bell",), {}) - print "Done." - print - time.sleep(2) - # demonstrates remote server calling local instance - class LocalPerson: - def __init__(self,name): - self.name = name - def greet(self, name): - print "You've greeted me!" - def getName(self): - return self.name - person = LocalPerson("Alexander Bell") - clt.register("alexander",person) - thomas.greet_this_guy("alexander") - # clt.remotecall("thomas","greet_this_guy",("alexander",), {}) - -def test(): - addr=("localhost",8833) - if len(sys.argv) == 2: - if sys.argv[1]=='-server': - testServer(addr) - return - testClient(addr) - -if __name__ == '__main__': - test() diff --git a/Tools/idle/run.py b/Tools/idle/run.py deleted file mode 100644 index 497cbbd..0000000 --- a/Tools/idle/run.py +++ /dev/null @@ -1,216 +0,0 @@ -import sys -import time -import socket -import traceback -import threading -import Queue - -import boolcheck - -import CallTips -import RemoteDebugger -import RemoteObjectBrowser -import StackViewer -import rpc -import interrupt - -import __main__ - -# Thread shared globals: Establish a queue between a subthread (which handles -# the socket) and the main thread (which runs user code), plus global -# completion and exit flags: - -server = None # RPCServer instance -queue = Queue.Queue(0) -execution_finished = False -exit_requested = False - - -def main(): - """Start the Python execution server in a subprocess - - In the Python subprocess, RPCServer is instantiated with handlerclass - MyHandler, which inherits register/unregister methods from RPCHandler via - the mix-in class SocketIO. - - When the RPCServer 'server' is instantiated, the TCPServer initialization - creates an instance of run.MyHandler and calls its handle() method. - handle() instantiates a run.Executive object, passing it a reference to the - MyHandler object. That reference is saved as attribute rpchandler of the - Executive instance. The Executive methods have access to the reference and - can pass it on to entities that they command - (e.g. RemoteDebugger.Debugger.start_debugger()). The latter, in turn, can - call MyHandler(SocketIO) register/unregister methods via the reference to - register and unregister themselves. - - """ - global queue, execution_finished, exit_requested - - port = 8833 - if sys.argv[1:]: - port = int(sys.argv[1]) - sys.argv[:] = [""] - sockthread = threading.Thread(target=manage_socket, - name='SockThread', - args=(('localhost', port),)) - sockthread.setDaemon(True) - sockthread.start() - while 1: - try: - if exit_requested: - sys.exit() - # XXX KBK 22Mar03 eventually check queue here! - pass - time.sleep(0.05) - except KeyboardInterrupt: - ##execution_finished = True - continue - -def manage_socket(address): - global server, exit_requested - - for i in range(6): - time.sleep(i) - try: - server = rpc.RPCServer(address, MyHandler) - break - except socket.error, err: - if i < 3: - print>>sys.__stderr__, ".. ", - else: - print>>sys.__stderr__,"\nPython subprocess socket error: "\ - + err[1] + ", retrying...." - else: - print>>sys.__stderr__, "\nConnection to Idle failed, exiting." - exit_requested = True - server.handle_request() # A single request only - - -class MyHandler(rpc.RPCHandler): - - def handle(self): - """Override base method""" - executive = Executive(self) - self.register("exec", executive) - sys.stdin = self.get_remote_proxy("stdin") - sys.stdout = self.get_remote_proxy("stdout") - sys.stderr = self.get_remote_proxy("stderr") - rpc.RPCHandler.getresponse(self, myseq=None, wait=0.5) - - -class Executive: - - def __init__(self, rpchandler): - self.rpchandler = rpchandler - self.locals = __main__.__dict__ - self.calltip = CallTips.CallTips() - - def runcode(self, code): - global queue, execution_finished - - execution_finished = False - queue.put(code) - # dequeue and run in subthread - self.runcode_from_queue() - while not execution_finished: - time.sleep(0.05) - - def runcode_from_queue(self): - global queue, execution_finished - - # poll until queue has code object, using threads, just block? - while True: - try: - code = queue.get(0) - break - except Queue.Empty: - time.sleep(0.05) - try: - exec code in self.locals - except: - self.flush_stdout() - efile = sys.stderr - typ, val, tb = info = sys.exc_info() - sys.last_type, sys.last_value, sys.last_traceback = info - tbe = traceback.extract_tb(tb) - print >>efile, 'Traceback (most recent call last):' - exclude = ("run.py", "rpc.py", "RemoteDebugger.py", "bdb.py") - self.cleanup_traceback(tbe, exclude) - traceback.print_list(tbe, file=efile) - lines = traceback.format_exception_only(typ, val) - for line in lines: - print>>efile, line, - execution_finished = True - else: - self.flush_stdout() - execution_finished = True - - def flush_stdout(self): - try: - if sys.stdout.softspace: - sys.stdout.softspace = 0 - sys.stdout.write("\n") - except (AttributeError, EOFError): - pass - - def cleanup_traceback(self, tb, exclude): - "Remove excluded traces from beginning/end of tb; get cached lines" - orig_tb = tb[:] - while tb: - for rpcfile in exclude: - if tb[0][0].count(rpcfile): - break # found an exclude, break for: and delete tb[0] - else: - break # no excludes, have left RPC code, break while: - del tb[0] - while tb: - for rpcfile in exclude: - if tb[-1][0].count(rpcfile): - break - else: - break - del tb[-1] - if len(tb) == 0: - # exception was in IDLE internals, don't prune! - tb[:] = orig_tb[:] - print>>sys.stderr, "** IDLE Internal Exception: " - for i in range(len(tb)): - fn, ln, nm, line = tb[i] - if nm == '?': - nm = "-toplevel-" - if not line and fn.startswith("<pyshell#"): - line = self.rpchandler.remotecall('linecache', 'getline', - (fn, ln), {}) - tb[i] = fn, ln, nm, line - - def interrupt_the_server(self): - self.rpchandler.interrupted = True - ##print>>sys.__stderr__, "** Interrupt main!" - interrupt.interrupt_main() - - def shutdown_the_server(self): - global exit_requested - - exit_requested = True - - def start_the_debugger(self, gui_adap_oid): - return RemoteDebugger.start_debugger(self.rpchandler, gui_adap_oid) - - def stop_the_debugger(self, idb_adap_oid): - "Unregister the Idb Adapter. Link objects and Idb then subject to GC" - self.rpchandler.unregister(idb_adap_oid) - - def get_the_calltip(self, name): - return self.calltip.fetch_tip(name) - - def stackviewer(self, flist_oid=None): - if not hasattr(sys, "last_traceback"): - return None - flist = None - if flist_oid is not None: - flist = self.rpchandler.get_remote_proxy(flist_oid) - tb = sys.last_traceback - while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]: - tb = tb.tb_next - item = StackViewer.StackTreeItem(flist, tb) - return RemoteObjectBrowser.remote_object_tree_item(item) diff --git a/Tools/idle/setup.cfg b/Tools/idle/setup.cfg deleted file mode 100644 index c4b5729..0000000 --- a/Tools/idle/setup.cfg +++ /dev/null @@ -1,4 +0,0 @@ -[bdist_rpm] -release = 1 -packager = Kurt B. Kaiser <kbk@shore.net> - diff --git a/Tools/idle/tabpage.py b/Tools/idle/tabpage.py deleted file mode 100644 index 12f8929..0000000 --- a/Tools/idle/tabpage.py +++ /dev/null @@ -1,113 +0,0 @@ -""" -a couple of classes for implementing partial tabbed-page like behaviour -""" - -from Tkinter import * - -class InvalidTabPage(Exception): pass -class AlreadyExists(Exception): pass - -class PageTab(Frame): - """ - a 'page tab' like framed button - """ - def __init__(self,parent): - Frame.__init__(self, parent,borderwidth=2,relief=RIDGE) - self.button=Radiobutton(self,padx=5,pady=5,takefocus=FALSE, - indicatoron=FALSE,highlightthickness=0, - borderwidth=0,selectcolor=self.cget('bg')) - self.button.pack() - -class TabPageSet(Frame): - """ - a set of 'pages' with TabButtons for controlling their display - """ - def __init__(self,parent,pageNames=[],**kw): - """ - pageNames - a list of strings, each string will be the dictionary key - to a page's data, and the name displayed on the page's tab. Should be - specified in desired page order. The first page will be the default - and first active page. - """ - Frame.__init__(self, parent, kw) - self.grid_location(0,0) - self.columnconfigure(0,weight=1) - self.rowconfigure(1,weight=1) - self.tabBar=Frame(self) - self.tabBar.grid(row=0,column=0,sticky=EW) - self.activePage=StringVar(self) - self.defaultPage='' - self.pages={} - for name in pageNames: - self.AddPage(name) - - def ChangePage(self,pageName=None): - if pageName: - if pageName in self.pages.keys(): - self.activePage.set(pageName) - else: - raise InvalidTabPage, 'Invalid TabPage Name' - ## pop up the active 'tab' only - for page in self.pages.keys(): - self.pages[page]['tab'].config(relief=RIDGE) - self.pages[self.GetActivePage()]['tab'].config(relief=RAISED) - ## switch page - self.pages[self.GetActivePage()]['page'].lift() - - def GetActivePage(self): - return self.activePage.get() - - def AddPage(self,pageName): - if pageName in self.pages.keys(): - raise AlreadyExists, 'TabPage Name Already Exists' - self.pages[pageName]={'tab':PageTab(self.tabBar), - 'page':Frame(self,borderwidth=2,relief=RAISED)} - self.pages[pageName]['tab'].button.config(text=pageName, - command=self.ChangePage,variable=self.activePage, - value=pageName) - self.pages[pageName]['tab'].pack(side=LEFT) - self.pages[pageName]['page'].grid(row=1,column=0,sticky=NSEW) - if len(self.pages)==1: # adding first page - self.defaultPage=pageName - self.activePage.set(self.defaultPage) - self.ChangePage() - - def RemovePage(self,pageName): - if not pageName in self.pages.keys(): - raise InvalidTabPage, 'Invalid TabPage Name' - self.pages[pageName]['tab'].pack_forget() - self.pages[pageName]['page'].grid_forget() - self.pages[pageName]['tab'].destroy() - self.pages[pageName]['page'].destroy() - del(self.pages[pageName]) - # handle removing last remaining, or default, or active page - if not self.pages: # removed last remaining page - self.defaultPage='' - return - if pageName==self.defaultPage: # set a new default page - self.defaultPage=\ - self.tabBar.winfo_children()[0].button.cget('text') - if pageName==self.GetActivePage(): # set a new active page - self.activePage.set(self.defaultPage) - self.ChangePage() - -if __name__ == '__main__': - #test dialog - root=Tk() - tabPage=TabPageSet(root,pageNames=['Foobar','Baz']) - tabPage.pack(expand=TRUE,fill=BOTH) - Label(tabPage.pages['Foobar']['page'],text='Foo',pady=20).pack() - Label(tabPage.pages['Foobar']['page'],text='Bar',pady=20).pack() - Label(tabPage.pages['Baz']['page'],text='Baz').pack() - entryPgName=Entry(root) - buttonAdd=Button(root,text='Add Page', - command=lambda:tabPage.AddPage(entryPgName.get())) - buttonRemove=Button(root,text='Remove Page', - command=lambda:tabPage.RemovePage(entryPgName.get())) - labelPgName=Label(root,text='name of page to add/remove:') - buttonAdd.pack(padx=5,pady=5) - buttonRemove.pack(padx=5,pady=5) - labelPgName.pack(padx=5) - entryPgName.pack(padx=5) - tabPage.ChangePage() - root.mainloop() diff --git a/Tools/idle/textView.py b/Tools/idle/textView.py deleted file mode 100644 index 23e8bed..0000000 --- a/Tools/idle/textView.py +++ /dev/null @@ -1,77 +0,0 @@ -##---------------------------------------------------------------------------## -## -## idle - simple text view dialog -## elguavas -## -##---------------------------------------------------------------------------## -""" -simple text browser for idle -""" -from Tkinter import * -import tkMessageBox - -class TextViewer(Toplevel): - """ - simple text viewer dialog for idle - """ - def __init__(self,parent,title,fileName): - """ - fileName - string,should be an absoulute filename - """ - Toplevel.__init__(self, parent) - self.configure(borderwidth=5) - self.geometry("+%d+%d" % (parent.winfo_rootx()+10, - parent.winfo_rooty()+10)) - #elguavas - config placeholders til config stuff completed - self.bg=None - self.fg=None - - self.CreateWidgets() - self.title(title) - self.transient(parent) - self.grab_set() - self.protocol("WM_DELETE_WINDOW", self.Ok) - self.parent = parent - self.textView.focus_set() - #key bindings for this dialog - self.bind('<Return>',self.Ok) #dismiss dialog - self.bind('<Escape>',self.Ok) #dismiss dialog - self.LoadTextFile(fileName) - self.textView.config(state=DISABLED) - self.wait_window() - - def LoadTextFile(self, fileName): - textFile = None - try: - textFile = open(fileName, 'r') - except IOError: - tkMessageBox.showerror(title='File Load Error', - message='Unable to load file '+`fileName`+' .') - else: - self.textView.insert(0.0,textFile.read()) - - def CreateWidgets(self): - frameText = Frame(self) - frameButtons = Frame(self) - self.buttonOk = Button(frameButtons,text='Ok', - command=self.Ok,takefocus=FALSE,default=ACTIVE) - self.scrollbarView = Scrollbar(frameText,orient=VERTICAL, - takefocus=FALSE,highlightthickness=0) - self.textView = Text(frameText,wrap=WORD,highlightthickness=0) - self.scrollbarView.config(command=self.textView.yview) - self.textView.config(yscrollcommand=self.scrollbarView.set) - self.buttonOk.pack(padx=5,pady=5) - self.scrollbarView.pack(side=RIGHT,fill=Y) - self.textView.pack(side=LEFT,expand=TRUE,fill=BOTH) - frameButtons.pack(side=BOTTOM,fill=X) - frameText.pack(side=TOP,expand=TRUE,fill=BOTH) - - def Ok(self, event=None): - self.destroy() - -if __name__ == '__main__': - #test the dialog - root=Tk() - Button(root,text='View', - command=lambda:TextViewer(root,'Text','./textView.py')).pack() - root.mainloop() |