3
3
import time
4
4
import heapq
5
5
import asyncio
6
+ import logging
6
7
import traceback
7
8
import collections
8
9
9
- import logging
10
-
11
10
from bakkesmod import cvarManager , gameWrapper
12
11
13
- __all__ = [" BMEventLoop" , " BMEventLoopPolicy" ]
12
+ __all__ = [' BMEventLoop' , ' BMEventLoopPolicy' ]
14
13
15
14
# Name the logger after the package.
16
- logger = logging .getLogger (__package__ )
15
+ _logger = logging .getLogger (__package__ )
17
16
18
17
# Maximum timeout passed to select to avoid OS limitations
19
- MAXIMUM_SELECT_TIMEOUT = 24 * 3600
18
+ _MAXIMUM_SELECT_TIMEOUT = 24 * 3600
20
19
21
20
22
21
class BMEventLoop (asyncio .AbstractEventLoop ):
@@ -32,9 +31,9 @@ def __init__(self):
32
31
33
32
def __repr__ (self ):
34
33
return (
35
- f' <{ self .__class__ .__name__ } running={ self .is_running ()} '
36
- f' closed={ self .is_closed ()} idle={ self .is_idle ()} '
37
- f' debug={ self .get_debug ()} >'
34
+ f" <{ self .__class__ .__name__ } running={ self .is_running ()} "
35
+ f" closed={ self .is_closed ()} idle={ self .is_idle ()} "
36
+ f" debug={ self .get_debug ()} >"
38
37
)
39
38
40
39
def set_debug (self , debug ):
@@ -60,14 +59,14 @@ def _debug_log(self, text):
60
59
def _check_closed (self ):
61
60
"""Throws runtime error if the event is closed"""
62
61
if self ._closed :
63
- raise RuntimeError (' Event loop is closed' )
62
+ raise RuntimeError (" Event loop is closed" )
64
63
65
64
def _wakeup (self ):
66
65
"""Will wake up the idle event loop."""
67
66
self ._check_closed ()
68
67
if not self .is_idle ():
69
- raise RuntimeError (' Event loop is not idle' )
70
- self ._debug_log (' resume event loop' )
68
+ raise RuntimeError (" Event loop is not idle" )
69
+ self ._debug_log (" resume event loop" )
71
70
gameWrapper .SetTimeout (lambda gw : self ._run_once (), 0 )
72
71
73
72
def _timer_handle_cancelled (self , handle ):
@@ -80,20 +79,20 @@ def _run_once(self):
80
79
"""Run one full iteration of the event loop.
81
80
82
81
This calls all currently ready callbacks, schedules the
83
- resulting callbacks, and finally schedules ' call_later'
82
+ resulting callbacks, and finally schedules " call_later"
84
83
callbacks.
85
84
"""
86
85
if self ._stopping :
87
86
self ._running = False
88
- self ._debug_log (' stopped event loop' )
87
+ self ._debug_log (" stopped event loop" )
89
88
return
90
89
91
- self ._debug_log (f' _scheduled={ self ._scheduled } ' )
90
+ self ._debug_log (f" _scheduled={ self ._scheduled } " )
92
91
93
92
# Remove delayed calls that were cancelled from head of queue.
94
93
while self ._scheduled and self ._scheduled [0 ]._cancelled :
95
94
handle = heapq .heappop (self ._scheduled )
96
- self ._debug_log (f' cancelled handle={ handle } ' )
95
+ self ._debug_log (f" cancelled handle={ handle } " )
97
96
handle ._scheduled = False
98
97
99
98
timeout = None
@@ -102,82 +101,83 @@ def _run_once(self):
102
101
elif self ._scheduled :
103
102
# Compute the desired timeout.
104
103
when = self ._scheduled [0 ]._when
105
- timeout = min (max (0 , when - self .time ()), MAXIMUM_SELECT_TIMEOUT )
104
+ timeout = min (max (0 , when - self .time ()), _MAXIMUM_SELECT_TIMEOUT )
106
105
107
106
# Handle 'later' callbacks that are ready.
108
107
end_time = self .time () + self ._clock_resolution
109
108
while self ._scheduled :
110
109
handle = self ._scheduled [0 ]
111
- self ._debug_log (f' _when={ handle ._when } >= end_time={ end_time } ' )
110
+ self ._debug_log (f" _when={ handle ._when } >= end_time={ end_time } " )
112
111
if handle ._when >= end_time :
113
112
break
114
113
handle = heapq .heappop (self ._scheduled )
115
114
handle ._scheduled = False
116
115
self ._ready .append (handle )
117
116
118
- self ._debug_log (f' _ready={ self ._ready } ' )
117
+ self ._debug_log (f" _ready={ self ._ready } " )
119
118
120
119
# Call the callbacks that are ready.
121
120
ntodo = len (self ._ready )
122
121
for i in range (ntodo ):
123
122
handle = self ._ready .popleft ()
124
123
if handle ._cancelled :
125
- self ._debug_log (f' cancelled handle={ handle } ' )
124
+ self ._debug_log (f" cancelled handle={ handle } " )
126
125
continue
127
- self ._debug_log (f' run handle={ handle } ' )
126
+ self ._debug_log (f" run handle={ handle } " )
128
127
handle ._run ()
129
128
handle = None
130
129
131
130
if timeout is not None :
132
- self ._debug_log (f'next tick in { timeout } seconds' )
133
- gameWrapper .SetTimeout (lambda gw : self ._run_once (), timeout )
131
+ # self._debug_log(f"next tick in {timeout} seconds")
132
+ # gameWrapper.SetTimeout(lambda gw: self._run_once(), timeout)
133
+ gameWrapper .SetTimeout (lambda gw : self ._run_once (), max (timeout , 1 ))
134
134
else :
135
- self ._debug_log (' pause event loop' )
135
+ self ._debug_log (" pause event loop" )
136
136
self ._idle = True
137
137
138
138
def start (self ):
139
139
"""Run the event loop until stop() is called.
140
140
This function is non blocking."""
141
- self ._debug_log (' start' )
141
+ self ._debug_log (" start" )
142
142
self ._check_closed ()
143
143
if self .is_running ():
144
- raise RuntimeError (' This event loop is already running' )
144
+ raise RuntimeError (" This event loop is already running" )
145
145
self ._running = True
146
- self ._debug_log (' started event loop' )
146
+ self ._debug_log (" started event loop" )
147
147
self ._run_once ()
148
148
149
149
def run_forever (self ):
150
150
"""Run the event loop until stop() is called."""
151
- self ._debug_log (' run_forever' )
152
- raise NotImplementedError (' run_forever' )
151
+ self ._debug_log (" run_forever" )
152
+ raise NotImplementedError (" run_forever" )
153
153
154
154
def run_until_complete (self , future ):
155
155
"""Run the event loop until a Future is done."""
156
- self ._debug_log (f' run_until_complete, future={ future } ' )
157
- raise NotImplementedError (f' run_until_complete, future={ future } ' )
156
+ self ._debug_log (f" run_until_complete, future={ future } " )
157
+ raise NotImplementedError (f" run_until_complete, future={ future } " )
158
158
159
159
def is_running (self ):
160
160
"""Return whether the event loop is currently running."""
161
- self ._debug_log (' is_running' )
161
+ self ._debug_log (" is_running" )
162
162
return self ._running
163
163
164
164
def is_closed (self ):
165
165
"""Returns True if the event loop was closed."""
166
- self ._debug_log (' is_closed' )
166
+ self ._debug_log (" is_closed" )
167
167
return self ._closed
168
168
169
169
def is_idle (self ):
170
170
"""Returns True if the event loop is idle."""
171
- self ._debug_log (' is_idle' )
171
+ self ._debug_log (" is_idle" )
172
172
return self ._idle
173
173
174
174
def stop (self ):
175
175
"""Stop running the event loop.
176
176
177
- Every callback already scheduled will still run. This simply informs
177
+ Every callback already scheduled will still run. This simply informs
178
178
run_forever to stop looping after a complete iteration.
179
179
"""
180
- self ._debug_log (' stop' )
180
+ self ._debug_log (" stop" )
181
181
self ._stopping = True
182
182
183
183
def close (self ):
@@ -188,7 +188,7 @@ def close(self):
188
188
189
189
The event loop must not be running.
190
190
"""
191
- self ._debug_log (' close' )
191
+ self ._debug_log (" close" )
192
192
if self .is_running ():
193
193
raise RuntimeError ("Cannot close a running event loop" )
194
194
if self ._closed :
@@ -199,8 +199,8 @@ def close(self):
199
199
200
200
async def shutdown_asyncgens (self ):
201
201
"""Shutdown all active asynchronous generators."""
202
- self ._debug_log (' shutdown_asyncgens' )
203
- # We don' t have any asynchronous generators.
202
+ self ._debug_log (" shutdown_asyncgens" )
203
+ # We don" t have any asynchronous generators.
204
204
205
205
def call_exception_handler (self , context ):
206
206
"""Call the current event loop's exception handler.
@@ -224,10 +224,10 @@ def call_exception_handler(self, context):
224
224
For custom exception handling, use the
225
225
`set_exception_handler()` method.
226
226
"""
227
- self ._debug_log (f' call_exception_handler, context={ context } ' )
227
+ self ._debug_log (f" call_exception_handler, context={ context } " )
228
228
message = context .get ('message' )
229
229
if not message :
230
- message = ' Unhandled exception in event loop'
230
+ message = " Unhandled exception in event loop"
231
231
232
232
exception = context .get ('exception' )
233
233
if exception is not None :
@@ -241,19 +241,19 @@ def call_exception_handler(self, context):
241
241
continue
242
242
value = context [key ]
243
243
if key == 'source_traceback' :
244
- tb = '' .join (traceback .format_list (value ))
245
- value = ' Object created at (most recent call last):\n '
244
+ tb = "" .join (traceback .format_list (value ))
245
+ value = " Object created at (most recent call last):\n "
246
246
value += tb .rstrip ()
247
247
elif key == 'handle_traceback' :
248
- tb = '' .join (traceback .format_list (value ))
249
- value = ' Handle created at (most recent call last):\n '
248
+ tb = "" .join (traceback .format_list (value ))
249
+ value = " Handle created at (most recent call last):\n "
250
250
value += tb .rstrip ()
251
251
else :
252
252
value = repr (value )
253
- log_lines .append (f'{ key } : { value } ' )
254
-
255
- logger .error ('\n ' .join (log_lines ), exc_info = exc_info )
253
+ log_lines .append (f"{ key } : { value } " )
256
254
255
+ _logger .error ("\n " .join (log_lines ), exc_info = exc_info )
256
+ # Logger writes to stderr, so we steal it.
257
257
sys .stderr .seek (0 )
258
258
for line in sys .stderr .read ().split ('\n ' ):
259
259
cvarManager .log (f"[async] ERROR: { line } " )
@@ -271,8 +271,8 @@ def call_soon(self, callback, *args, context=None):
271
271
Any positional arguments after the callback will be passed to
272
272
the callback when it is called.
273
273
"""
274
- self ._debug_log (f' call_soon, callback={ callback } , args={ args } , '
275
- ' context={context}' )
274
+ self ._debug_log (f" call_soon, callback={ callback } , args={ args } , "
275
+ f" context={ context } " )
276
276
self ._check_closed ()
277
277
handle = asyncio .Handle (callback , args , self , context )
278
278
self ._ready .append (handle )
@@ -298,8 +298,8 @@ def call_later(self, delay, callback, *args, context=None):
298
298
Any positional arguments after the callback will be passed to
299
299
the callback when it is called.
300
300
"""
301
- self ._debug_log (f' call_later, delay={ delay } , callback={ callback } , '
302
- ' args={args}, context={context}' )
301
+ self ._debug_log (f" call_later, delay={ delay } , callback={ callback } , "
302
+ f" args={ args } , context={ context } " )
303
303
return self .call_at (self .time () + delay , callback , * args ,
304
304
context = context )
305
305
@@ -308,8 +308,8 @@ def call_at(self, when, callback, *args, context=None):
308
308
309
309
Absolute time corresponds to the event loop's time() method.
310
310
"""
311
- self ._debug_log (f' call_at, when={ when } , callback={ callback } , '
312
- ' args={args}, context={context}' )
311
+ self ._debug_log (f" call_at, when={ when } , callback={ callback } , "
312
+ f" args={ args } , context={ context } " )
313
313
self ._check_closed ()
314
314
timer = asyncio .TimerHandle (when , callback , args , self , context )
315
315
heapq .heappush (self ._scheduled , timer )
@@ -325,13 +325,13 @@ def create_task(self, coro):
325
325
326
326
Return a task object.
327
327
"""
328
- self ._debug_log (f' create_task, coro={ coro } ' )
328
+ self ._debug_log (f" create_task, coro={ coro } " )
329
329
self ._check_closed ()
330
330
return asyncio .Task (coro , loop = self )
331
331
332
332
def create_future (self ):
333
333
"""Create a Future object attached to the loop."""
334
- self ._debug_log (' create_future' )
334
+ self ._debug_log (" create_future" )
335
335
return asyncio .Future (loop = self )
336
336
337
337
0 commit comments