This commit is contained in:
ton
2024-10-07 10:13:40 +07:00
parent aa1631742f
commit 3a7d696db6
9729 changed files with 1832837 additions and 161742 deletions

View File

@@ -277,7 +277,7 @@ 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.
automatically pops up when you get a traceback.
Windows menu:

View File

@@ -1,13 +1,51 @@
The IDLE icons are from https://bugs.python.org/issue1490384
IDLE-PYTHON LOGOS
Created by Andrew Clover.
These are sent to tk on Windows, *NIX, and non-Aqua macOS
in pyshell following "# set application icon".
The original sources are available from Andrew's website:
2006?: Andrew Clover made variously sized python icons for win23.
https://www.doxdesk.com/software/py/pyicons.html
Various different formats and sizes are available at this GitHub Pull Request:
https://github.com/python/cpython/pull/17473
2006: 16, 32, and 48 bit .png versions were copied to CPython
as Python application icons, maybe in PC/icons/py.ico.
https://github.com/python/cpython/issues/43372
The idle.ico file was created with ImageMagick:
2014: They were copied (perhaps a bit revised) to idlelib/Icons.
https://github.com/python/cpython/issues/64605
.gif versions were also added.
$ convert idle_16.png idle_32.png idle_48.png idle_256.png idle.ico
2020: Add Clover's 256-bit image.
https://github.com/python/cpython/issues/82620
Other fixups were done.
The idle.ico file used for Windows was created with ImageMagick:
$ convert idle_16.png idle_32.png idle_48.png idle_256.png idle.ico
** This needs redoing whenever files are changed.
?? Do Start, Desktop, and Taskbar use idlelib/Icons files?
Issue added Windows Store PC/icons/idlex44.png and .../idlex150.png.
https://github.com/python/cpython/pull/22817
?? Should these be updated with major changes?
2022: Optimize .png images in CPython repository with external program.
https://github.com/python/cpython/pull/21348
idle.ico (and idlex##) were not updated.
The idlexx.gif files are only needed for *nix running tcl/tk 8.5.
As of 2022, this was known true for 1 'major' Linux distribution.
(Same would be true for any non-Aqua macOS with 8.5, but now none?)
Can be deleted when we require 8.6 or it is known always used.
Future: Derivatives of Python logo should be submitted for approval.
PSF Trademark Working Group / Committee psf-trademarks@python.org
https://www.python.org/community/logos/ # Original files
https://www.python.org/psf/trademarks-faq/
https://www.python.org/psf/trademarks/ # Usage.
OTHER GIFS: These are used by browsers using idlelib.tree.
At least some will not be used when tree is replaced by ttk.Treeview.
Edited 2024 August 26 by TJR.

View File

@@ -1,9 +1,47 @@
What's New in IDLE 3.12.z
(since 3.12.0)
Released after 2023-10-02
=========================
gh-120083: Add explicit black IDLE Hovertip foreground color needed for
recent macOS. Fixes Sonoma showing unreadable white on pale yellow.
Patch by John Riggles.
gh-122482: Change About IDLE to direct users to discuss.python.org
instead of the now unused idle-dev email and mailing list.
gh-78889: Stop Shell freezes by blocking user access to non-method
sys.stdout.shell attributes, which are all private.
gh-78955: Use user-selected color theme for Help => IDLE Doc.
gh-96905: In idlelib code, stop redefining built-ins 'dict' and 'object'.
gh-72284: Improve the lists of features, editor key bindings,
and shell key bingings in the IDLE doc.
gh-113903: Fix rare failure of test.test_idle, in test_configdialog.
gh-113729: Fix the "Help -> IDLE Doc" menu bug in 3.11.7 and 3.12.1.
gh-57795: Enter selected text into the Find box when opening
a Replace dialog. Patch by Roger Serwy and Zackery Spytz.
gh-113269: Fix test_editor hang on macOS Catalina.
Patch by Terry Reedy.
gh-112939: Fix processing unsaved files when quitting IDLE on macOS.
Patch by Ronald Oussoren and Christopher Chavez.
gh-79871: Add docstrings to debugger.py. Fix two bugs in test_debugger and expand coverage by 47%. Patch by Anthony Shaw.
What's New in IDLE 3.12.0
(since 3.11.0)
Released on 2023-10-02
=========================
gh-104719: Remove IDLE's modification of tokenize.tabsize and test
other uses of tokenize data and methods.
@@ -539,14 +577,14 @@ bpo-33679: Enable theme-specific color configuration for Code Context.
color setting, default or custom, on the extensions tab, that applied
to all themes.) For built-in themes, the foreground is the same as
normal text and the background is a contrasting gray. Context colors for
custom themes are set on the Hightlights tab along with other colors.
custom themes are set on the Highlights tab along with other colors.
When one starts IDLE from a console and loads a custom theme without
definitions for 'context', one will see a warning message on the
console.
bpo-33642: Display up to maxlines non-blank lines for Code Context.
If there is no current context, show a single blank line. (Previously,
the Code Contex had numlines lines, usually with some blank.) The use
the Code Context had numlines lines, usually with some blank.) The use
of a new option, 'maxlines' (default 15), avoids possible interference
with user settings of the old option, 'numlines' (default 3).
@@ -700,7 +738,7 @@ not affect their keyset-specific customization after 3.6.3. and vice
versa.
Initial patch by Charles Wohlganger, revised by Terry Jan Reedy.
bpo-31051: Rearrange condigdialog General tab.
bpo-31051: Rearrange configdialog General tab.
Sort non-Help options into Window (Shell+Editor) and Editor (only).
Leave room for the addition of new options.
Patch by Terry Jan Reedy.

View File

@@ -179,7 +179,7 @@ it -- i.e. you can only edit the current command, and the cursor can't
escape from the command area. (Albert Brandl)
- Set X11 class to "idle/Idle", set icon and title to something
beginning with "idle" -- for window manangers. (Randall Hopper)
beginning with "idle" -- for window managers. (Randall Hopper)
- Config files editable through a preferences dialog. (me) DONE

View File

@@ -250,9 +250,11 @@ def _module_browser(parent): # htest #
class Nested_in_closure: pass
ModuleBrowser(parent, file, _htest=True)
if __name__ == "__main__":
if len(sys.argv) == 1: # If pass file on command line, unittest fails.
from unittest import main
main('idlelib.idle_test.test_browser', verbosity=2, exit=False)
from idlelib.idle_test.htest import run
run(_module_browser)

View File

@@ -193,6 +193,7 @@ def _calltip_window(parent): # htest #
text.focus_set()
if __name__ == '__main__':
from unittest import main
main('idlelib.idle_test.test_calltip_w', verbosity=2, exit=False)

View File

@@ -158,8 +158,9 @@ class IdleConf:
self.defaultCfg = {}
self.userCfg = {}
self.cfg = {} # TODO use to select userCfg vs defaultCfg
# See https://bugs.python.org/issue4630#msg356516 for following.
# self.blink_off_time = <first editor text>['insertofftime']
# See https:/bugs.python.org/issue4630, msg356516.
if not _utest:
self.CreateConfigHandlers()
@@ -597,7 +598,9 @@ class IdleConf:
problem getting any core binding there will be an 'ultimate last
resort fallback' to the CUA-ish bindings defined here.
"""
# TODO: = dict(sorted([(v-event, keys), ...]))?
keyBindings={
# virtual-event: list of key events.
'<<copy>>': ['<Control-c>', '<Control-C>'],
'<<cut>>': ['<Control-x>', '<Control-X>'],
'<<paste>>': ['<Control-v>', '<Control-V>'],
@@ -880,7 +883,7 @@ def _dump(): # htest # (not really, but ignore in coverage)
line, crc = 0, 0
def sprint(obj):
global line, crc
nonlocal line, crc
txt = str(obj)
line += 1
crc = crc32(txt.encode(encoding='utf-8'), crc)
@@ -889,7 +892,7 @@ def _dump(): # htest # (not really, but ignore in coverage)
def dumpCfg(cfg):
print('\n', cfg, '\n') # Cfg has variable '0xnnnnnnnn' address.
for key in sorted(cfg.keys()):
for key in sorted(cfg):
sections = cfg[key].sections()
sprint(key)
sprint(sections)
@@ -904,8 +907,11 @@ def _dump(): # htest # (not really, but ignore in coverage)
dumpCfg(idleConf.userCfg)
print('\nlines = ', line, ', crc = ', crc, sep='')
if __name__ == '__main__':
from unittest import main
main('idlelib.idle_test.test_config', verbosity=2, exit=False)
# Run revised _dump() as htest?
_dump()
# Run revised _dump() (700+ lines) as htest? More sorting.
# Perhaps as window with tabs for textviews, making it config viewer.

View File

@@ -351,4 +351,4 @@ if __name__ == '__main__':
main('idlelib.idle_test.test_config_key', verbosity=2, exit=False)
from idlelib.idle_test.htest import run
run(GetKeysDialog)
run(GetKeysWindow)

View File

@@ -111,7 +111,7 @@ class ConfigDialog(Toplevel):
load_configs: Load pages except for extensions.
activate_config_changes: Tell editors to reload.
"""
self.frame = frame = Frame(self, padding="5px")
self.frame = frame = Frame(self, padding=5)
self.frame.grid(sticky="nwes")
self.note = note = Notebook(frame)
self.extpage = ExtPage(note)
@@ -211,14 +211,8 @@ class ConfigDialog(Toplevel):
contents=help_common+help_pages.get(page, ''))
def deactivate_current_config(self):
"""Remove current key bindings.
Iterate over window instances defined in parent and remove
the keybindings.
"""
# Before a config is saved, some cleanup of current
# config must be done - remove the previous keybindings.
win_instances = self.parent.instance_dict.keys()
for instance in win_instances:
"""Remove current key bindings in current windows."""
for instance in self.parent.instance_dict:
instance.RemoveKeybindings()
def activate_config_changes(self):
@@ -227,8 +221,7 @@ class ConfigDialog(Toplevel):
Dynamically update the current parent window instances
with some of the configuration changes.
"""
win_instances = self.parent.instance_dict.keys()
for instance in win_instances:
for instance in self.parent.instance_dict:
instance.ResetColorizer()
instance.ResetFont()
instance.set_notabs_indentwidth()
@@ -583,22 +576,23 @@ class HighPage(Frame):
(*)theme_message: Label
"""
self.theme_elements = {
'Normal Code or Text': ('normal', '00'),
'Code Context': ('context', '01'),
'Python Keywords': ('keyword', '02'),
'Python Definitions': ('definition', '03'),
'Python Builtins': ('builtin', '04'),
'Python Comments': ('comment', '05'),
'Python Strings': ('string', '06'),
'Selected Text': ('hilite', '07'),
'Found Text': ('hit', '08'),
'Cursor': ('cursor', '09'),
'Editor Breakpoint': ('break', '10'),
'Shell Prompt': ('console', '11'),
'Error Text': ('error', '12'),
'Shell User Output': ('stdout', '13'),
'Shell User Exception': ('stderr', '14'),
'Line Number': ('linenumber', '16'),
# Display-name: internal-config-tag-name.
'Normal Code or Text': 'normal',
'Code Context': 'context',
'Python Keywords': 'keyword',
'Python Definitions': 'definition',
'Python Builtins': 'builtin',
'Python Comments': 'comment',
'Python Strings': 'string',
'Selected Text': 'hilite',
'Found Text': 'hit',
'Cursor': 'cursor',
'Editor Breakpoint': 'break',
'Shell Prompt': 'console',
'Error Text': 'error',
'Shell User Output': 'stdout',
'Shell User Exception': 'stderr',
'Line Number': 'linenumber',
}
self.builtin_name = tracers.add(
StringVar(self), self.var_changed_builtin_name)
@@ -658,7 +652,7 @@ class HighPage(Frame):
# event.widget.winfo_top_level().highlight_target.set(elem)
self.highlight_target.set(elem)
text.tag_bind(
self.theme_elements[element][0], '<ButtonPress-1>', tem)
self.theme_elements[element], '<ButtonPress-1>', tem)
text['state'] = 'disabled'
self.style.configure('frame_color_set.TFrame', borderwidth=1,
relief='solid')
@@ -765,8 +759,7 @@ class HighPage(Frame):
self.builtinlist.SetMenu(item_list, item_list[0])
self.set_theme_type()
# Load theme element option menu.
theme_names = list(self.theme_elements.keys())
theme_names.sort(key=lambda x: self.theme_elements[x][1])
theme_names = list(self.theme_elements)
self.targetlist.SetMenu(theme_names, theme_names[0])
self.paint_theme_sample()
self.set_highlight_target()
@@ -893,7 +886,7 @@ class HighPage(Frame):
new_color = self.color.get()
self.style.configure('frame_color_set.TFrame', background=new_color)
plane = 'foreground' if self.fg_bg_toggle.get() else 'background'
sample_element = self.theme_elements[self.highlight_target.get()][0]
sample_element = self.theme_elements[self.highlight_target.get()]
self.highlight_sample.tag_config(sample_element, **{plane: new_color})
theme = self.custom_name.get()
theme_element = sample_element + '-' + plane
@@ -1007,7 +1000,7 @@ class HighPage(Frame):
frame_color_set
"""
# Set the color sample area.
tag = self.theme_elements[self.highlight_target.get()][0]
tag = self.theme_elements[self.highlight_target.get()]
plane = 'foreground' if self.fg_bg_toggle.get() else 'background'
color = self.highlight_sample.tag_cget(tag, plane)
self.style.configure('frame_color_set.TFrame', background=color)
@@ -1037,7 +1030,7 @@ class HighPage(Frame):
else: # User theme
theme = self.custom_name.get()
for element_title in self.theme_elements:
element = self.theme_elements[element_title][0]
element = self.theme_elements[element_title]
colors = idleConf.GetHighlight(theme, element)
if element == 'cursor': # Cursor sample needs special painting.
colors['background'] = idleConf.GetHighlight(
@@ -1477,12 +1470,13 @@ class KeysPage(Frame):
reselect = True
list_index = self.bindingslist.index(ANCHOR)
keyset = idleConf.GetKeySet(keyset_name)
bind_names = list(keyset.keys())
# 'set' is dict mapping virtual event to list of key events.
bind_names = list(keyset)
bind_names.sort()
self.bindingslist.delete(0, END)
for bind_name in bind_names:
key = ' '.join(keyset[bind_name])
bind_name = bind_name[2:-2] # Trim off the angle brackets.
bind_name = bind_name[2:-2] # Trim double angle brackets.
if keyset_name in changes['keys']:
# Handle any unsaved changes to this key set.
if bind_name in changes['keys'][keyset_name]:

View File

@@ -1,3 +1,20 @@
"""Debug user code with a GUI interface to a subclass of bdb.Bdb.
The Idb idb and Debugger gui instances each need a reference to each
other or to an rpc proxy for each other.
If IDLE is started with '-n', so that user code and idb both run in the
IDLE process, Debugger is called without an idb. Debugger.__init__
calls Idb with its incomplete self. Idb.__init__ stores gui and gui
then stores idb.
If IDLE is started normally, so that user code executes in a separate
process, debugger_r.start_remote_debugger is called, executing in the
IDLE process. It calls 'start the debugger' in the remote process,
which calls Idb with a gui proxy. Then Debugger is called in the IDLE
for more.
"""
import bdb
import os
@@ -10,66 +27,95 @@ from idlelib.window import ListedToplevel
class Idb(bdb.Bdb):
"Supply user_line and user_exception functions for Bdb."
def __init__(self, gui):
self.gui = gui # An instance of Debugger or proxy of remote.
bdb.Bdb.__init__(self)
self.gui = gui # An instance of Debugger or proxy thereof.
super().__init__()
def user_line(self, frame):
if self.in_rpc_code(frame):
"""Handle a user stopping or breaking at a line.
Convert frame to a string and send it to gui.
"""
if _in_rpc_code(frame):
self.set_step()
return
message = self.__frame2message(frame)
message = _frame2message(frame)
try:
self.gui.interaction(message, frame)
except TclError: # When closing debugger window with [x] in 3.x
pass
def user_exception(self, frame, info):
if self.in_rpc_code(frame):
def user_exception(self, frame, exc_info):
"""Handle an the occurrence of an exception."""
if _in_rpc_code(frame):
self.set_step()
return
message = self.__frame2message(frame)
self.gui.interaction(message, frame, info)
message = _frame2message(frame)
self.gui.interaction(message, frame, exc_info)
def in_rpc_code(self, frame):
if frame.f_code.co_filename.count('rpc.py'):
return True
else:
prev_frame = frame.f_back
prev_name = prev_frame.f_code.co_filename
if 'idlelib' in prev_name and 'debugger' in prev_name:
# catch both idlelib/debugger.py and idlelib/debugger_r.py
# on both Posix and Windows
return False
return self.in_rpc_code(prev_frame)
def _in_rpc_code(frame):
"Determine if debugger is within RPC code."
if frame.f_code.co_filename.count('rpc.py'):
return True # Skip this frame.
else:
prev_frame = frame.f_back
if prev_frame is None:
return False
prev_name = prev_frame.f_code.co_filename
if 'idlelib' in prev_name and 'debugger' in prev_name:
# catch both idlelib/debugger.py and idlelib/debugger_r.py
# on both Posix and Windows
return False
return _in_rpc_code(prev_frame)
def __frame2message(self, frame):
code = frame.f_code
filename = code.co_filename
lineno = frame.f_lineno
basename = os.path.basename(filename)
message = f"{basename}:{lineno}"
if code.co_name != "?":
message = f"{message}: {code.co_name}()"
return message
def _frame2message(frame):
"""Return a message string for frame."""
code = frame.f_code
filename = code.co_filename
lineno = frame.f_lineno
basename = os.path.basename(filename)
message = f"{basename}:{lineno}"
if code.co_name != "?":
message = f"{message}: {code.co_name}()"
return message
class Debugger:
"""The debugger interface.
vstack = vsource = vlocals = vglobals = None
This class handles the drawing of the debugger window and
the interactions with the underlying debugger session.
"""
vstack = None
vsource = None
vlocals = None
vglobals = None
stackviewer = None
localsviewer = None
globalsviewer = None
def __init__(self, pyshell, idb=None):
"""Instantiate and draw a debugger window.
:param pyshell: An instance of the PyShell Window
:type pyshell: :class:`idlelib.pyshell.PyShell`
:param idb: An instance of the IDLE debugger (optional)
:type idb: :class:`idlelib.debugger.Idb`
"""
if idb is None:
idb = Idb(self)
self.pyshell = pyshell
self.idb = idb # If passed, a proxy of remote instance.
self.frame = None
self.make_gui()
self.interacting = 0
self.interacting = False
self.nesting_level = 0
def run(self, *args):
"""Run the debugger."""
# Deal with the scenario where we've already got a program running
# in the debugger and we want to start another. If that is the case,
# our second 'run' was invoked from an event dispatched not from
@@ -104,12 +150,13 @@ class Debugger:
self.root.after(100, lambda: self.run(*args))
return
try:
self.interacting = 1
self.interacting = True
return self.idb.run(*args)
finally:
self.interacting = 0
self.interacting = False
def close(self, event=None):
"""Close the debugger and window."""
try:
self.quit()
except Exception:
@@ -127,6 +174,7 @@ class Debugger:
self.top.destroy()
def make_gui(self):
"""Draw the debugger gui on the screen."""
pyshell = self.pyshell
self.flist = pyshell.flist
self.root = root = pyshell.root
@@ -135,11 +183,11 @@ class Debugger:
self.top.wm_iconname("Debug")
top.wm_protocol("WM_DELETE_WINDOW", self.close)
self.top.bind("<Escape>", self.close)
#
self.bframe = bframe = Frame(top)
self.bframe.pack(anchor="w")
self.buttons = bl = []
#
self.bcont = b = Button(bframe, text="Go", command=self.cont)
bl.append(b)
self.bstep = b = Button(bframe, text="Step", command=self.step)
@@ -150,14 +198,14 @@ class Debugger:
bl.append(b)
self.bret = b = Button(bframe, text="Quit", command=self.quit)
bl.append(b)
#
for b in bl:
b.configure(state="disabled")
b.pack(side="left")
#
self.cframe = cframe = Frame(bframe)
self.cframe.pack(side="left")
#
if not self.vstack:
self.__class__.vstack = BooleanVar(top)
self.vstack.set(1)
@@ -180,20 +228,20 @@ class Debugger:
self.bglobals = Checkbutton(cframe,
text="Globals", command=self.show_globals, variable=self.vglobals)
self.bglobals.grid(row=1, column=1)
#
self.status = Label(top, anchor="w")
self.status.pack(anchor="w")
self.error = Label(top, anchor="w")
self.error.pack(anchor="w", fill="x")
self.errorbg = self.error.cget("background")
#
self.fstack = Frame(top, height=1)
self.fstack.pack(expand=1, fill="both")
self.flocals = Frame(top)
self.flocals.pack(expand=1, fill="both")
self.fglobals = Frame(top, height=1)
self.fglobals.pack(expand=1, fill="both")
#
if self.vstack.get():
self.show_stack()
if self.vlocals.get():
@@ -204,7 +252,7 @@ class Debugger:
def interaction(self, message, frame, info=None):
self.frame = frame
self.status.configure(text=message)
#
if info:
type, value, tb = info
try:
@@ -223,28 +271,28 @@ class Debugger:
tb = None
bg = self.errorbg
self.error.configure(text=m1, background=bg)
#
sv = self.stackviewer
if sv:
stack, i = self.idb.get_stack(self.frame, tb)
sv.load_stack(stack, i)
#
self.show_variables(1)
#
if self.vsource.get():
self.sync_source_line()
#
for b in self.buttons:
b.configure(state="normal")
#
self.top.wakeup()
# Nested main loop: Tkinter's main loop is not reentrant, so use
# Tcl's vwait facility, which reenters the event loop until an
# event handler sets the variable we're waiting on
# event handler sets the variable we're waiting on.
self.nesting_level += 1
self.root.tk.call('vwait', '::idledebugwait')
self.nesting_level -= 1
#
for b in self.buttons:
b.configure(state="disabled")
self.status.configure(text="")
@@ -288,8 +336,6 @@ class Debugger:
def abort_loop(self):
self.root.tk.call('set', '::idledebugwait', '1')
stackviewer = None
def show_stack(self):
if not self.stackviewer and self.vstack.get():
self.stackviewer = sv = StackViewer(self.fstack, self.flist, self)
@@ -311,9 +357,6 @@ class Debugger:
self.frame = stackitem[0] # lineno is stackitem[1]
self.show_variables()
localsviewer = None
globalsviewer = None
def show_locals(self):
lv = self.localsviewer
if self.vlocals.get():
@@ -354,26 +397,32 @@ class Debugger:
if gv:
gv.load_dict(gdict, force, self.pyshell.interp.rpcclt)
def set_breakpoint_here(self, filename, lineno):
def set_breakpoint(self, filename, lineno):
"""Set a filename-lineno breakpoint in the debugger.
Called from self.load_breakpoints and EW.setbreakpoint
"""
self.idb.set_break(filename, lineno)
def clear_breakpoint_here(self, filename, lineno):
def clear_breakpoint(self, filename, lineno):
self.idb.clear_break(filename, lineno)
def clear_file_breaks(self, filename):
self.idb.clear_all_file_breaks(filename)
def load_breakpoints(self):
"Load PyShellEditorWindow breakpoints into subprocess debugger"
"""Load PyShellEditorWindow breakpoints into subprocess debugger."""
for editwin in self.pyshell.flist.inversedict:
filename = editwin.io.filename
try:
for lineno in editwin.breakpoints:
self.set_breakpoint_here(filename, lineno)
self.set_breakpoint(filename, lineno)
except AttributeError:
continue
class StackViewer(ScrolledList):
"Code stack viewer for debugger GUI."
def __init__(self, master, flist, gui):
if macosx.isAquaTk():
@@ -414,12 +463,12 @@ class StackViewer(ScrolledList):
self.select(index)
def popup_event(self, event):
"override base method"
"Override base method."
if self.stack:
return ScrolledList.popup_event(self, event)
def fill_menu(self):
"override base method"
"Override base method."
menu = self.menu
menu.add_command(label="Go to source line",
command=self.goto_source_line)
@@ -427,12 +476,12 @@ class StackViewer(ScrolledList):
command=self.show_stack_frame)
def on_select(self, index):
"override base method"
"Override base method."
if 0 <= index < len(self.stack):
self.gui.show_frame(self.stack[index])
def on_double(self, index):
"override base method"
"Override base method."
self.show_source(index)
def goto_source_line(self):
@@ -457,12 +506,13 @@ class StackViewer(ScrolledList):
class NamespaceViewer:
"Global/local namespace viewer for debugger GUI."
def __init__(self, master, title, dict=None):
def __init__(self, master, title, odict=None): # XXX odict never passed.
width = 0
height = 40
if dict:
height = 20*len(dict) # XXX 20 == observed height of Entry widget
if odict:
height = 20*len(odict) # XXX 20 == observed height of Entry widget
self.master = master
self.title = title
import reprlib
@@ -483,24 +533,24 @@ class NamespaceViewer:
canvas["yscrollcommand"] = vbar.set
self.subframe = subframe = Frame(canvas)
self.sfid = canvas.create_window(0, 0, window=subframe, anchor="nw")
self.load_dict(dict)
self.load_dict(odict)
dict = -1
prev_odict = -1 # Needed for initial comparison below.
def load_dict(self, dict, force=0, rpc_client=None):
if dict is self.dict and not force:
def load_dict(self, odict, force=0, rpc_client=None):
if odict is self.prev_odict and not force:
return
subframe = self.subframe
frame = self.frame
for c in list(subframe.children.values()):
c.destroy()
self.dict = None
if not dict:
self.prev_odict = None
if not odict:
l = Label(subframe, text="None")
l.grid(row=0, column=0)
else:
#names = sorted(dict)
###
#
# Because of (temporary) limitations on the dict_keys type (not yet
# public or pickleable), have the subprocess to send a list of
# keys, not a dict_keys object. sorted() will take a dict_keys
@@ -509,13 +559,13 @@ class NamespaceViewer:
# There is also an obscure bug in sorted(dict) where the
# interpreter gets into a loop requesting non-existing dict[0],
# dict[1], dict[2], etc from the debugger_r.DictProxy.
###
keys_list = dict.keys()
# TODO recheck above; see debugger_r 159ff, debugobj 60.
keys_list = odict.keys()
names = sorted(keys_list)
###
row = 0
for name in names:
value = dict[name]
value = odict[name]
svalue = self.repr.repr(value) # repr(value)
# Strip extra quotes caused by calling repr on the (already)
# repr'd value sent across the RPC interface:
@@ -527,7 +577,7 @@ class NamespaceViewer:
l.insert(0, svalue)
l.grid(row=row, column=1, sticky="nw")
row = row+1
self.dict = dict
self.prev_odict = odict
# XXX Could we use a <Configure> callback for the following?
subframe.update_idletasks() # Alas!
width = subframe.winfo_reqwidth()
@@ -544,6 +594,7 @@ class NamespaceViewer:
def close(self):
self.frame.destroy()
if __name__ == "__main__":
from unittest import main
main('idlelib.idle_test.test_debugger', verbosity=2, exit=False)

View File

@@ -125,16 +125,16 @@ class IdbAdapter:
def frame_globals(self, fid):
frame = frametable[fid]
dict = frame.f_globals
did = id(dict)
dicttable[did] = dict
gdict = frame.f_globals
did = id(gdict)
dicttable[did] = gdict
return did
def frame_locals(self, fid):
frame = frametable[fid]
dict = frame.f_locals
did = id(dict)
dicttable[did] = dict
ldict = frame.f_locals
did = id(ldict)
dicttable[did] = ldict
return did
def frame_code(self, fid):
@@ -158,20 +158,17 @@ class IdbAdapter:
def dict_keys(self, did):
raise NotImplementedError("dict_keys not public or pickleable")
## dict = dicttable[did]
## return dict.keys()
## return dicttable[did].keys()
### Needed until dict_keys is type is finished and pickealable.
### Needed until dict_keys type is finished and pickleable.
# xxx finished. pickleable?
### Will probably need to extend rpc.py:SocketIO._proxify at that time.
def dict_keys_list(self, did):
dict = dicttable[did]
return list(dict.keys())
return list(dicttable[did].keys())
def dict_item(self, did, key):
dict = dicttable[did]
value = dict[key]
value = reprlib.repr(value) ### can't pickle module 'builtins'
return value
value = dicttable[did][key]
return reprlib.repr(value) # Can't pickle module 'builtins'.
#----------end class IdbAdapter----------

View File

@@ -1,3 +1,5 @@
"""Define tree items for debug stackviewer, which is only user.
"""
# XXX TO DO:
# - popup menu
# - support partial or total redisplay
@@ -17,9 +19,9 @@ myrepr.maxstring = 100
myrepr.maxother = 100
class ObjectTreeItem(TreeItem):
def __init__(self, labeltext, object, setfunction=None):
def __init__(self, labeltext, object_, setfunction=None):
self.labeltext = labeltext
self.object = object
self.object = object_
self.setfunction = setfunction
def GetLabelText(self):
return self.labeltext
@@ -51,8 +53,8 @@ class ObjectTreeItem(TreeItem):
item = make_objecttreeitem(
str(key) + " =",
value,
lambda value, key=key, object=self.object:
setattr(object, key, value))
lambda value, key=key, object_=self.object:
setattr(object_, key, value))
sublist.append(item)
return sublist
@@ -85,15 +87,16 @@ class SequenceTreeItem(ObjectTreeItem):
value = self.object[key]
except KeyError:
continue
def setfunction(value, key=key, object=self.object):
object[key] = value
def setfunction(value, key=key, object_=self.object):
object_[key] = value
item = make_objecttreeitem(f"{key!r}:", value, setfunction)
sublist.append(item)
return sublist
class DictTreeItem(SequenceTreeItem):
def keys(self):
keys = list(self.object.keys())
# TODO return sorted(self.object)
keys = list(self.object)
try:
keys.sort()
except:
@@ -110,16 +113,16 @@ dispatch = {
type: ClassTreeItem,
}
def make_objecttreeitem(labeltext, object, setfunction=None):
t = type(object)
def make_objecttreeitem(labeltext, object_, setfunction=None):
t = type(object_)
if t in dispatch:
c = dispatch[t]
else:
c = ObjectTreeItem
return c(labeltext, object, setfunction)
return c(labeltext, object_, setfunction)
def _object_browser(parent): # htest #
def _debug_object_browser(parent): # htest #
import sys
from tkinter import Toplevel
top = Toplevel(parent)
@@ -134,9 +137,10 @@ def _object_browser(parent): # htest #
node = TreeNode(sc.canvas, None, item)
node.update()
if __name__ == '__main__':
from unittest import main
main('idlelib.idle_test.test_debugobj', verbosity=2, exit=False)
from idlelib.idle_test.htest import run
run(_object_browser)
run(_debug_object_browser)

View File

@@ -28,6 +28,7 @@ class Delegator:
self.resetcache()
self.delegate = delegate
if __name__ == '__main__':
from unittest import main
main('idlelib.idle_test.test_delegator', verbosity=2)

View File

@@ -29,6 +29,7 @@ class DynOptionMenu(OptionMenu):
if value:
self.variable.set(value)
def _dyn_option_menu(parent): # htest #
from tkinter import Toplevel # + StringVar, Button
@@ -49,6 +50,7 @@ def _dyn_option_menu(parent): # htest #
button = Button(top, text="Change option set", command=update)
button.pack()
if __name__ == '__main__':
# Only module without unittests because of intention to replace.
from idlelib.idle_test.htest import run

View File

@@ -166,8 +166,9 @@ class EditorWindow:
text.bind("<3>",self.right_menu_event)
text.bind('<MouseWheel>', wheel_event)
text.bind('<Button-4>', wheel_event)
text.bind('<Button-5>', wheel_event)
if text._windowingsystem == 'x11':
text.bind('<Button-4>', wheel_event)
text.bind('<Button-5>', wheel_event)
text.bind('<Configure>', self.handle_winconfig)
text.bind("<<cut>>", self.cut)
text.bind("<<copy>>", self.copy)
@@ -913,7 +914,7 @@ class EditorWindow:
def ApplyKeybindings(self):
"""Apply the virtual, configurable keybindings.
Alse update hotkeys to current keyset.
Also update hotkeys to current keyset.
"""
# Called from configdialog.activate_config_changes.
self.mainmenu.default_keydefs = keydefs = idleConf.GetCurrentKeySet()
@@ -1043,7 +1044,9 @@ class EditorWindow:
def saved_change_hook(self):
short = self.short_title()
long = self.long_title()
if short and long:
if short and long and not macosx.isCocoaTk():
# Don't use both values on macOS because
# that doesn't match platform conventions.
title = short + " - " + long + _py_version
elif short:
title = short
@@ -1058,6 +1061,13 @@ class EditorWindow:
self.top.wm_title(title)
self.top.wm_iconname(icon)
if macosx.isCocoaTk():
# Add a proxy icon to the window title
self.top.wm_attributes("-titlepath", long)
# Maintain the modification status for the window
self.top.wm_attributes("-modified", not self.get_saved())
def get_saved(self):
return self.undo.get_saved()
@@ -1748,6 +1758,7 @@ def _editor_window(parent): # htest #
# Does not stop error, neither does following
# edit.text.bind("<<close-window>>", edit.close_event)
if __name__ == '__main__':
from unittest import main
main('idlelib.idle_test.test_editor', verbosity=2, exit=False)

View File

@@ -52,7 +52,7 @@ should probably be refined in the future.)
Extensions are not required to define menu entries for all the events they
implement. (They are also not required to create keybindings, but in that
case there must be empty bindings in cofig-extensions.def)
case there must be empty bindings in config-extensions.def)
Here is a partial example from zzdummy.py:

View File

@@ -124,6 +124,7 @@ def _test(): # TODO check and convert to htest
if flist.inversedict:
root.mainloop()
if __name__ == '__main__':
from unittest import main
main('idlelib.idle_test.test_filelist', verbosity=2)

View File

@@ -190,7 +190,7 @@ class GrepDialog(SearchDialogBase):
def _grep_dialog(parent): # htest #
from tkinter import Toplevel, Text, SEL, END
from tkinter import Toplevel, Text, SEL
from tkinter.ttk import Frame, Button
from idlelib.pyshell import PyShellFileList
@@ -204,15 +204,17 @@ def _grep_dialog(parent): # htest #
frame.pack()
text = Text(frame, height=5)
text.pack()
text.insert('1.0', 'import grep')
def show_grep_dialog():
text.tag_add(SEL, "1.0", END)
text.tag_add(SEL, "1.0", '1.end')
grep(text, flist=flist)
text.tag_remove(SEL, "1.0", END)
text.tag_remove(SEL, "1.0", '1.end')
button = Button(frame, text="Show GrepDialog", command=show_grep_dialog)
button.pack()
if __name__ == "__main__":
from unittest import main
main('idlelib.idle_test.test_grep', verbosity=2, exit=False)

View File

@@ -1,33 +1,31 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>IDLE &#8212; Python 3.12.0a0 documentation</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>IDLE &#8212; Python 3.13.0a2 documentation</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pydoctheme.css?2022.1" />
<link rel="stylesheet" type="text/css" href="../_static/pydoctheme.css?digest=b37c26da2f7529d09fe70b41c4b2133fe4931a90" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/_sphinx_javascript_frameworks_compat.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<script src="../_static/sidebar.js"></script>
<link rel="search" type="application/opensearchdescription+xml"
title="Search within Python 3.12.0a0 documentation"
title="Search within Python 3.13.0a2 documentation"
href="../_static/opensearch.xml"/>
<link rel="author" title="About these documents" href="../about.html" />
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="copyright" title="Copyright" href="../copyright.html" />
<link rel="next" title="Development Tools" href="development.html" />
<link rel="prev" title="tkinter.tixExtension widgets for Tk" href="tkinter.tix.html" />
<link rel="prev" title="tkinter.ttkTk themed widgets" href="tkinter.ttk.html" />
<link rel="canonical" href="https://docs.python.org/3/library/idle.html" />
@@ -41,35 +39,48 @@
}
}
</style>
<link rel="shortcut icon" type="image/png" href="../_static/py.svg" />
<link rel="stylesheet" href="../_static/pydoctheme_dark.css" media="(prefers-color-scheme: dark)" id="pydoctheme_dark_css">
<link rel="shortcut icon" type="image/png" href="../_static/py.svg" />
<script type="text/javascript" src="../_static/copybutton.js"></script>
<script type="text/javascript" src="../_static/menu.js"></script>
<script type="text/javascript" src="../_static/search-focus.js"></script>
<script type="text/javascript" src="../_static/themetoggle.js"></script>
</head>
<body>
<div class="mobile-nav">
<input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation"
aria-pressed="false" aria-expanded="false" role="button" aria-label="Menu" />
<label for="menuToggler" class="toggler__label">
<span></span>
</label>
<nav class="nav-content" role="navigation">
<a href="https://www.python.org/" class="nav-logo">
<img src="../_static/py.svg" alt="Logo"/>
</a>
<div class="version_switcher_placeholder"></div>
<form role="search" class="search" action="../search.html" method="get">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
<path fill-rule="nonzero"
d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" fill="#444"></path>
</svg>
<input type="text" name="q" aria-label="Quick search"/>
<input type="submit" value="Go"/>
</form>
<label for="menuToggler" class="toggler__label">
<span></span>
</label>
<span class="nav-items-wrapper">
<a href="https://www.python.org/" class="nav-logo">
<img src="../_static/py.svg" alt="Logo"/>
</a>
<span class="version_switcher_placeholder"></span>
<form role="search" class="search" action="../search.html" method="get">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
<path fill-rule="nonzero" fill="currentColor" d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path>
</svg>
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
<input type="submit" value="Go"/>
</form>
</span>
</nav>
<div class="menu-wrapper">
<nav class="menu" role="navigation" aria-label="main navigation">
<div class="language_switcher_placeholder"></div>
<label class="theme-selector-label">
Theme
<select class="theme-selector" oninput="activateTheme(this.value)">
<option value="auto" selected>Auto</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</label>
<div>
<h3><a href="../contents.html">Table of Contents</a></h3>
<ul>
@@ -123,8 +134,8 @@
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="tkinter.tix.html"
title="previous chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">tkinter.tix</span></code>Extension widgets for Tk</a></p>
<p class="topless"><a href="tkinter.ttk.html"
title="previous chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">tkinter.ttk</span></code>Tk themed widgets</a></p>
</div>
<div>
<h4>Next topic</h4>
@@ -160,7 +171,7 @@
<a href="development.html" title="Development Tools"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="tkinter.tix.html" title="tkinter.tixExtension widgets for Tk"
<a href="tkinter.ttk.html" title="tkinter.ttkTk themed widgets"
accesskey="P">previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
@@ -173,7 +184,7 @@
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0a0 Documentation</a> &#187;
<a href="../index.html">3.13.0a2 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> &#187;</li>
@@ -184,14 +195,21 @@
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="Quick search" aria-label="Quick search" type="text" name="q" />
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" id="search-box" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
|
</li>
<li class="right">
<label class="theme-selector-label">
Theme
<select class="theme-selector" oninput="activateTheme(this.value)">
<option value="auto" selected>Auto</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</label> |</li>
</ul>
</div>
@@ -208,7 +226,6 @@
<p>IDLE is Pythons Integrated Development and Learning Environment.</p>
<p>IDLE has the following features:</p>
<ul class="simple">
<li><p>coded in 100% pure Python, using the <a class="reference internal" href="tkinter.html#module-tkinter" title="tkinter: Interface to Tcl/Tk for graphical user interfaces"><code class="xref py py-mod docutils literal notranslate"><span class="pre">tkinter</span></code></a> GUI toolkit</p></li>
<li><p>cross-platform: works mostly the same on Windows, Unix, and macOS</p></li>
<li><p>Python shell window (interactive interpreter) with colorizing
of code input, output, and error messages</p></li>
@@ -529,32 +546,26 @@ and that other files do not. Run Python code with the Run menu.</p>
</section>
<section id="key-bindings">
<h3>Key bindings<a class="headerlink" href="#key-bindings" title="Permalink to this heading"></a></h3>
<p>In this section, C refers to the <kbd class="kbd docutils literal notranslate">Control</kbd> key on Windows and Unix and
the <kbd class="kbd docutils literal notranslate">Command</kbd> key on macOS.</p>
<ul>
<li><p><kbd class="kbd docutils literal notranslate">Backspace</kbd> deletes to the left; <kbd class="kbd docutils literal notranslate">Del</kbd> deletes to the right</p></li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">Backspace</kbd></kbd> delete word left; <kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">Del</kbd></kbd> delete word to the right</p></li>
<li><p>Arrow keys and <kbd class="kbd docutils literal notranslate">Page Up</kbd>/<kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">Page</kbd> <kbd class="kbd docutils literal notranslate">Down</kbd></kbd> to move around</p></li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">LeftArrow</kbd></kbd> and <kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">RightArrow</kbd></kbd> moves by words</p></li>
<li><p><kbd class="kbd docutils literal notranslate">Home</kbd>/<kbd class="kbd docutils literal notranslate">End</kbd> go to begin/end of line</p></li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">Home</kbd></kbd>/<kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">End</kbd></kbd> go to begin/end of file</p></li>
<li><p>Some useful Emacs bindings are inherited from Tcl/Tk:</p>
<blockquote>
<div><ul class="simple">
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">a</kbd></kbd> beginning of line</p></li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">e</kbd></kbd> end of line</p></li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">k</kbd></kbd> kill line (but doesnt put it in clipboard)</p></li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">l</kbd></kbd> center window around the insertion point</p></li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">b</kbd></kbd> go backward one character without deleting (usually you can
also use the cursor key for this)</p></li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">f</kbd></kbd> go forward one character without deleting (usually you can
also use the cursor key for this)</p></li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">p</kbd></kbd> go up one line (usually you can also use the cursor key for
this)</p></li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">d</kbd></kbd> delete next character</p></li>
</ul>
</div></blockquote>
</li>
<p>The IDLE insertion cursor is a thin vertical bar between character
positions. When characters are entered, the insertion cursor and
everything to its right moves right one character and
the new character is entered in the new space.</p>
<p>Several non-character keys move the cursor and possibly
delete characters. Deletion does not puts text on the clipboard,
but IDLE has an undo list. Wherever this doc discusses keys,
C refers to the <kbd class="kbd docutils literal notranslate">Control</kbd> key on Windows and
Unix and the <kbd class="kbd docutils literal notranslate">Command</kbd> key on macOS. (And all such dicussions
assume that the keys have not been re-bound to something else.)</p>
<ul class="simple">
<li><p>Arrow keys move the cursor one character or line.</p></li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">LeftArrow</kbd></kbd> and <kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">RightArrow</kbd></kbd> moves left or right one word.</p></li>
<li><p><kbd class="kbd docutils literal notranslate">Home</kbd> and <kbd class="kbd docutils literal notranslate">End</kbd> go to the beginning or end of the line.</p></li>
<li><p><kbd class="kbd docutils literal notranslate">Page Up</kbd> and <kbd class="kbd docutils literal notranslate">Page Down</kbd> go up or down one screen.</p></li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">Home</kbd></kbd> and <kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">End</kbd></kbd> go to beginning or end of the file.</p></li>
<li><p><kbd class="kbd docutils literal notranslate">Backspace</kbd> and <kbd class="kbd docutils literal notranslate">Del</kbd> (or <cite>C-d</cite>) delete the previous or
next character.</p></li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">Backspace</kbd></kbd> and <kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">Del</kbd></kbd> delete one word left or right.</p></li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">k</kbd></kbd> deletes (kills) everything to the right.</p></li>
</ul>
<p>Standard keybindings (like <kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">c</kbd></kbd> to copy and <kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">v</kbd></kbd> to paste)
may work. Keybindings are selected in the Configure IDLE dialog.</p>
@@ -574,7 +585,7 @@ are restricted to four spaces due to Tcl/Tk limitations.</p>
<h3>Search and Replace<a class="headerlink" href="#search-and-replace" title="Permalink to this heading"></a></h3>
<p>Any selection becomes a search target. However, only selections within
a line work because searches are only performed within lines with the
terminal newline removed. If <code class="docutils literal notranslate"><span class="pre">[x]</span> <span class="pre">Regular</span> <span class="pre">expresion</span></code> is checked, the
terminal newline removed. If <code class="docutils literal notranslate"><span class="pre">[x]</span> <span class="pre">Regular</span> <span class="pre">expression</span></code> is checked, the
target is interpreted according to the Python re module.</p>
</section>
<section id="completions">
@@ -681,20 +692,15 @@ re-started. This occurs when the user execution process has crashed,
when one requests a restart on the Shell menu, or when one runs code
in an editor window.</p>
<p>The editing features described in previous subsections work when entering
code interactively. IDLEs Shell window also responds to the following keys.</p>
<ul>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">c</kbd></kbd> interrupts executing command</p></li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">d</kbd></kbd> sends end-of-file; closes window if typed at a <code class="docutils literal notranslate"><span class="pre">&gt;&gt;&gt;</span></code> prompt</p></li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">Alt</kbd>-<kbd class="kbd docutils literal notranslate">/</kbd></kbd> (Expand word) is also useful to reduce typing</p>
<p>Command history</p>
code interactively. IDLEs Shell window also responds to the following:</p>
<ul class="simple">
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">Alt</kbd>-<kbd class="kbd docutils literal notranslate">p</kbd></kbd> retrieves previous command matching what you have typed. On
macOS use <kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">p</kbd></kbd>.</p></li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">Alt</kbd>-<kbd class="kbd docutils literal notranslate">n</kbd></kbd> retrieves next. On macOS use <kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">n</kbd></kbd>.</p></li>
<li><p><kbd class="kbd docutils literal notranslate">Return</kbd> while the cursor is on any previous command
retrieves that command</p></li>
</ul>
</li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">c</kbd></kbd> attemps to interrupt statement execution (but may fail).</p></li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">d</kbd></kbd> closes Shell if typed at a <code class="docutils literal notranslate"><span class="pre">&gt;&gt;&gt;</span></code> prompt.</p></li>
<li><p><kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">Alt</kbd>-<kbd class="kbd docutils literal notranslate">p</kbd></kbd> and <kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">Alt</kbd>-<kbd class="kbd docutils literal notranslate">n</kbd></kbd> (<kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">p</kbd></kbd> and <kbd class="kbd compound docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">n</kbd></kbd> on macOS)
retrieve to the current prompt the previous or next previously
entered statement that matches anything already typed.</p></li>
<li><p><kbd class="kbd docutils literal notranslate">Return</kbd> while the cursor is on any previous statement
appends the latter to anything already typed at the prompt.</p></li>
</ul>
</section>
<section id="text-colors">
@@ -1077,8 +1083,8 @@ sense that feature changes can be backported (see <span class="target" id="index
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="tkinter.tix.html"
title="previous chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">tkinter.tix</span></code>Extension widgets for Tk</a></p>
<p class="topless"><a href="tkinter.ttk.html"
title="previous chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">tkinter.ttk</span></code>Tk themed widgets</a></p>
</div>
<div>
<h4>Next topic</h4>
@@ -1117,7 +1123,7 @@ sense that feature changes can be backported (see <span class="target" id="index
<a href="development.html" title="Development Tools"
>next</a> |</li>
<li class="right" >
<a href="tkinter.tix.html" title="tkinter.tixExtension widgets for Tk"
<a href="tkinter.ttk.html" title="tkinter.ttkTk themed widgets"
>previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
@@ -1130,7 +1136,7 @@ sense that feature changes can be backported (see <span class="target" id="index
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0a0 Documentation</a> &#187;
<a href="../index.html">3.13.0a2 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> &#187;</li>
@@ -1141,19 +1147,26 @@ sense that feature changes can be backported (see <span class="target" id="index
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="Quick search" aria-label="Quick search" type="text" name="q" />
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" id="search-box" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
|
</li>
<li class="right">
<label class="theme-selector-label">
Theme
<select class="theme-selector" oninput="activateTheme(this.value)">
<option value="auto" selected>Auto</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</label> |</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">Copyright</a> 2001-2022, Python Software Foundation.
&copy; <a href="../copyright.html">Copyright</a> 2001-2024, Python Software Foundation.
<br />
This page is licensed under the Python Software Foundation License Version 2.
<br />
@@ -1167,11 +1180,11 @@ sense that feature changes can be backported (see <span class="target" id="index
<br />
<br />
Last updated on Sep 03, 2022.
Last updated on Jan 17, 2024 (06:57 UTC).
<a href="/bugs.html">Found a bug</a>?
<br />
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 5.0.2.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 7.0.1.
</div>
</body>

View File

@@ -33,6 +33,7 @@ from tkinter.ttk import Frame, Menubutton, Scrollbar, Style
from tkinter import font as tkfont
from idlelib.config import idleConf
from idlelib.colorizer import color_config
## About IDLE ##
@@ -102,7 +103,7 @@ class HelpParser(HTMLParser):
if self.level > 0:
self.nested_dl = True
elif tag == 'li':
s = '\n* ' if self.simplelist else '\n\n* '
s = '\n* '
elif tag == 'dt':
s = '\n\n' if not self.nested_dl else '\n' # Avoid extra line.
self.nested_dl = False
@@ -177,14 +178,16 @@ class HelpText(Text):
normalfont = self.findfont(['TkDefaultFont', 'arial', 'helvetica'])
fixedfont = self.findfont(['TkFixedFont', 'monaco', 'courier'])
color_config(self)
self['font'] = (normalfont, 12)
self.tag_configure('em', font=(normalfont, 12, 'italic'))
self.tag_configure('h1', font=(normalfont, 20, 'bold'))
self.tag_configure('h2', font=(normalfont, 18, 'bold'))
self.tag_configure('h3', font=(normalfont, 15, 'bold'))
self.tag_configure('pre', font=(fixedfont, 12), background='#f6f6ff')
self.tag_configure('pre', font=(fixedfont, 12))
preback = self['selectbackground']
self.tag_configure('preblock', font=(fixedfont, 10), lmargin1=25,
borderwidth=1, relief='solid', background='#eeffcc')
background=preback)
self.tag_configure('l1', lmargin1=25, lmargin2=25)
self.tag_configure('l2', lmargin1=50, lmargin2=50)
self.tag_configure('l3', lmargin1=75, lmargin2=75)
@@ -241,12 +244,13 @@ class HelpWindow(Toplevel):
Toplevel.__init__(self, parent)
self.wm_title(title)
self.protocol("WM_DELETE_WINDOW", self.destroy)
HelpFrame(self, filename).grid(column=0, row=0, sticky='nsew')
self.frame = HelpFrame(self, filename)
self.frame.grid(column=0, row=0, sticky='nsew')
self.grid_columnconfigure(0, weight=1)
self.grid_rowconfigure(0, weight=1)
def copy_strip():
def copy_strip(): # pragma: no cover
"""Copy idle.html to idlelib/help.html, stripping trailing whitespace.
Files with trailing whitespace cannot be pushed to the git cpython
@@ -278,13 +282,15 @@ def copy_strip():
out.write(line.rstrip() + b'\n')
print(f'{src} copied to {dst}')
def show_idlehelp(parent):
"Create HelpWindow; called from Idle Help event handler."
filename = join(abspath(dirname(__file__)), 'help.html')
if not isfile(filename):
if not isfile(filename): # pragma: no cover
# Try copy_strip, present message.
return
HelpWindow(parent, filename, 'IDLE Help (%s)' % python_version())
return HelpWindow(parent, filename, 'IDLE Doc (%s)' % python_version())
if __name__ == '__main__':
from unittest import main

View File

@@ -85,15 +85,18 @@ class AboutDialog(Toplevel):
byline = Label(frame_background, text=byline_text, justify=LEFT,
fg=self.fg, bg=self.bg)
byline.grid(row=2, column=0, sticky=W, columnspan=3, padx=10, pady=5)
email = Label(frame_background, text='email: idle-dev@python.org',
justify=LEFT, fg=self.fg, bg=self.bg)
email.grid(row=6, column=0, columnspan=2, sticky=W, padx=10, pady=0)
forums_url = "https://discuss.python.org"
forums = Label(frame_background, text="Python forums: "+forums_url,
justify=LEFT, fg=self.fg, bg=self.bg)
forums.grid(row=6, column=0, sticky=W, padx=10, pady=0)
forums.bind("<Button-1>", lambda event: webbrowser.open(forums_url))
docs_url = ("https://docs.python.org/%d.%d/library/idle.html" %
sys.version_info[:2])
docs = Label(frame_background, text=docs_url,
justify=LEFT, fg=self.fg, bg=self.bg)
docs.grid(row=7, column=0, columnspan=2, sticky=W, padx=10, pady=0)
docs.bind("<Button-1>", lambda event: webbrowser.open(docs['text']))
docs.bind("<Button-1>", lambda event: webbrowser.open(docs_url))
Frame(frame_background, borderwidth=1, relief=SUNKEN,
height=2, bg=self.bg).grid(row=8, column=0, sticky=EW,
@@ -123,17 +126,15 @@ class AboutDialog(Toplevel):
height=2, bg=self.bg).grid(row=11, column=0, sticky=EW,
columnspan=3, padx=5, pady=5)
idle = Label(frame_background,
text='IDLE',
fg=self.fg, bg=self.bg)
idle = Label(frame_background, text='IDLE', fg=self.fg, bg=self.bg)
idle.grid(row=12, column=0, sticky=W, padx=10, pady=0)
idle_buttons = Frame(frame_background, bg=self.bg)
idle_buttons.grid(row=13, column=0, columnspan=3, sticky=NSEW)
self.readme = Button(idle_buttons, text='README', width=8,
self.readme = Button(idle_buttons, text='Readme', width=8,
highlightbackground=self.bg,
command=self.show_readme)
self.readme.pack(side=LEFT, padx=10, pady=10)
self.idle_news = Button(idle_buttons, text='NEWS', width=8,
self.idle_news = Button(idle_buttons, text='News', width=8,
highlightbackground=self.bg,
command=self.show_idle_news)
self.idle_news.pack(side=LEFT, padx=10, pady=10)
@@ -167,7 +168,7 @@ class AboutDialog(Toplevel):
def show_idle_news(self):
"Handle News button event."
self.display_file_text('About - NEWS', 'NEWS.txt', 'utf-8')
self.display_file_text('About - News', 'News3.txt', 'utf-8')
def display_printer_text(self, title, printer):
"""Create textview for built-in constants.

Some files were not shown because too many files have changed in this diff Show More