Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2e54cbb

Browse files
threads -> greenlets
also fixed ctrl-c during raw_input bug--HG--branch : scroll-frontend
1 parent1934a83 commit2e54cbb

File tree

4 files changed

+48
-61
lines changed

4 files changed

+48
-61
lines changed

‎bpython/curtsiesfrontend/coderunner.py‎

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
importcode
2-
importQueue
32
importsignal
43
importsys
5-
importthreading
4+
importgreenlet
65
importlogging
76

87
classSigintHappened(object):
@@ -16,54 +15,51 @@ class CodeRunner(object):
1615
def__init__(self,interp=None,stuff_a_refresh_request=lambda:None):
1716
self.interp=interporcode.InteractiveInterpreter()
1817
self.source=None
19-
self.code_thread=None
20-
self.requests_from_code_thread=Queue.Queue(maxsize=1)
21-
self.responses_for_code_thread=Queue.Queue(maxsize=1)
18+
self.main_greenlet=greenlet.getcurrent()
19+
self.code_greenlet=None
2220
self.stuff_a_refresh_request=stuff_a_refresh_request
2321
self.code_is_waiting=False
2422
self.sigint_happened=False
2523
self.orig_sigint_handler=None
2624

2725
@property
2826
defrunning(self):
29-
returnself.sourceandself.code_thread
27+
returnself.sourceandself.code_greenlet
3028

3129
defload_code(self,source):
3230
"""Prep code to be run"""
3331
self.source=source
34-
self.code_thread=None
32+
self.code_greenlet=None
3533

3634
def_unload_code(self):
3735
"""Called when done running code"""
3836
self.source=None
39-
self.code_thread=None
37+
self.code_greenlet=None
4038
self.code_is_waiting=False
4139

4240
defrun_code(self,for_code=None):
4341
"""Returns Truthy values if code finishes, False otherwise
4442
45-
if for_code is provided, send that value to the codethread
43+
if for_code is provided, send that value to the codegreenlet
4644
if source code is complete, returns "done"
4745
if source code is incomplete, returns "unfinished"
4846
"""
49-
ifself.code_threadisNone:
47+
ifself.code_greenletisNone:
5048
assertself.sourceisnotNone
51-
self.code_thread=threading.Thread(target=self._blocking_run_code,name='codethread')
52-
self.code_thread.daemon=True
49+
self.code_greenlet=greenlet.greenlet(self._blocking_run_code)
5350
self.orig_sigint_handler=signal.getsignal(signal.SIGINT)
5451
signal.signal(signal.SIGINT,self.sigint_handler)
55-
self.code_thread.start()
52+
request=self.code_greenlet.switch()
5653
else:
5754
assertself.code_is_waiting
5855
self.code_is_waiting=False
5956
signal.signal(signal.SIGINT,self.sigint_handler)
6057
ifself.sigint_happened:
6158
self.sigint_happened=False
62-
self.responses_for_code_thread.put(SigintHappened)
59+
request=self.code_greenlet.switch(SigintHappened)
6360
else:
64-
self.responses_for_code_thread.put(for_code)
61+
request=self.code_greenlet.switch(for_code)
6562

66-
request=self.requests_from_code_thread.get()
6763
ifrequestin ['wait','refresh']:
6864
self.code_is_waiting=True
6965
ifrequest=='refresh':
@@ -78,10 +74,10 @@ def run_code(self, for_code=None):
7874
self._unload_code()
7975
raiseSystemExitFromCodeThread()
8076
else:
81-
raiseValueError("Not a validrequest_from_code_threadvalue: %r"%request)
77+
raiseValueError("Not a valid value from code greenlet: %r"%request)
8278

8379
defsigint_handler(self,*args):
84-
ifthreading.current_thread()isself.code_thread:
80+
ifgreenlet.getcurrent()isself.code_greenlet:
8581
logging.debug('sigint while running user code!')
8682
raiseKeyboardInterrupt()
8783
else:
@@ -92,25 +88,22 @@ def _blocking_run_code(self):
9288
try:
9389
unfinished=self.interp.runsource(self.source)
9490
exceptSystemExit:
95-
self.requests_from_code_thread.put('SystemExit')
96-
return
97-
self.requests_from_code_thread.put('unfinished'ifunfinishedelse'done')
91+
return'SystemExit'
92+
return'unfinished'ifunfinishedelse'done'
9893

9994
defwait_and_get_value(self):
10095
"""Return the argument passed in to .run_code(for_code)
10196
10297
Nothing means calls to run_code must be...
10398
"""
104-
self.requests_from_code_thread.put('wait')
105-
value=self.responses_for_code_thread.get()
99+
value=self.main_greenlet.switch('wait')
106100
ifvalueisSigintHappened:
107101
raiseKeyboardInterrupt()
108102
returnvalue
109103

110104
defrefresh_and_get_value(self):
111105
"""Returns the argument passed in to .run_code(for_code) """
112-
self.requests_from_code_thread.put('refresh')
113-
value=self.responses_for_code_thread.get()
106+
value=self.main_greenlet.switch('refresh')
114107
ifvalueisSigintHappened:
115108
raiseKeyboardInterrupt()
116109
returnvalue

‎bpython/curtsiesfrontend/interaction.py‎

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
importQueue
1+
importgreenlet
22
importtime
33

44
frombpython.replimportInteractionasBpythonInteraction
@@ -28,8 +28,8 @@ def __init__(self, initial_message='', permanent_text=""):
2828
self.message_start_time=time.time()
2929
self.message_time=3
3030
self.permanent_text=permanent_text
31-
self.response_queue=Queue.Queue(maxsize=1)
32-
self.request_or_notify_queue=Queue.Queue()
31+
self.main_greenlet=greenlet.getcurrent()
32+
self.request_greenlet=None
3333

3434
@property
3535
defhas_focus(self):
@@ -53,16 +53,17 @@ def process_event(self, e):
5353
elife=="":
5454
raiseSystemExit()
5555
elifself.in_promptandein ("\n","\r"):
56-
self.response_queue.put(self._current_line)
56+
line=self._current_line
5757
self.escape()
58+
self.main_greenlet_switch(line)
5859
elifself.in_confirm:
5960
ifein ('y','Y'):
60-
self.response_queue.put(True)
61+
self.request_greenlet.switch(True)
6162
else:
62-
self.response_queue.put(False)
63+
self.request_greenlet.switch(False)
6364
self.escape()
6465
elifein ['\x1b','\t','\x1b\t','\x1b\x1b']:
65-
self.response_queue.put(False)
66+
self.request_greenlet.switch(False)
6667
self.escape()
6768
else:# add normal character
6869
self._current_line= (self._current_line[:self.cursor_offset_in_line]+
@@ -72,7 +73,6 @@ def process_event(self, e):
7273

7374
defescape(self):
7475
"""unfocus from statusbar, clear prompt state, wait for notify call"""
75-
self.wait_for_request_or_notify()
7676
self.in_prompt=False
7777
self.in_confirm=False
7878
self.prompt=''
@@ -89,30 +89,23 @@ def current_line(self):
8989
returnself._message
9090
returnself.permanent_text
9191

92-
defwait_for_request_or_notify(self):
93-
try:
94-
r=self.request_or_notify_queue.get(True,1)
95-
exceptQueue.Empty:
96-
raiseException('Main thread blocked because task thread not calling back')
97-
returnr
98-
99-
# interaction interface - should be called from other threads
92+
# interaction interface - should be called from other greenlets
10093
defnotify(self,msg,n=3):
94+
self.request_greenlet=greenlet.getcurrent()
10195
self.message_time=n
10296
self.message(msg)
103-
self.request_or_notify_queue.put(msg)
104-
# below Really ought to be called from threads other than the mainloop because they block
97+
self.main_greenlet.switch(msg)
98+
99+
# below Really ought to be called from greenlets other than main because they block
105100
defconfirm(self,q):
106101
"""Expected to return True or False, given question prompt q"""
102+
self.request_greenlet=greenlet.getcurrent()
107103
self.prompt=q
108104
self.in_confirm=True
109-
self.request_or_notify_queue.put(q)
110-
returnself.response_queue.get()
105+
returnself.main_greenlet.switch(q)
111106
deffile_prompt(self,s):
112107
"""Expected to return a file name, given """
108+
self.request_greenlet=greenlet.getcurrent()
113109
self.prompt=s.replace('Esc','Tab')
114110
self.in_prompt=True
115-
self.request_or_notify_queue.put(s)
116-
r=self.response_queue.get()
117-
returnr
118-
111+
returnself.main_greenlet.switch(s)

‎bpython/curtsiesfrontend/repl.py‎

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
importlogging
55
importcode
66
importthreading
7+
importgreenlet
78
importsubprocess
89
importtempfile
910

@@ -60,6 +61,9 @@ def process_event(self, e):
6061
#TODO EOF on ctrl-d
6162
elifisinstance(e,events.SigIntEvent):
6263
self.coderunner.sigint_happened=True
64+
self.has_focus=False
65+
self.current_line=''
66+
self.cursor_offset_in_line=0
6367
self.repl.run_code_and_maybe_finish()
6468
else:# add normal character
6569
logging.debug('adding normal char %r to current line',e)
@@ -203,7 +207,8 @@ def start_background_tasks(self):
203207
t.start()
204208

205209
defimportcompletion_thread(self):
206-
"""quick tasks we want to do bits of during downtime"""
210+
"""task that should run on startup in the background"""
211+
#TODO use locks or something to avoid error on import completion right at startup
207212
whileimportcompletion.find_coroutine():# returns None when fully initialized
208213
pass
209214

@@ -292,18 +297,12 @@ def process_event(self, e):
292297
self.undo()
293298
self.update_completion()
294299
elifeinkey_dispatch[self.config.save_key]:# ctrl-s for save
295-
t=threading.Thread(target=self.write2file)
296-
t.daemon=True
297-
logging.debug('starting write2file thread')
298-
t.start()
299-
self.interact.wait_for_request_or_notify()
300+
g=greenlet.greenlet(self.write2file)
301+
g.switch()
300302
# F8 for pastebin
301303
elifeinkey_dispatch[self.config.pastebin_key]:
302-
t=threading.Thread(target=self.pastebin)
303-
t.daemon=True
304-
logging.debug('starting pastebin thread')
305-
t.start()
306-
self.interact.wait_for_request_or_notify()
304+
g=greenlet.greenlet(self.pastebin)
305+
g.switch()
307306
elifeinkey_dispatch[self.config.external_editor_key]:
308307
self.send_to_external_editor()
309308
#TODO add PAD keys hack as in bpython.cli
@@ -482,6 +481,8 @@ def run_code_and_maybe_finish(self, for_code=None):
482481
iferr:
483482
indent=0
484483

484+
#TODO This should be printed ABOVE the error that just happened instead
485+
# or maybe just thrown away and not shown
485486
ifself.current_stdouterr_line:
486487
self.display_lines.extend(paint.display_linize(self.current_stdouterr_line,self.width))
487488
self.current_stdouterr_line=''

‎setup.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ def initialize_options(self):
153153
'pygments'
154154
],
155155
extras_require= {
156-
'curtsies': ['curtsies>=0.0.24'],
156+
'curtsies': ['curtsies>=0.0.24','greenlet'],
157157
'urwid' : ['urwid']
158158
},
159159
tests_require= ['mock'],

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2026 Movatter.jp