Mercurial > cpython-lru_cache-weakref
annotate Mac/Tools/IDE/PyConsole.py @ 25838:8540887bcec6 2.2
Backport of 2.183:
Fix memory leak in add_subclass() found by NealN with valgrind.
| author | Guido van Rossum <guido@python.org> |
|---|---|
| date | Fri, 18 Oct 2002 13:42:21 +0000 |
| parents | 99341e85017e |
| children |
| rev | line source |
|---|---|
| 10047 | 1 import W |
| 2 import Wkeys | |
|
19488
42b2f1936254
Import the MacOS toolbox modules from the Carbon package.
Jack Jansen <jack.jansen@cwi.nl>
parents:
19009
diff
changeset
|
3 from Carbon import Fm |
| 10047 | 4 import WASTEconst |
| 5 from types import * | |
|
19488
42b2f1936254
Import the MacOS toolbox modules from the Carbon package.
Jack Jansen <jack.jansen@cwi.nl>
parents:
19009
diff
changeset
|
6 from Carbon import Events |
| 10047 | 7 import string |
| 8 import sys | |
| 9 import traceback | |
| 10 import MacOS | |
| 11 import MacPrefs | |
|
19488
42b2f1936254
Import the MacOS toolbox modules from the Carbon package.
Jack Jansen <jack.jansen@cwi.nl>
parents:
19009
diff
changeset
|
12 from Carbon import Qd |
| 10047 | 13 import PyInteractive |
| 14 | |
| 15 if not hasattr(sys, 'ps1'): | |
| 16 sys.ps1 = '>>> ' | |
| 17 if not hasattr(sys, 'ps2'): | |
| 18 sys.ps2 = '... ' | |
| 19 | |
| 20 def inspect(foo): # JJS 1/25/99 | |
| 21 "Launch the browser on the given object. This is a general built-in function." | |
| 22 import PyBrowser | |
| 23 PyBrowser.Browser(foo) | |
| 24 | |
| 25 class ConsoleTextWidget(W.EditText): | |
| 26 | |
| 27 def __init__(self, *args, **kwargs): | |
| 28 apply(W.EditText.__init__, (self,) + args, kwargs) | |
| 29 self._inputstart = 0 | |
| 30 self._buf = '' | |
| 31 self.pyinteractive = PyInteractive.PyInteractive() | |
| 32 | |
| 33 import __main__ | |
| 34 self._namespace = __main__.__dict__ | |
| 35 self._namespace['inspect'] = inspect # JJS 1/25/99 | |
| 36 | |
| 37 def insert(self, text): | |
| 38 self.checkselection() | |
| 39 self.ted.WEInsert(text, None, None) | |
| 40 self.changed = 1 | |
| 41 self.selchanged = 1 | |
| 42 | |
| 43 def set_namespace(self, dict): | |
| 44 if type(dict) <> DictionaryType: | |
| 45 raise TypeError, "The namespace needs to be a dictionary" | |
| 46 if 'inspect' not in dict.keys(): dict['inspect'] = inspect # JJS 1/25/99 | |
| 47 self._namespace = dict | |
| 48 | |
| 49 def open(self): | |
|
19009
1bc67cf57d0a
Show the MacPython IDE version in the interactive banner.
Just van Rossum <just@letterror.com>
parents:
18167
diff
changeset
|
50 import __main__ |
| 10047 | 51 W.EditText.open(self) |
|
19009
1bc67cf57d0a
Show the MacPython IDE version in the interactive banner.
Just van Rossum <just@letterror.com>
parents:
18167
diff
changeset
|
52 self.write('Python %s\n' % sys.version) |
|
1bc67cf57d0a
Show the MacPython IDE version in the interactive banner.
Just van Rossum <just@letterror.com>
parents:
18167
diff
changeset
|
53 self.write('Type "copyright", "credits" or "license" for more information.\n') |
|
1bc67cf57d0a
Show the MacPython IDE version in the interactive banner.
Just van Rossum <just@letterror.com>
parents:
18167
diff
changeset
|
54 self.write('MacPython IDE %s\n' % __main__.__version__) |
| 10047 | 55 self.write(sys.ps1) |
| 56 self.flush() | |
| 57 | |
| 58 def key(self, char, event): | |
| 59 (what, message, when, where, modifiers) = event | |
| 60 if self._enabled and not modifiers & Events.cmdKey or char in Wkeys.arrowkeys: | |
| 61 if char not in Wkeys.navigationkeys: | |
| 62 self.checkselection() | |
| 63 if char == Wkeys.enterkey: | |
| 64 char = Wkeys.returnkey | |
| 65 selstart, selend = self.getselection() | |
| 66 if char == Wkeys.backspacekey: | |
| 67 if selstart <= (self._inputstart - (selstart <> selend)): | |
| 68 return | |
| 69 self.ted.WEKey(ord(char), modifiers) | |
| 70 if char not in Wkeys.navigationkeys: | |
| 71 self.changed = 1 | |
| 72 if char not in Wkeys.scrollkeys: | |
| 73 self.selchanged = 1 | |
| 74 self.updatescrollbars() | |
| 75 if char == Wkeys.returnkey: | |
| 76 text = self.get()[self._inputstart:selstart] | |
| 77 text = string.join(string.split(text, "\r"), "\n") | |
| 22030 | 78 if hasattr(MacOS, 'EnableAppswitch'): |
| 79 saveyield = MacOS.EnableAppswitch(0) | |
| 10047 | 80 self.pyinteractive.executeline(text, self, self._namespace) |
| 22030 | 81 if hasattr(MacOS, 'EnableAppswitch'): |
| 82 MacOS.EnableAppswitch(saveyield) | |
| 10047 | 83 selstart, selend = self.getselection() |
| 84 self._inputstart = selstart | |
| 85 | |
| 86 def domenu_save_as(self, *args): | |
| 87 import macfs | |
| 88 fss, ok = macfs.StandardPutFile('Save console text as:', 'console.txt') | |
| 89 if not ok: | |
| 90 return | |
| 91 f = open(fss.as_pathname(), 'wb') | |
| 92 f.write(self.get()) | |
| 93 f.close() | |
| 94 fss.SetCreatorType(W._signature, 'TEXT') | |
| 95 | |
| 96 def write(self, text): | |
| 97 self._buf = self._buf + text | |
| 98 if '\n' in self._buf: | |
| 99 self.flush() | |
| 100 | |
| 101 def flush(self): | |
| 102 stuff = string.split(self._buf, '\n') | |
| 103 stuff = string.join(stuff, '\r') | |
| 104 self.setselection_at_end() | |
| 105 self.ted.WEInsert(stuff, None, None) | |
| 106 selstart, selend = self.getselection() | |
| 107 self._inputstart = selstart | |
| 108 self._buf = "" | |
| 109 self.ted.WEClearUndo() | |
| 110 self.updatescrollbars() | |
| 22030 | 111 if Qd.QDIsPortBuffered(self._parentwindow.wid): |
| 112 Qd.QDFlushPortBuffer(self._parentwindow.wid, None) | |
| 10047 | 113 |
| 114 def selection_ok(self): | |
| 115 selstart, selend = self.getselection() | |
| 116 return not (selstart < self._inputstart or selend < self._inputstart) | |
| 117 | |
| 118 def checkselection(self): | |
| 119 if not self.selection_ok(): | |
| 120 self.setselection_at_end() | |
| 121 | |
| 122 def setselection_at_end(self): | |
| 123 end = self.ted.WEGetTextLength() | |
| 124 self.setselection(end, end) | |
| 125 self.updatescrollbars() | |
| 126 | |
| 127 def domenu_cut(self, *args): | |
| 128 if not self.selection_ok(): | |
| 129 return | |
| 130 W.EditText.domenu_cut(self) | |
| 131 | |
| 132 def domenu_paste(self, *args): | |
| 133 if not self.selection_ok(): | |
| 134 self.setselection_at_end() | |
| 135 W.EditText.domenu_paste(self) | |
| 136 | |
| 137 def domenu_clear(self, *args): | |
| 138 if not self.selection_ok(): | |
| 139 return | |
| 140 W.EditText.domenu_clear(self) | |
| 141 | |
| 142 | |
| 143 class PyConsole(W.Window): | |
| 144 | |
| 145 def __init__(self, bounds, show = 1, fontsettings = ("Monaco", 0, 9, (0, 0, 0)), | |
| 146 tabsettings = (32, 0), unclosable = 0): | |
| 147 W.Window.__init__(self, | |
| 148 bounds, | |
| 149 "Python Interactive", | |
| 150 minsize = (200, 100), | |
| 151 tabbable = 0, | |
| 152 show = show) | |
| 153 | |
| 154 self._unclosable = unclosable | |
| 155 consoletext = ConsoleTextWidget((-1, -1, -14, 1), inset = (6, 5), | |
| 156 fontsettings = fontsettings, tabsettings = tabsettings) | |
| 157 self._bary = W.Scrollbar((-15, 14, 16, -14), consoletext.vscroll, max = 32767) | |
| 158 self.consoletext = consoletext | |
| 159 self.namespacemenu = W.PopupMenu((-15, -1, 16, 16), [], self.consoletext.set_namespace) | |
| 160 self.namespacemenu.bind('<click>', self.makenamespacemenu) | |
| 161 self.open() | |
| 162 | |
| 163 def makenamespacemenu(self, *args): | |
| 164 W.SetCursor('watch') | |
| 165 namespacelist = self.getnamespacelist() | |
|
18167
c5ac6f055c62
Some long overdue maintainance. Made all IDE sources 7-bit-clean, to avoid any further encoding conversion troubles.
Just van Rossum <just@letterror.com>
parents:
17972
diff
changeset
|
166 self.namespacemenu.set([("Clear window", self.clearbuffer), ("Font settings\xc9", self.dofontsettings), |
|
c5ac6f055c62
Some long overdue maintainance. Made all IDE sources 7-bit-clean, to avoid any further encoding conversion troubles.
Just van Rossum <just@letterror.com>
parents:
17972
diff
changeset
|
167 ["Namespace"] + namespacelist, ("Browse namespace\xc9", self.browsenamespace)]) |
| 10047 | 168 currentname = self.consoletext._namespace["__name__"] |
| 169 for i in range(len(namespacelist)): | |
| 170 if namespacelist[i][0] == currentname: | |
| 171 break | |
| 172 else: | |
| 173 return | |
| 174 # XXX this functionality should be generally available in Wmenus | |
| 175 submenuid = self.namespacemenu.menu.menu.GetItemMark(3) | |
| 176 menu = self.namespacemenu.menu.bar.menus[submenuid] | |
|
16336
2d8e02902d67
Replace {Enable,Disable,Check}Item with their carbon-compatible equivalents {Enable,Disable,Check}MenuItem.
Jack Jansen <jack.jansen@cwi.nl>
parents:
10087
diff
changeset
|
177 menu.menu.CheckMenuItem(i + 1, 1) |
| 10047 | 178 |
| 179 def browsenamespace(self): | |
| 180 import PyBrowser, W | |
| 181 W.SetCursor('watch') | |
| 182 PyBrowser.Browser(self.consoletext._namespace, self.consoletext._namespace["__name__"]) | |
| 183 | |
| 184 def clearbuffer(self): | |
|
19488
42b2f1936254
Import the MacOS toolbox modules from the Carbon package.
Jack Jansen <jack.jansen@cwi.nl>
parents:
19009
diff
changeset
|
185 from Carbon import Res |
| 10047 | 186 self.consoletext.ted.WEUseText(Res.Resource('')) |
| 187 self.consoletext.write(sys.ps1) | |
| 188 self.consoletext.flush() | |
| 189 | |
| 190 def getnamespacelist(self): | |
| 191 import os | |
| 192 import __main__ | |
| 193 editors = filter(lambda x: x.__class__.__name__ == "Editor", self.parent._windows.values()) | |
| 194 | |
| 195 namespaces = [ ("__main__",__main__.__dict__) ] | |
| 196 for ed in editors: | |
| 197 modname = os.path.splitext(ed.title)[0] | |
| 198 if sys.modules.has_key(modname): | |
| 199 module = sys.modules[modname] | |
| 200 namespaces.append((modname, module.__dict__)) | |
| 201 else: | |
| 202 if ed.title[-3:] == '.py': | |
| 203 modname = ed.title[:-3] | |
| 204 else: | |
| 205 modname = ed.title | |
| 206 ed.globals["__name__"] = modname | |
| 207 namespaces.append((modname, ed.globals)) | |
| 208 return namespaces | |
| 209 | |
| 210 def dofontsettings(self): | |
| 211 import FontSettings | |
| 212 settings = FontSettings.FontDialog(self.consoletext.getfontsettings(), | |
| 213 self.consoletext.gettabsettings()) | |
| 214 if settings: | |
| 215 fontsettings, tabsettings = settings | |
| 216 self.consoletext.setfontsettings(fontsettings) | |
| 217 self.consoletext.settabsettings(tabsettings) | |
| 218 | |
| 219 def show(self, onoff = 1): | |
| 220 W.Window.show(self, onoff) | |
| 221 if onoff: | |
| 222 self.select() | |
| 223 | |
| 224 def close(self): | |
| 225 if self._unclosable: | |
| 226 self.show(0) | |
| 227 return -1 | |
| 228 W.Window.close(self) | |
| 229 | |
| 230 def writeprefs(self): | |
| 231 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath) | |
| 232 prefs.console.show = self.isvisible() | |
| 233 prefs.console.windowbounds = self.getbounds() | |
| 234 prefs.console.fontsettings = self.consoletext.getfontsettings() | |
| 235 prefs.console.tabsettings = self.consoletext.gettabsettings() | |
| 236 prefs.save() | |
| 237 | |
| 238 | |
| 239 class OutputTextWidget(W.EditText): | |
| 240 | |
| 241 def domenu_save_as(self, *args): | |
| 242 title = self._parentwindow.gettitle() | |
| 243 import macfs | |
| 244 fss, ok = macfs.StandardPutFile('Save %s text as:' % title, title + '.txt') | |
| 245 if not ok: | |
| 246 return | |
| 247 f = open(fss.as_pathname(), 'wb') | |
| 248 f.write(self.get()) | |
| 249 f.close() | |
| 250 fss.SetCreatorType(W._signature, 'TEXT') | |
| 251 | |
| 252 | |
| 253 class PyOutput: | |
| 254 | |
| 255 def __init__(self, bounds, show = 1, fontsettings = ("Monaco", 0, 9, (0, 0, 0)), tabsettings = (32, 0)): | |
| 256 self.bounds = bounds | |
| 257 self.fontsettings = fontsettings | |
| 258 self.tabsettings = tabsettings | |
| 259 self.w = None | |
| 260 self.closed = 1 | |
| 261 self._buf = '' | |
| 262 # should be able to set this | |
| 263 self.savestdout, self.savestderr = sys.stdout, sys.stderr | |
| 264 sys.stderr = sys.stdout = self | |
| 265 if show: | |
| 266 self.show() | |
| 267 | |
| 268 def setupwidgets(self): | |
| 269 self.w = W.Window(self.bounds, "Output", | |
| 270 minsize = (200, 100), | |
| 271 tabbable = 0) | |
| 272 self.w.outputtext = OutputTextWidget((-1, -1, -14, 1), inset = (6, 5), | |
| 273 fontsettings = self.fontsettings, tabsettings = self.tabsettings, readonly = 1) | |
|
18167
c5ac6f055c62
Some long overdue maintainance. Made all IDE sources 7-bit-clean, to avoid any further encoding conversion troubles.
Just van Rossum <just@letterror.com>
parents:
17972
diff
changeset
|
274 menuitems = [("Clear window", self.clearbuffer), ("Font settings\xc9", self.dofontsettings)] |
| 10047 | 275 self.w.popupmenu = W.PopupMenu((-15, -1, 16, 16), menuitems) |
| 276 | |
| 277 self.w._bary = W.Scrollbar((-15, 14, 16, -14), self.w.outputtext.vscroll, max = 32767) | |
| 278 self.w.bind("<close>", self.close) | |
| 279 self.w.bind("<activate>", self.activate) | |
| 280 | |
| 281 def write(self, text): | |
| 22030 | 282 if hasattr(MacOS, 'EnableAppswitch'): |
| 283 oldyield = MacOS.EnableAppswitch(-1) | |
| 10047 | 284 try: |
| 285 self._buf = self._buf + text | |
| 286 if '\n' in self._buf: | |
| 287 self.flush() | |
| 288 finally: | |
| 22030 | 289 if hasattr(MacOS, 'EnableAppswitch'): |
| 290 MacOS.EnableAppswitch(oldyield) | |
| 10047 | 291 |
| 292 def flush(self): | |
| 293 self.show() | |
| 294 stuff = string.split(self._buf, '\n') | |
| 295 stuff = string.join(stuff, '\r') | |
| 296 end = self.w.outputtext.ted.WEGetTextLength() | |
| 297 self.w.outputtext.setselection(end, end) | |
| 298 self.w.outputtext.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 0) | |
| 299 self.w.outputtext.ted.WEInsert(stuff, None, None) | |
| 300 self._buf = "" | |
| 301 self.w.outputtext.updatescrollbars() | |
| 302 self.w.outputtext.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 1) | |
| 22030 | 303 if Qd.QDIsPortBuffered(self.w.wid): |
| 304 Qd.QDFlushPortBuffer(self.w.wid, None) | |
| 10047 | 305 |
| 306 def show(self): | |
| 307 if self.closed: | |
| 308 if not self.w: | |
| 309 self.setupwidgets() | |
| 310 self.w.open() | |
| 311 self.w.outputtext.updatescrollbars() | |
| 312 self.closed = 0 | |
| 313 else: | |
| 314 self.w.show(1) | |
| 315 self.closed = 0 | |
| 316 self.w.select() | |
| 317 | |
| 318 def writeprefs(self): | |
| 319 if self.w is not None: | |
| 320 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath) | |
| 321 prefs.output.show = self.w.isvisible() | |
| 322 prefs.output.windowbounds = self.w.getbounds() | |
| 323 prefs.output.fontsettings = self.w.outputtext.getfontsettings() | |
| 324 prefs.output.tabsettings = self.w.outputtext.gettabsettings() | |
| 325 prefs.save() | |
| 326 | |
| 327 def dofontsettings(self): | |
| 328 import FontSettings | |
| 329 settings = FontSettings.FontDialog(self.w.outputtext.getfontsettings(), | |
| 330 self.w.outputtext.gettabsettings()) | |
| 331 if settings: | |
| 332 fontsettings, tabsettings = settings | |
| 333 self.w.outputtext.setfontsettings(fontsettings) | |
| 334 self.w.outputtext.settabsettings(tabsettings) | |
| 335 | |
| 336 def clearbuffer(self): | |
|
19488
42b2f1936254
Import the MacOS toolbox modules from the Carbon package.
Jack Jansen <jack.jansen@cwi.nl>
parents:
19009
diff
changeset
|
337 from Carbon import Res |
| 10047 | 338 self.w.outputtext.set('') |
| 339 | |
| 340 def activate(self, onoff): | |
| 341 if onoff: | |
| 342 self.closed = 0 | |
| 343 | |
| 344 def close(self): | |
| 345 self.w.show(0) | |
| 346 self.closed = 1 | |
| 347 return -1 | |
| 348 | |
| 349 | |
| 350 class SimpleStdin: | |
| 351 | |
| 352 def readline(self): | |
| 353 import EasyDialogs | |
|
17972
401ccfcf28c3
When reading from stdin (with the dialog box) use any partial line on
Jack Jansen <jack.jansen@cwi.nl>
parents:
17845
diff
changeset
|
354 # A trick to make the input dialog box a bit more palatable |
|
401ccfcf28c3
When reading from stdin (with the dialog box) use any partial line on
Jack Jansen <jack.jansen@cwi.nl>
parents:
17845
diff
changeset
|
355 if hasattr(sys.stdout, '_buf'): |
|
401ccfcf28c3
When reading from stdin (with the dialog box) use any partial line on
Jack Jansen <jack.jansen@cwi.nl>
parents:
17845
diff
changeset
|
356 prompt = sys.stdout._buf |
|
401ccfcf28c3
When reading from stdin (with the dialog box) use any partial line on
Jack Jansen <jack.jansen@cwi.nl>
parents:
17845
diff
changeset
|
357 else: |
|
401ccfcf28c3
When reading from stdin (with the dialog box) use any partial line on
Jack Jansen <jack.jansen@cwi.nl>
parents:
17845
diff
changeset
|
358 prompt = "" |
|
401ccfcf28c3
When reading from stdin (with the dialog box) use any partial line on
Jack Jansen <jack.jansen@cwi.nl>
parents:
17845
diff
changeset
|
359 if not prompt: |
|
401ccfcf28c3
When reading from stdin (with the dialog box) use any partial line on
Jack Jansen <jack.jansen@cwi.nl>
parents:
17845
diff
changeset
|
360 prompt = "Stdin input:" |
| 10047 | 361 sys.stdout.flush() |
|
17972
401ccfcf28c3
When reading from stdin (with the dialog box) use any partial line on
Jack Jansen <jack.jansen@cwi.nl>
parents:
17845
diff
changeset
|
362 rv = EasyDialogs.AskString(prompt) |
| 10047 | 363 if rv is None: |
| 364 return "" | |
| 22030 | 365 rv = rv + "\n" # readline should include line terminator |
| 366 sys.stdout.write(rv) # echo user's reply | |
| 367 return rv | |
| 10047 | 368 |
| 369 | |
| 370 def installconsole(defaultshow = 1): | |
| 371 global console | |
| 372 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath) | |
| 373 if not prefs.console or not hasattr(prefs.console, 'show'): | |
| 374 prefs.console.show = defaultshow | |
| 375 if not hasattr(prefs.console, "windowbounds"): | |
| 376 prefs.console.windowbounds = (450, 250) | |
| 377 if not hasattr(prefs.console, "fontsettings"): | |
| 378 prefs.console.fontsettings = ("Monaco", 0, 9, (0, 0, 0)) | |
| 379 if not hasattr(prefs.console, "tabsettings"): | |
| 380 prefs.console.tabsettings = (32, 0) | |
| 381 console = PyConsole(prefs.console.windowbounds, prefs.console.show, | |
| 382 prefs.console.fontsettings, prefs.console.tabsettings, 1) | |
| 383 | |
| 384 def installoutput(defaultshow = 0, OutPutWindow = PyOutput): | |
| 385 global output | |
| 386 | |
| 387 # quick 'n' dirty std in emulation | |
| 388 sys.stdin = SimpleStdin() | |
| 389 | |
| 390 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath) | |
| 391 if not prefs.output or not hasattr(prefs.output, 'show'): | |
| 392 prefs.output.show = defaultshow | |
| 393 if not hasattr(prefs.output, "windowbounds"): | |
| 394 prefs.output.windowbounds = (450, 250) | |
| 395 if not hasattr(prefs.output, "fontsettings"): | |
| 396 prefs.output.fontsettings = ("Monaco", 0, 9, (0, 0, 0)) | |
| 397 if not hasattr(prefs.output, "tabsettings"): | |
| 398 prefs.output.tabsettings = (32, 0) | |
| 399 output = OutPutWindow(prefs.output.windowbounds, prefs.output.show, | |
| 400 prefs.output.fontsettings, prefs.output.tabsettings) |
