1616import marshal
1717import regex
1818
19+ try :
20+ # experimental microthread support
21+ import uthread2
22+ except ImportError :
23+ uthread2 = None
24+
1925_scriptuntitledcounter = 1
2026_wordchars = string .letters + string .digits + "_"
2127
2228
29+ runButtonLabels = ["Run all" , "Stop!" ]
30+ runSelButtonLabels = ["Run selection" , "Pause!" , "Resume" ]
31+
32+
2333class Editor (W .Window ):
2434
2535 def __init__ (self , path = "" , title = "" ):
@@ -54,7 +64,8 @@ def __init__(self, path = "", title = ""):
5464 else :
5565 sourceOS = 'UNIX'
5666 searchString = '\n '
57- change = EasyDialogs .AskYesNoCancel ('³%s² contains %s-style line feeds. Change them to MacOS carriage returns?' % (self .title , sourceOS ), 1 )
67+ change = EasyDialogs .AskYesNoCancel ('³%s² contains %s-style line feeds. '
68+ 'Change them to MacOS carriage returns?' % (self .title , sourceOS ), 1 )
5869 # bug: Cancel is treated as No
5970 if change > 0 :
6071 text = string .replace (text , searchString , '\r ' )
@@ -98,6 +109,8 @@ def __init__(self, path = "", title = ""):
98109 self .run_as_main = self .settings ["run_as_main" ]
99110 else :
100111 self .run_as_main = 0
112+ self ._threadstate = (0 , 0 )
113+ self ._thread = None
101114
102115 def readwindowsettings (self ):
103116 try :
@@ -178,8 +191,8 @@ def setupwidgets(self, text):
178191 self .bevelbox = W .BevelBox ((0 , 0 , 0 , topbarheight ))
179192 self .hline = W .HorizontalLine ((0 , topbarheight , 0 , 0 ))
180193 self .infotext = W .TextBox ((175 , 6 , - 4 , 14 ), backgroundcolor = (0xe000 , 0xe000 , 0xe000 ))
181- self .runbutton = W .Button ((5 , 4 , 80 , 16 ), "Run all" , self .run )
182- self .runselbutton = W .Button ((90 , 4 , 80 , 16 ), "Run selection" , self .runselection )
194+ self .runbutton = W .Button ((5 , 4 , 80 , 16 ), runButtonLabels [ 0 ] , self .run )
195+ self .runselbutton = W .Button ((90 , 4 , 80 , 16 ), runSelButtonLabels [ 0 ] , self .runselection )
183196
184197 # bind some keys
185198 editor .bind ("cmdr" , self .runbutton .push )
@@ -460,15 +473,29 @@ def domenu_runselection(self, *args):
460473 self .runselbutton .push ()
461474
462475 def run (self ):
463- self ._run ()
476+ if self ._threadstate == (0 , 0 ):
477+ self ._run ()
478+ else :
479+ uthread2 .globalLock ()
480+ self ._thread .raiseException (KeyboardInterrupt )
481+ if self ._thread .isPaused ():
482+ self ._thread .start ()
483+ uthread2 .globalUnlock ()
464484
465485 def _run (self ):
466486 pytext = self .editgroup .editor .get ()
467487 globals , file , modname = self .getenvironment ()
468488 self .execstring (pytext , globals , globals , file , modname )
469489
470490 def runselection (self ):
471- self ._runselection ()
491+ if self ._threadstate == (0 , 0 ):
492+ self ._runselection ()
493+ elif self ._threadstate == (1 , 1 ):
494+ self ._thread .pause ()
495+ self .setthreadstate ((1 , 2 ))
496+ elif self ._threadstate == (1 , 2 ):
497+ self ._thread .start ()
498+ self .setthreadstate ((1 , 1 ))
472499
473500 def _runselection (self ):
474501 globals , file , modname = self .getenvironment ()
@@ -517,6 +544,19 @@ def _runselection(self):
517544 pytext = selfirstline * '\r ' + pytext
518545 self .execstring (pytext , globals , locals , file , modname )
519546
547+ def setthreadstate (self , state ):
548+ oldstate = self ._threadstate
549+ if oldstate [0 ] <> state [0 ]:
550+ self .runbutton .settitle (runButtonLabels [state [0 ]])
551+ if oldstate [1 ] <> state [1 ]:
552+ self .runselbutton .settitle (runSelButtonLabels [state [1 ]])
553+ self ._threadstate = state
554+
555+ def _exec_threadwrapper (self , * args , ** kwargs ):
556+ apply (execstring , args , kwargs )
557+ self .setthreadstate ((0 , 0 ))
558+ self ._thread = None
559+
520560 def execstring (self , pytext , globals , locals , file , modname ):
521561 tracebackwindow .hide ()
522562 # update windows
@@ -531,8 +571,15 @@ def execstring(self, pytext, globals, locals, file, modname):
531571 else :
532572 cwdindex = None
533573 try :
534- execstring (pytext , globals , locals , file , self .debugging ,
535- modname , self .profiling )
574+ if uthread2 and uthread2 .currentThread () is not None :
575+ self ._thread = uthread2 .Thread (file ,
576+ self ._exec_threadwrapper , pytext , globals , locals , file , self .debugging ,
577+ modname , self .profiling )
578+ self .setthreadstate ((1 , 1 ))
579+ self ._thread .start ()
580+ else :
581+ execstring (pytext , globals , locals , file , self .debugging ,
582+ modname , self .profiling )
536583 finally :
537584 if self .path :
538585 os .chdir (savedir )
@@ -561,6 +608,7 @@ def getenvironment(self):
561608 self .globals = {}
562609 else :
563610 globals = self .globals
611+ modname = subname
564612 else :
565613 file = '<%s>' % self .title
566614 globals = self .globals
@@ -1034,8 +1082,13 @@ def execstring(pytext, globals, locals, filename="<string>", debugging=0,
10341082 return
10351083 try :
10361084 if debugging :
1037- PyDebugger .startfromhere ()
1038- else :
1085+ if uthread2 :
1086+ uthread2 .globalLock ()
1087+ PyDebugger .startfromhere ()
1088+ uthread2 .globalUnlock ()
1089+ else :
1090+ PyDebugger .startfromhere ()
1091+ elif not uthread2 :
10391092 MacOS .EnableAppswitch (0 )
10401093 try :
10411094 if profiling :
@@ -1052,18 +1105,23 @@ def execstring(pytext, globals, locals, filename="<string>", debugging=0,
10521105 else :
10531106 exec code in globals , locals
10541107 finally :
1055- MacOS .EnableAppswitch (- 1 )
1108+ if not uthread2 :
1109+ MacOS .EnableAppswitch (- 1 )
10561110 except W .AlertError , detail :
10571111 raise W .AlertError , detail
10581112 except (KeyboardInterrupt , BdbQuit ):
10591113 pass
10601114 except :
1115+ if uthread2 :
1116+ uthread2 .globalLock ()
10611117 if debugging :
10621118 sys .settrace (None )
10631119 PyDebugger .postmortem (sys .exc_type , sys .exc_value , sys .exc_traceback )
10641120 return
10651121 else :
10661122 tracebackwindow .traceback (1 , filename )
1123+ if not uthread2 :
1124+ uthread2 .globalUnlock ()
10671125 if debugging :
10681126 sys .settrace (None )
10691127 PyDebugger .stop ()
0 commit comments